blob: bafb65389562c3724171bf1ef7a7b2ad6d877234 [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 Sharmaa144c2e2012-11-26 10:52:57 +053053/* AVI header and aspect ratio */
54#define HDMI_AVI_VERSION 0x02
55#define HDMI_AVI_LENGTH 0x0D
56#define AVI_PIC_ASPECT_RATIO_16_9 (2 << 4)
57#define AVI_SAME_AS_PIC_ASPECT_RATIO 8
58
59/* AUI header info */
60#define HDMI_AUI_VERSION 0x01
61#define HDMI_AUI_LENGTH 0x0A
62
63/* HDMI infoframe to configure HDMI out packet header, AUI and AVI */
64enum HDMI_PACKET_TYPE {
65 /* refer to Table 5-8 Packet Type in HDMI specification v1.4a */
66 /* InfoFrame packet type */
67 HDMI_PACKET_TYPE_INFOFRAME = 0x80,
68 /* Vendor-Specific InfoFrame */
69 HDMI_PACKET_TYPE_VSI = HDMI_PACKET_TYPE_INFOFRAME + 1,
70 /* Auxiliary Video information InfoFrame */
71 HDMI_PACKET_TYPE_AVI = HDMI_PACKET_TYPE_INFOFRAME + 2,
72 /* Audio information InfoFrame */
73 HDMI_PACKET_TYPE_AUI = HDMI_PACKET_TYPE_INFOFRAME + 4
74};
75
Rahul Sharma5a325072012-10-04 20:48:54 +053076enum hdmi_type {
77 HDMI_TYPE13,
78 HDMI_TYPE14,
79};
80
Joonyoung Shim590f4182012-03-16 18:47:14 +090081struct hdmi_resources {
82 struct clk *hdmi;
83 struct clk *sclk_hdmi;
84 struct clk *sclk_pixel;
85 struct clk *sclk_hdmiphy;
86 struct clk *hdmiphy;
87 struct regulator_bulk_data *regul_bulk;
88 int regul_count;
89};
90
91struct hdmi_context {
92 struct device *dev;
93 struct drm_device *drm_dev;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +090094 bool hpd;
95 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +090096 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +090097 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +090098
Joonyoung Shim590f4182012-03-16 18:47:14 +090099 void __iomem *regs;
Inki Dae1055b392012-10-19 17:37:35 +0900100 void *parent_ctx;
Tomasz Stanislawski07c8bdd2012-10-04 20:48:45 +0530101 int external_irq;
102 int internal_irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900103
104 struct i2c_client *ddc_port;
105 struct i2c_client *hdmiphy_port;
106
107 /* current hdmiphy conf index */
108 int cur_conf;
109
110 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900111
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530112 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530113
114 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900115};
116
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900117/* HDMI Version 1.3 */
118static const u8 hdmiphy_v13_conf27[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900119 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
120 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
121 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
122 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
123};
124
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900125static const u8 hdmiphy_v13_conf27_027[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900126 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
127 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
128 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
129 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
130};
131
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900132static const u8 hdmiphy_v13_conf74_175[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900133 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
134 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
135 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
136 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
137};
138
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900139static const u8 hdmiphy_v13_conf74_25[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900140 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
141 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
142 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
143 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
144};
145
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900146static const u8 hdmiphy_v13_conf148_5[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900147 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
148 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
149 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
150 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
151};
152
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900153struct hdmi_v13_tg_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900154 u8 cmd;
155 u8 h_fsz_l;
156 u8 h_fsz_h;
157 u8 hact_st_l;
158 u8 hact_st_h;
159 u8 hact_sz_l;
160 u8 hact_sz_h;
161 u8 v_fsz_l;
162 u8 v_fsz_h;
163 u8 vsync_l;
164 u8 vsync_h;
165 u8 vsync2_l;
166 u8 vsync2_h;
167 u8 vact_st_l;
168 u8 vact_st_h;
169 u8 vact_sz_l;
170 u8 vact_sz_h;
171 u8 field_chg_l;
172 u8 field_chg_h;
173 u8 vact_st2_l;
174 u8 vact_st2_h;
175 u8 vsync_top_hdmi_l;
176 u8 vsync_top_hdmi_h;
177 u8 vsync_bot_hdmi_l;
178 u8 vsync_bot_hdmi_h;
179 u8 field_top_hdmi_l;
180 u8 field_top_hdmi_h;
181 u8 field_bot_hdmi_l;
182 u8 field_bot_hdmi_h;
183};
184
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900185struct hdmi_v13_core_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900186 u8 h_blank[2];
187 u8 v_blank[3];
188 u8 h_v_line[3];
189 u8 vsync_pol[1];
190 u8 int_pro_mode[1];
191 u8 v_blank_f[3];
192 u8 h_sync_gen[3];
193 u8 v_sync_gen1[3];
194 u8 v_sync_gen2[3];
195 u8 v_sync_gen3[3];
196};
197
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900198struct hdmi_v13_preset_conf {
199 struct hdmi_v13_core_regs core;
200 struct hdmi_v13_tg_regs tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900201};
202
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900203struct hdmi_v13_conf {
204 int width;
205 int height;
206 int vrefresh;
207 bool interlace;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530208 int cea_video_id;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900209 const u8 *hdmiphy_data;
210 const struct hdmi_v13_preset_conf *conf;
211};
212
213static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900214 .core = {
215 .h_blank = {0x8a, 0x00},
216 .v_blank = {0x0d, 0x6a, 0x01},
217 .h_v_line = {0x0d, 0xa2, 0x35},
218 .vsync_pol = {0x01},
219 .int_pro_mode = {0x00},
220 .v_blank_f = {0x00, 0x00, 0x00},
221 .h_sync_gen = {0x0e, 0x30, 0x11},
222 .v_sync_gen1 = {0x0f, 0x90, 0x00},
223 /* other don't care */
224 },
225 .tg = {
226 0x00, /* cmd */
227 0x5a, 0x03, /* h_fsz */
228 0x8a, 0x00, 0xd0, 0x02, /* hact */
229 0x0d, 0x02, /* v_fsz */
230 0x01, 0x00, 0x33, 0x02, /* vsync */
231 0x2d, 0x00, 0xe0, 0x01, /* vact */
232 0x33, 0x02, /* field_chg */
233 0x49, 0x02, /* vact_st2 */
234 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
235 0x01, 0x00, 0x33, 0x02, /* field top/bot */
236 },
237};
238
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900239static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900240 .core = {
241 .h_blank = {0x72, 0x01},
242 .v_blank = {0xee, 0xf2, 0x00},
243 .h_v_line = {0xee, 0x22, 0x67},
244 .vsync_pol = {0x00},
245 .int_pro_mode = {0x00},
246 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
247 .h_sync_gen = {0x6c, 0x50, 0x02},
248 .v_sync_gen1 = {0x0a, 0x50, 0x00},
249 .v_sync_gen2 = {0x01, 0x10, 0x00},
250 .v_sync_gen3 = {0x01, 0x10, 0x00},
251 /* other don't care */
252 },
253 .tg = {
254 0x00, /* cmd */
255 0x72, 0x06, /* h_fsz */
256 0x71, 0x01, 0x01, 0x05, /* hact */
257 0xee, 0x02, /* v_fsz */
258 0x01, 0x00, 0x33, 0x02, /* vsync */
259 0x1e, 0x00, 0xd0, 0x02, /* vact */
260 0x33, 0x02, /* field_chg */
261 0x49, 0x02, /* vact_st2 */
262 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
263 0x01, 0x00, 0x33, 0x02, /* field top/bot */
264 },
265};
266
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900267static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900268 .core = {
269 .h_blank = {0xd0, 0x02},
270 .v_blank = {0x32, 0xB2, 0x00},
271 .h_v_line = {0x65, 0x04, 0xa5},
272 .vsync_pol = {0x00},
273 .int_pro_mode = {0x01},
274 .v_blank_f = {0x49, 0x2A, 0x23},
275 .h_sync_gen = {0x0E, 0xEA, 0x08},
276 .v_sync_gen1 = {0x07, 0x20, 0x00},
277 .v_sync_gen2 = {0x39, 0x42, 0x23},
278 .v_sync_gen3 = {0x38, 0x87, 0x73},
279 /* other don't care */
280 },
281 .tg = {
282 0x00, /* cmd */
283 0x50, 0x0A, /* h_fsz */
284 0xCF, 0x02, 0x81, 0x07, /* hact */
285 0x65, 0x04, /* v_fsz */
286 0x01, 0x00, 0x33, 0x02, /* vsync */
287 0x16, 0x00, 0x1c, 0x02, /* vact */
288 0x33, 0x02, /* field_chg */
289 0x49, 0x02, /* vact_st2 */
290 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
291 0x01, 0x00, 0x33, 0x02, /* field top/bot */
292 },
293};
294
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900295static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900296 .core = {
297 .h_blank = {0xd0, 0x02},
298 .v_blank = {0x65, 0x6c, 0x01},
299 .h_v_line = {0x65, 0x04, 0xa5},
300 .vsync_pol = {0x00},
301 .int_pro_mode = {0x00},
302 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
303 .h_sync_gen = {0x0e, 0xea, 0x08},
304 .v_sync_gen1 = {0x09, 0x40, 0x00},
305 .v_sync_gen2 = {0x01, 0x10, 0x00},
306 .v_sync_gen3 = {0x01, 0x10, 0x00},
307 /* other don't care */
308 },
309 .tg = {
310 0x00, /* cmd */
311 0x50, 0x0A, /* h_fsz */
312 0xCF, 0x02, 0x81, 0x07, /* hact */
313 0x65, 0x04, /* v_fsz */
314 0x01, 0x00, 0x33, 0x02, /* vsync */
315 0x2d, 0x00, 0x38, 0x04, /* vact */
316 0x33, 0x02, /* field_chg */
317 0x48, 0x02, /* vact_st2 */
318 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
319 0x01, 0x00, 0x33, 0x02, /* field top/bot */
320 },
321};
322
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900323static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900324 .core = {
325 .h_blank = {0x18, 0x01},
326 .v_blank = {0x32, 0xB2, 0x00},
327 .h_v_line = {0x65, 0x84, 0x89},
328 .vsync_pol = {0x00},
329 .int_pro_mode = {0x01},
330 .v_blank_f = {0x49, 0x2A, 0x23},
331 .h_sync_gen = {0x56, 0x08, 0x02},
332 .v_sync_gen1 = {0x07, 0x20, 0x00},
333 .v_sync_gen2 = {0x39, 0x42, 0x23},
334 .v_sync_gen3 = {0xa4, 0x44, 0x4a},
335 /* other don't care */
336 },
337 .tg = {
338 0x00, /* cmd */
339 0x98, 0x08, /* h_fsz */
340 0x17, 0x01, 0x81, 0x07, /* hact */
341 0x65, 0x04, /* v_fsz */
342 0x01, 0x00, 0x33, 0x02, /* vsync */
343 0x16, 0x00, 0x1c, 0x02, /* vact */
344 0x33, 0x02, /* field_chg */
345 0x49, 0x02, /* vact_st2 */
346 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
347 0x01, 0x00, 0x33, 0x02, /* field top/bot */
348 },
349};
350
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900351static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900352 .core = {
353 .h_blank = {0x18, 0x01},
354 .v_blank = {0x65, 0x6c, 0x01},
355 .h_v_line = {0x65, 0x84, 0x89},
356 .vsync_pol = {0x00},
357 .int_pro_mode = {0x00},
358 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
359 .h_sync_gen = {0x56, 0x08, 0x02},
360 .v_sync_gen1 = {0x09, 0x40, 0x00},
361 .v_sync_gen2 = {0x01, 0x10, 0x00},
362 .v_sync_gen3 = {0x01, 0x10, 0x00},
363 /* other don't care */
364 },
365 .tg = {
366 0x00, /* cmd */
367 0x98, 0x08, /* h_fsz */
368 0x17, 0x01, 0x81, 0x07, /* hact */
369 0x65, 0x04, /* v_fsz */
370 0x01, 0x00, 0x33, 0x02, /* vsync */
371 0x2d, 0x00, 0x38, 0x04, /* vact */
372 0x33, 0x02, /* field_chg */
373 0x48, 0x02, /* vact_st2 */
374 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
375 0x01, 0x00, 0x33, 0x02, /* field top/bot */
376 },
377};
378
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900379static const struct hdmi_v13_conf hdmi_v13_confs[] = {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530380 { 1280, 720, 60, false, 4, hdmiphy_v13_conf74_25,
381 &hdmi_v13_conf_720p60 },
382 { 1280, 720, 50, false, 19, hdmiphy_v13_conf74_25,
383 &hdmi_v13_conf_720p60 },
384 { 720, 480, 60, false, 3, hdmiphy_v13_conf27_027,
385 &hdmi_v13_conf_480p },
386 { 1920, 1080, 50, true, 20, hdmiphy_v13_conf74_25,
387 &hdmi_v13_conf_1080i50 },
388 { 1920, 1080, 50, false, 31, hdmiphy_v13_conf148_5,
389 &hdmi_v13_conf_1080p50 },
390 { 1920, 1080, 60, true, 5, hdmiphy_v13_conf74_25,
391 &hdmi_v13_conf_1080i60 },
392 { 1920, 1080, 60, false, 16, hdmiphy_v13_conf148_5,
393 &hdmi_v13_conf_1080p60 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900394};
395
396/* HDMI Version 1.4 */
397static const u8 hdmiphy_conf27_027[32] = {
398 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
399 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
400 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
401 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
402};
403
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900404static const u8 hdmiphy_conf74_176[32] = {
405 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08,
406 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80,
407 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
408 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
409};
410
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900411static const u8 hdmiphy_conf74_25[32] = {
412 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
413 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
414 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
415 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
416};
417
418static const u8 hdmiphy_conf148_5[32] = {
419 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
420 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
421 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
422 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
423};
424
425struct hdmi_tg_regs {
426 u8 cmd;
427 u8 h_fsz_l;
428 u8 h_fsz_h;
429 u8 hact_st_l;
430 u8 hact_st_h;
431 u8 hact_sz_l;
432 u8 hact_sz_h;
433 u8 v_fsz_l;
434 u8 v_fsz_h;
435 u8 vsync_l;
436 u8 vsync_h;
437 u8 vsync2_l;
438 u8 vsync2_h;
439 u8 vact_st_l;
440 u8 vact_st_h;
441 u8 vact_sz_l;
442 u8 vact_sz_h;
443 u8 field_chg_l;
444 u8 field_chg_h;
445 u8 vact_st2_l;
446 u8 vact_st2_h;
447 u8 vact_st3_l;
448 u8 vact_st3_h;
449 u8 vact_st4_l;
450 u8 vact_st4_h;
451 u8 vsync_top_hdmi_l;
452 u8 vsync_top_hdmi_h;
453 u8 vsync_bot_hdmi_l;
454 u8 vsync_bot_hdmi_h;
455 u8 field_top_hdmi_l;
456 u8 field_top_hdmi_h;
457 u8 field_bot_hdmi_l;
458 u8 field_bot_hdmi_h;
459 u8 tg_3d;
460};
461
462struct hdmi_core_regs {
463 u8 h_blank[2];
464 u8 v2_blank[2];
465 u8 v1_blank[2];
466 u8 v_line[2];
467 u8 h_line[2];
468 u8 hsync_pol[1];
469 u8 vsync_pol[1];
470 u8 int_pro_mode[1];
471 u8 v_blank_f0[2];
472 u8 v_blank_f1[2];
473 u8 h_sync_start[2];
474 u8 h_sync_end[2];
475 u8 v_sync_line_bef_2[2];
476 u8 v_sync_line_bef_1[2];
477 u8 v_sync_line_aft_2[2];
478 u8 v_sync_line_aft_1[2];
479 u8 v_sync_line_aft_pxl_2[2];
480 u8 v_sync_line_aft_pxl_1[2];
481 u8 v_blank_f2[2]; /* for 3D mode */
482 u8 v_blank_f3[2]; /* for 3D mode */
483 u8 v_blank_f4[2]; /* for 3D mode */
484 u8 v_blank_f5[2]; /* for 3D mode */
485 u8 v_sync_line_aft_3[2];
486 u8 v_sync_line_aft_4[2];
487 u8 v_sync_line_aft_5[2];
488 u8 v_sync_line_aft_6[2];
489 u8 v_sync_line_aft_pxl_3[2];
490 u8 v_sync_line_aft_pxl_4[2];
491 u8 v_sync_line_aft_pxl_5[2];
492 u8 v_sync_line_aft_pxl_6[2];
493 u8 vact_space_1[2];
494 u8 vact_space_2[2];
495 u8 vact_space_3[2];
496 u8 vact_space_4[2];
497 u8 vact_space_5[2];
498 u8 vact_space_6[2];
499};
500
501struct hdmi_preset_conf {
502 struct hdmi_core_regs core;
503 struct hdmi_tg_regs tg;
504};
505
506struct hdmi_conf {
507 int width;
508 int height;
509 int vrefresh;
510 bool interlace;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530511 int cea_video_id;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900512 const u8 *hdmiphy_data;
513 const struct hdmi_preset_conf *conf;
514};
515
516static const struct hdmi_preset_conf hdmi_conf_480p60 = {
517 .core = {
518 .h_blank = {0x8a, 0x00},
519 .v2_blank = {0x0d, 0x02},
520 .v1_blank = {0x2d, 0x00},
521 .v_line = {0x0d, 0x02},
522 .h_line = {0x5a, 0x03},
523 .hsync_pol = {0x01},
524 .vsync_pol = {0x01},
525 .int_pro_mode = {0x00},
526 .v_blank_f0 = {0xff, 0xff},
527 .v_blank_f1 = {0xff, 0xff},
528 .h_sync_start = {0x0e, 0x00},
529 .h_sync_end = {0x4c, 0x00},
530 .v_sync_line_bef_2 = {0x0f, 0x00},
531 .v_sync_line_bef_1 = {0x09, 0x00},
532 .v_sync_line_aft_2 = {0xff, 0xff},
533 .v_sync_line_aft_1 = {0xff, 0xff},
534 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
535 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
536 .v_blank_f2 = {0xff, 0xff},
537 .v_blank_f3 = {0xff, 0xff},
538 .v_blank_f4 = {0xff, 0xff},
539 .v_blank_f5 = {0xff, 0xff},
540 .v_sync_line_aft_3 = {0xff, 0xff},
541 .v_sync_line_aft_4 = {0xff, 0xff},
542 .v_sync_line_aft_5 = {0xff, 0xff},
543 .v_sync_line_aft_6 = {0xff, 0xff},
544 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
545 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
546 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
547 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
548 .vact_space_1 = {0xff, 0xff},
549 .vact_space_2 = {0xff, 0xff},
550 .vact_space_3 = {0xff, 0xff},
551 .vact_space_4 = {0xff, 0xff},
552 .vact_space_5 = {0xff, 0xff},
553 .vact_space_6 = {0xff, 0xff},
554 /* other don't care */
555 },
556 .tg = {
557 0x00, /* cmd */
558 0x5a, 0x03, /* h_fsz */
559 0x8a, 0x00, 0xd0, 0x02, /* hact */
560 0x0d, 0x02, /* v_fsz */
561 0x01, 0x00, 0x33, 0x02, /* vsync */
562 0x2d, 0x00, 0xe0, 0x01, /* vact */
563 0x33, 0x02, /* field_chg */
564 0x48, 0x02, /* vact_st2 */
565 0x00, 0x00, /* vact_st3 */
566 0x00, 0x00, /* vact_st4 */
567 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
568 0x01, 0x00, 0x33, 0x02, /* field top/bot */
569 0x00, /* 3d FP */
570 },
571};
572
573static const struct hdmi_preset_conf hdmi_conf_720p50 = {
574 .core = {
575 .h_blank = {0xbc, 0x02},
576 .v2_blank = {0xee, 0x02},
577 .v1_blank = {0x1e, 0x00},
578 .v_line = {0xee, 0x02},
579 .h_line = {0xbc, 0x07},
580 .hsync_pol = {0x00},
581 .vsync_pol = {0x00},
582 .int_pro_mode = {0x00},
583 .v_blank_f0 = {0xff, 0xff},
584 .v_blank_f1 = {0xff, 0xff},
585 .h_sync_start = {0xb6, 0x01},
586 .h_sync_end = {0xde, 0x01},
587 .v_sync_line_bef_2 = {0x0a, 0x00},
588 .v_sync_line_bef_1 = {0x05, 0x00},
589 .v_sync_line_aft_2 = {0xff, 0xff},
590 .v_sync_line_aft_1 = {0xff, 0xff},
591 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
592 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
593 .v_blank_f2 = {0xff, 0xff},
594 .v_blank_f3 = {0xff, 0xff},
595 .v_blank_f4 = {0xff, 0xff},
596 .v_blank_f5 = {0xff, 0xff},
597 .v_sync_line_aft_3 = {0xff, 0xff},
598 .v_sync_line_aft_4 = {0xff, 0xff},
599 .v_sync_line_aft_5 = {0xff, 0xff},
600 .v_sync_line_aft_6 = {0xff, 0xff},
601 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
602 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
603 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
604 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
605 .vact_space_1 = {0xff, 0xff},
606 .vact_space_2 = {0xff, 0xff},
607 .vact_space_3 = {0xff, 0xff},
608 .vact_space_4 = {0xff, 0xff},
609 .vact_space_5 = {0xff, 0xff},
610 .vact_space_6 = {0xff, 0xff},
611 /* other don't care */
612 },
613 .tg = {
614 0x00, /* cmd */
615 0xbc, 0x07, /* h_fsz */
616 0xbc, 0x02, 0x00, 0x05, /* hact */
617 0xee, 0x02, /* v_fsz */
618 0x01, 0x00, 0x33, 0x02, /* vsync */
619 0x1e, 0x00, 0xd0, 0x02, /* vact */
620 0x33, 0x02, /* field_chg */
621 0x48, 0x02, /* vact_st2 */
622 0x00, 0x00, /* vact_st3 */
623 0x00, 0x00, /* vact_st4 */
624 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
625 0x01, 0x00, 0x33, 0x02, /* field top/bot */
626 0x00, /* 3d FP */
627 },
628};
629
630static const struct hdmi_preset_conf hdmi_conf_720p60 = {
631 .core = {
632 .h_blank = {0x72, 0x01},
633 .v2_blank = {0xee, 0x02},
634 .v1_blank = {0x1e, 0x00},
635 .v_line = {0xee, 0x02},
636 .h_line = {0x72, 0x06},
637 .hsync_pol = {0x00},
638 .vsync_pol = {0x00},
639 .int_pro_mode = {0x00},
640 .v_blank_f0 = {0xff, 0xff},
641 .v_blank_f1 = {0xff, 0xff},
642 .h_sync_start = {0x6c, 0x00},
643 .h_sync_end = {0x94, 0x00},
644 .v_sync_line_bef_2 = {0x0a, 0x00},
645 .v_sync_line_bef_1 = {0x05, 0x00},
646 .v_sync_line_aft_2 = {0xff, 0xff},
647 .v_sync_line_aft_1 = {0xff, 0xff},
648 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
649 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
650 .v_blank_f2 = {0xff, 0xff},
651 .v_blank_f3 = {0xff, 0xff},
652 .v_blank_f4 = {0xff, 0xff},
653 .v_blank_f5 = {0xff, 0xff},
654 .v_sync_line_aft_3 = {0xff, 0xff},
655 .v_sync_line_aft_4 = {0xff, 0xff},
656 .v_sync_line_aft_5 = {0xff, 0xff},
657 .v_sync_line_aft_6 = {0xff, 0xff},
658 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
659 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
660 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
661 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
662 .vact_space_1 = {0xff, 0xff},
663 .vact_space_2 = {0xff, 0xff},
664 .vact_space_3 = {0xff, 0xff},
665 .vact_space_4 = {0xff, 0xff},
666 .vact_space_5 = {0xff, 0xff},
667 .vact_space_6 = {0xff, 0xff},
668 /* other don't care */
669 },
670 .tg = {
671 0x00, /* cmd */
672 0x72, 0x06, /* h_fsz */
673 0x72, 0x01, 0x00, 0x05, /* hact */
674 0xee, 0x02, /* v_fsz */
675 0x01, 0x00, 0x33, 0x02, /* vsync */
676 0x1e, 0x00, 0xd0, 0x02, /* vact */
677 0x33, 0x02, /* field_chg */
678 0x48, 0x02, /* vact_st2 */
679 0x00, 0x00, /* vact_st3 */
680 0x00, 0x00, /* vact_st4 */
681 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
682 0x01, 0x00, 0x33, 0x02, /* field top/bot */
683 0x00, /* 3d FP */
684 },
685};
686
687static const struct hdmi_preset_conf hdmi_conf_1080i50 = {
688 .core = {
689 .h_blank = {0xd0, 0x02},
690 .v2_blank = {0x32, 0x02},
691 .v1_blank = {0x16, 0x00},
692 .v_line = {0x65, 0x04},
693 .h_line = {0x50, 0x0a},
694 .hsync_pol = {0x00},
695 .vsync_pol = {0x00},
696 .int_pro_mode = {0x01},
697 .v_blank_f0 = {0x49, 0x02},
698 .v_blank_f1 = {0x65, 0x04},
699 .h_sync_start = {0x0e, 0x02},
700 .h_sync_end = {0x3a, 0x02},
701 .v_sync_line_bef_2 = {0x07, 0x00},
702 .v_sync_line_bef_1 = {0x02, 0x00},
703 .v_sync_line_aft_2 = {0x39, 0x02},
704 .v_sync_line_aft_1 = {0x34, 0x02},
705 .v_sync_line_aft_pxl_2 = {0x38, 0x07},
706 .v_sync_line_aft_pxl_1 = {0x38, 0x07},
707 .v_blank_f2 = {0xff, 0xff},
708 .v_blank_f3 = {0xff, 0xff},
709 .v_blank_f4 = {0xff, 0xff},
710 .v_blank_f5 = {0xff, 0xff},
711 .v_sync_line_aft_3 = {0xff, 0xff},
712 .v_sync_line_aft_4 = {0xff, 0xff},
713 .v_sync_line_aft_5 = {0xff, 0xff},
714 .v_sync_line_aft_6 = {0xff, 0xff},
715 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
716 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
717 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
718 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
719 .vact_space_1 = {0xff, 0xff},
720 .vact_space_2 = {0xff, 0xff},
721 .vact_space_3 = {0xff, 0xff},
722 .vact_space_4 = {0xff, 0xff},
723 .vact_space_5 = {0xff, 0xff},
724 .vact_space_6 = {0xff, 0xff},
725 /* other don't care */
726 },
727 .tg = {
728 0x00, /* cmd */
729 0x50, 0x0a, /* h_fsz */
730 0xd0, 0x02, 0x80, 0x07, /* hact */
731 0x65, 0x04, /* v_fsz */
732 0x01, 0x00, 0x33, 0x02, /* vsync */
733 0x16, 0x00, 0x1c, 0x02, /* vact */
734 0x33, 0x02, /* field_chg */
735 0x49, 0x02, /* vact_st2 */
736 0x00, 0x00, /* vact_st3 */
737 0x00, 0x00, /* vact_st4 */
738 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
739 0x01, 0x00, 0x33, 0x02, /* field top/bot */
740 0x00, /* 3d FP */
741 },
742};
743
744static const struct hdmi_preset_conf hdmi_conf_1080i60 = {
745 .core = {
746 .h_blank = {0x18, 0x01},
747 .v2_blank = {0x32, 0x02},
748 .v1_blank = {0x16, 0x00},
749 .v_line = {0x65, 0x04},
750 .h_line = {0x98, 0x08},
751 .hsync_pol = {0x00},
752 .vsync_pol = {0x00},
753 .int_pro_mode = {0x01},
754 .v_blank_f0 = {0x49, 0x02},
755 .v_blank_f1 = {0x65, 0x04},
756 .h_sync_start = {0x56, 0x00},
757 .h_sync_end = {0x82, 0x00},
758 .v_sync_line_bef_2 = {0x07, 0x00},
759 .v_sync_line_bef_1 = {0x02, 0x00},
760 .v_sync_line_aft_2 = {0x39, 0x02},
761 .v_sync_line_aft_1 = {0x34, 0x02},
762 .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
763 .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
764 .v_blank_f2 = {0xff, 0xff},
765 .v_blank_f3 = {0xff, 0xff},
766 .v_blank_f4 = {0xff, 0xff},
767 .v_blank_f5 = {0xff, 0xff},
768 .v_sync_line_aft_3 = {0xff, 0xff},
769 .v_sync_line_aft_4 = {0xff, 0xff},
770 .v_sync_line_aft_5 = {0xff, 0xff},
771 .v_sync_line_aft_6 = {0xff, 0xff},
772 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
773 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
774 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
775 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
776 .vact_space_1 = {0xff, 0xff},
777 .vact_space_2 = {0xff, 0xff},
778 .vact_space_3 = {0xff, 0xff},
779 .vact_space_4 = {0xff, 0xff},
780 .vact_space_5 = {0xff, 0xff},
781 .vact_space_6 = {0xff, 0xff},
782 /* other don't care */
783 },
784 .tg = {
785 0x00, /* cmd */
786 0x98, 0x08, /* h_fsz */
787 0x18, 0x01, 0x80, 0x07, /* hact */
788 0x65, 0x04, /* v_fsz */
789 0x01, 0x00, 0x33, 0x02, /* vsync */
790 0x16, 0x00, 0x1c, 0x02, /* vact */
791 0x33, 0x02, /* field_chg */
792 0x49, 0x02, /* vact_st2 */
793 0x00, 0x00, /* vact_st3 */
794 0x00, 0x00, /* vact_st4 */
795 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
796 0x01, 0x00, 0x33, 0x02, /* field top/bot */
797 0x00, /* 3d FP */
798 },
799};
800
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900801static const struct hdmi_preset_conf hdmi_conf_1080p30 = {
802 .core = {
803 .h_blank = {0x18, 0x01},
804 .v2_blank = {0x65, 0x04},
805 .v1_blank = {0x2d, 0x00},
806 .v_line = {0x65, 0x04},
807 .h_line = {0x98, 0x08},
808 .hsync_pol = {0x00},
809 .vsync_pol = {0x00},
810 .int_pro_mode = {0x00},
811 .v_blank_f0 = {0xff, 0xff},
812 .v_blank_f1 = {0xff, 0xff},
813 .h_sync_start = {0x56, 0x00},
814 .h_sync_end = {0x82, 0x00},
815 .v_sync_line_bef_2 = {0x09, 0x00},
816 .v_sync_line_bef_1 = {0x04, 0x00},
817 .v_sync_line_aft_2 = {0xff, 0xff},
818 .v_sync_line_aft_1 = {0xff, 0xff},
819 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
820 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
821 .v_blank_f2 = {0xff, 0xff},
822 .v_blank_f3 = {0xff, 0xff},
823 .v_blank_f4 = {0xff, 0xff},
824 .v_blank_f5 = {0xff, 0xff},
825 .v_sync_line_aft_3 = {0xff, 0xff},
826 .v_sync_line_aft_4 = {0xff, 0xff},
827 .v_sync_line_aft_5 = {0xff, 0xff},
828 .v_sync_line_aft_6 = {0xff, 0xff},
829 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
830 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
831 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
832 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
833 .vact_space_1 = {0xff, 0xff},
834 .vact_space_2 = {0xff, 0xff},
835 .vact_space_3 = {0xff, 0xff},
836 .vact_space_4 = {0xff, 0xff},
837 .vact_space_5 = {0xff, 0xff},
838 .vact_space_6 = {0xff, 0xff},
839 /* other don't care */
840 },
841 .tg = {
842 0x00, /* cmd */
843 0x98, 0x08, /* h_fsz */
844 0x18, 0x01, 0x80, 0x07, /* hact */
845 0x65, 0x04, /* v_fsz */
846 0x01, 0x00, 0x33, 0x02, /* vsync */
847 0x2d, 0x00, 0x38, 0x04, /* vact */
848 0x33, 0x02, /* field_chg */
849 0x48, 0x02, /* vact_st2 */
850 0x00, 0x00, /* vact_st3 */
851 0x00, 0x00, /* vact_st4 */
852 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
853 0x01, 0x00, 0x33, 0x02, /* field top/bot */
854 0x00, /* 3d FP */
855 },
856};
857
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900858static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
859 .core = {
860 .h_blank = {0xd0, 0x02},
861 .v2_blank = {0x65, 0x04},
862 .v1_blank = {0x2d, 0x00},
863 .v_line = {0x65, 0x04},
864 .h_line = {0x50, 0x0a},
865 .hsync_pol = {0x00},
866 .vsync_pol = {0x00},
867 .int_pro_mode = {0x00},
868 .v_blank_f0 = {0xff, 0xff},
869 .v_blank_f1 = {0xff, 0xff},
870 .h_sync_start = {0x0e, 0x02},
871 .h_sync_end = {0x3a, 0x02},
872 .v_sync_line_bef_2 = {0x09, 0x00},
873 .v_sync_line_bef_1 = {0x04, 0x00},
874 .v_sync_line_aft_2 = {0xff, 0xff},
875 .v_sync_line_aft_1 = {0xff, 0xff},
876 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
877 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
878 .v_blank_f2 = {0xff, 0xff},
879 .v_blank_f3 = {0xff, 0xff},
880 .v_blank_f4 = {0xff, 0xff},
881 .v_blank_f5 = {0xff, 0xff},
882 .v_sync_line_aft_3 = {0xff, 0xff},
883 .v_sync_line_aft_4 = {0xff, 0xff},
884 .v_sync_line_aft_5 = {0xff, 0xff},
885 .v_sync_line_aft_6 = {0xff, 0xff},
886 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
887 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
888 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
889 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
890 .vact_space_1 = {0xff, 0xff},
891 .vact_space_2 = {0xff, 0xff},
892 .vact_space_3 = {0xff, 0xff},
893 .vact_space_4 = {0xff, 0xff},
894 .vact_space_5 = {0xff, 0xff},
895 .vact_space_6 = {0xff, 0xff},
896 /* other don't care */
897 },
898 .tg = {
899 0x00, /* cmd */
900 0x50, 0x0a, /* h_fsz */
901 0xd0, 0x02, 0x80, 0x07, /* hact */
902 0x65, 0x04, /* v_fsz */
903 0x01, 0x00, 0x33, 0x02, /* vsync */
904 0x2d, 0x00, 0x38, 0x04, /* vact */
905 0x33, 0x02, /* field_chg */
906 0x48, 0x02, /* vact_st2 */
907 0x00, 0x00, /* vact_st3 */
908 0x00, 0x00, /* vact_st4 */
909 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
910 0x01, 0x00, 0x33, 0x02, /* field top/bot */
911 0x00, /* 3d FP */
912 },
913};
914
915static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
916 .core = {
917 .h_blank = {0x18, 0x01},
918 .v2_blank = {0x65, 0x04},
919 .v1_blank = {0x2d, 0x00},
920 .v_line = {0x65, 0x04},
921 .h_line = {0x98, 0x08},
922 .hsync_pol = {0x00},
923 .vsync_pol = {0x00},
924 .int_pro_mode = {0x00},
925 .v_blank_f0 = {0xff, 0xff},
926 .v_blank_f1 = {0xff, 0xff},
927 .h_sync_start = {0x56, 0x00},
928 .h_sync_end = {0x82, 0x00},
929 .v_sync_line_bef_2 = {0x09, 0x00},
930 .v_sync_line_bef_1 = {0x04, 0x00},
931 .v_sync_line_aft_2 = {0xff, 0xff},
932 .v_sync_line_aft_1 = {0xff, 0xff},
933 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
934 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
935 .v_blank_f2 = {0xff, 0xff},
936 .v_blank_f3 = {0xff, 0xff},
937 .v_blank_f4 = {0xff, 0xff},
938 .v_blank_f5 = {0xff, 0xff},
939 .v_sync_line_aft_3 = {0xff, 0xff},
940 .v_sync_line_aft_4 = {0xff, 0xff},
941 .v_sync_line_aft_5 = {0xff, 0xff},
942 .v_sync_line_aft_6 = {0xff, 0xff},
943 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
944 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
945 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
946 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
947 /* other don't care */
948 },
949 .tg = {
950 0x00, /* cmd */
951 0x98, 0x08, /* h_fsz */
952 0x18, 0x01, 0x80, 0x07, /* hact */
953 0x65, 0x04, /* v_fsz */
954 0x01, 0x00, 0x33, 0x02, /* vsync */
955 0x2d, 0x00, 0x38, 0x04, /* vact */
956 0x33, 0x02, /* field_chg */
957 0x48, 0x02, /* vact_st2 */
958 0x00, 0x00, /* vact_st3 */
959 0x00, 0x00, /* vact_st4 */
960 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
961 0x01, 0x00, 0x33, 0x02, /* field top/bot */
962 0x00, /* 3d FP */
963 },
964};
965
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900966static const struct hdmi_conf hdmi_confs[] = {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530967 { 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 },
968 { 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 },
969 { 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 },
970 { 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
971 { 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
972 { 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
973 { 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
974 { 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900975};
976
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530977struct hdmi_infoframe {
978 enum HDMI_PACKET_TYPE type;
979 u8 ver;
980 u8 len;
981};
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900982
983static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
984{
985 return readl(hdata->regs + reg_id);
986}
987
988static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
989 u32 reg_id, u8 value)
990{
991 writeb(value, hdata->regs + reg_id);
992}
993
994static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
995 u32 reg_id, u32 value, u32 mask)
996{
997 u32 old = readl(hdata->regs + reg_id);
998 value = (value & mask) | (old & ~mask);
999 writel(value, hdata->regs + reg_id);
1000}
1001
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001002static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001003{
1004#define DUMPREG(reg_id) \
1005 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
1006 readl(hdata->regs + reg_id))
1007 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
1008 DUMPREG(HDMI_INTC_FLAG);
1009 DUMPREG(HDMI_INTC_CON);
1010 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001011 DUMPREG(HDMI_V13_PHY_RSTOUT);
1012 DUMPREG(HDMI_V13_PHY_VPLL);
1013 DUMPREG(HDMI_V13_PHY_CMU);
1014 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001015
1016 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
1017 DUMPREG(HDMI_CON_0);
1018 DUMPREG(HDMI_CON_1);
1019 DUMPREG(HDMI_CON_2);
1020 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001021 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001022 DUMPREG(HDMI_STATUS_EN);
1023 DUMPREG(HDMI_HPD);
1024 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001025 DUMPREG(HDMI_V13_HPD_GEN);
1026 DUMPREG(HDMI_V13_DC_CONTROL);
1027 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001028
1029 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
1030 DUMPREG(HDMI_H_BLANK_0);
1031 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001032 DUMPREG(HDMI_V13_V_BLANK_0);
1033 DUMPREG(HDMI_V13_V_BLANK_1);
1034 DUMPREG(HDMI_V13_V_BLANK_2);
1035 DUMPREG(HDMI_V13_H_V_LINE_0);
1036 DUMPREG(HDMI_V13_H_V_LINE_1);
1037 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001038 DUMPREG(HDMI_VSYNC_POL);
1039 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001040 DUMPREG(HDMI_V13_V_BLANK_F_0);
1041 DUMPREG(HDMI_V13_V_BLANK_F_1);
1042 DUMPREG(HDMI_V13_V_BLANK_F_2);
1043 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
1044 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
1045 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
1046 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
1047 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
1048 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
1049 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
1050 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
1051 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
1052 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
1053 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
1054 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001055
1056 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
1057 DUMPREG(HDMI_TG_CMD);
1058 DUMPREG(HDMI_TG_H_FSZ_L);
1059 DUMPREG(HDMI_TG_H_FSZ_H);
1060 DUMPREG(HDMI_TG_HACT_ST_L);
1061 DUMPREG(HDMI_TG_HACT_ST_H);
1062 DUMPREG(HDMI_TG_HACT_SZ_L);
1063 DUMPREG(HDMI_TG_HACT_SZ_H);
1064 DUMPREG(HDMI_TG_V_FSZ_L);
1065 DUMPREG(HDMI_TG_V_FSZ_H);
1066 DUMPREG(HDMI_TG_VSYNC_L);
1067 DUMPREG(HDMI_TG_VSYNC_H);
1068 DUMPREG(HDMI_TG_VSYNC2_L);
1069 DUMPREG(HDMI_TG_VSYNC2_H);
1070 DUMPREG(HDMI_TG_VACT_ST_L);
1071 DUMPREG(HDMI_TG_VACT_ST_H);
1072 DUMPREG(HDMI_TG_VACT_SZ_L);
1073 DUMPREG(HDMI_TG_VACT_SZ_H);
1074 DUMPREG(HDMI_TG_FIELD_CHG_L);
1075 DUMPREG(HDMI_TG_FIELD_CHG_H);
1076 DUMPREG(HDMI_TG_VACT_ST2_L);
1077 DUMPREG(HDMI_TG_VACT_ST2_H);
1078 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
1079 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
1080 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
1081 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
1082 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
1083 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
1084 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
1085 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
1086#undef DUMPREG
1087}
1088
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001089static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
1090{
1091 int i;
1092
1093#define DUMPREG(reg_id) \
1094 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
1095 readl(hdata->regs + reg_id))
1096
1097 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
1098 DUMPREG(HDMI_INTC_CON);
1099 DUMPREG(HDMI_INTC_FLAG);
1100 DUMPREG(HDMI_HPD_STATUS);
1101 DUMPREG(HDMI_INTC_CON_1);
1102 DUMPREG(HDMI_INTC_FLAG_1);
1103 DUMPREG(HDMI_PHY_STATUS_0);
1104 DUMPREG(HDMI_PHY_STATUS_PLL);
1105 DUMPREG(HDMI_PHY_CON_0);
1106 DUMPREG(HDMI_PHY_RSTOUT);
1107 DUMPREG(HDMI_PHY_VPLL);
1108 DUMPREG(HDMI_PHY_CMU);
1109 DUMPREG(HDMI_CORE_RSTOUT);
1110
1111 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
1112 DUMPREG(HDMI_CON_0);
1113 DUMPREG(HDMI_CON_1);
1114 DUMPREG(HDMI_CON_2);
1115 DUMPREG(HDMI_SYS_STATUS);
1116 DUMPREG(HDMI_PHY_STATUS_0);
1117 DUMPREG(HDMI_STATUS_EN);
1118 DUMPREG(HDMI_HPD);
1119 DUMPREG(HDMI_MODE_SEL);
1120 DUMPREG(HDMI_ENC_EN);
1121 DUMPREG(HDMI_DC_CONTROL);
1122 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
1123
1124 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
1125 DUMPREG(HDMI_H_BLANK_0);
1126 DUMPREG(HDMI_H_BLANK_1);
1127 DUMPREG(HDMI_V2_BLANK_0);
1128 DUMPREG(HDMI_V2_BLANK_1);
1129 DUMPREG(HDMI_V1_BLANK_0);
1130 DUMPREG(HDMI_V1_BLANK_1);
1131 DUMPREG(HDMI_V_LINE_0);
1132 DUMPREG(HDMI_V_LINE_1);
1133 DUMPREG(HDMI_H_LINE_0);
1134 DUMPREG(HDMI_H_LINE_1);
1135 DUMPREG(HDMI_HSYNC_POL);
1136
1137 DUMPREG(HDMI_VSYNC_POL);
1138 DUMPREG(HDMI_INT_PRO_MODE);
1139 DUMPREG(HDMI_V_BLANK_F0_0);
1140 DUMPREG(HDMI_V_BLANK_F0_1);
1141 DUMPREG(HDMI_V_BLANK_F1_0);
1142 DUMPREG(HDMI_V_BLANK_F1_1);
1143
1144 DUMPREG(HDMI_H_SYNC_START_0);
1145 DUMPREG(HDMI_H_SYNC_START_1);
1146 DUMPREG(HDMI_H_SYNC_END_0);
1147 DUMPREG(HDMI_H_SYNC_END_1);
1148
1149 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
1150 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
1151 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
1152 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
1153
1154 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
1155 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
1156 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
1157 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
1158
1159 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
1160 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
1161 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
1162 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
1163
1164 DUMPREG(HDMI_V_BLANK_F2_0);
1165 DUMPREG(HDMI_V_BLANK_F2_1);
1166 DUMPREG(HDMI_V_BLANK_F3_0);
1167 DUMPREG(HDMI_V_BLANK_F3_1);
1168 DUMPREG(HDMI_V_BLANK_F4_0);
1169 DUMPREG(HDMI_V_BLANK_F4_1);
1170 DUMPREG(HDMI_V_BLANK_F5_0);
1171 DUMPREG(HDMI_V_BLANK_F5_1);
1172
1173 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
1174 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
1175 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
1176 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
1177 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
1178 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
1179 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
1180 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
1181
1182 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
1183 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
1184 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
1185 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
1186 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
1187 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
1188 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
1189 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
1190
1191 DUMPREG(HDMI_VACT_SPACE_1_0);
1192 DUMPREG(HDMI_VACT_SPACE_1_1);
1193 DUMPREG(HDMI_VACT_SPACE_2_0);
1194 DUMPREG(HDMI_VACT_SPACE_2_1);
1195 DUMPREG(HDMI_VACT_SPACE_3_0);
1196 DUMPREG(HDMI_VACT_SPACE_3_1);
1197 DUMPREG(HDMI_VACT_SPACE_4_0);
1198 DUMPREG(HDMI_VACT_SPACE_4_1);
1199 DUMPREG(HDMI_VACT_SPACE_5_0);
1200 DUMPREG(HDMI_VACT_SPACE_5_1);
1201 DUMPREG(HDMI_VACT_SPACE_6_0);
1202 DUMPREG(HDMI_VACT_SPACE_6_1);
1203
1204 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
1205 DUMPREG(HDMI_TG_CMD);
1206 DUMPREG(HDMI_TG_H_FSZ_L);
1207 DUMPREG(HDMI_TG_H_FSZ_H);
1208 DUMPREG(HDMI_TG_HACT_ST_L);
1209 DUMPREG(HDMI_TG_HACT_ST_H);
1210 DUMPREG(HDMI_TG_HACT_SZ_L);
1211 DUMPREG(HDMI_TG_HACT_SZ_H);
1212 DUMPREG(HDMI_TG_V_FSZ_L);
1213 DUMPREG(HDMI_TG_V_FSZ_H);
1214 DUMPREG(HDMI_TG_VSYNC_L);
1215 DUMPREG(HDMI_TG_VSYNC_H);
1216 DUMPREG(HDMI_TG_VSYNC2_L);
1217 DUMPREG(HDMI_TG_VSYNC2_H);
1218 DUMPREG(HDMI_TG_VACT_ST_L);
1219 DUMPREG(HDMI_TG_VACT_ST_H);
1220 DUMPREG(HDMI_TG_VACT_SZ_L);
1221 DUMPREG(HDMI_TG_VACT_SZ_H);
1222 DUMPREG(HDMI_TG_FIELD_CHG_L);
1223 DUMPREG(HDMI_TG_FIELD_CHG_H);
1224 DUMPREG(HDMI_TG_VACT_ST2_L);
1225 DUMPREG(HDMI_TG_VACT_ST2_H);
1226 DUMPREG(HDMI_TG_VACT_ST3_L);
1227 DUMPREG(HDMI_TG_VACT_ST3_H);
1228 DUMPREG(HDMI_TG_VACT_ST4_L);
1229 DUMPREG(HDMI_TG_VACT_ST4_H);
1230 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
1231 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
1232 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
1233 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
1234 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
1235 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
1236 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
1237 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
1238 DUMPREG(HDMI_TG_3D);
1239
1240 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
1241 DUMPREG(HDMI_AVI_CON);
1242 DUMPREG(HDMI_AVI_HEADER0);
1243 DUMPREG(HDMI_AVI_HEADER1);
1244 DUMPREG(HDMI_AVI_HEADER2);
1245 DUMPREG(HDMI_AVI_CHECK_SUM);
1246 DUMPREG(HDMI_VSI_CON);
1247 DUMPREG(HDMI_VSI_HEADER0);
1248 DUMPREG(HDMI_VSI_HEADER1);
1249 DUMPREG(HDMI_VSI_HEADER2);
1250 for (i = 0; i < 7; ++i)
1251 DUMPREG(HDMI_VSI_DATA(i));
1252
1253#undef DUMPREG
1254}
1255
1256static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
1257{
Rahul Sharma5a325072012-10-04 20:48:54 +05301258 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001259 hdmi_v13_regs_dump(hdata, prefix);
1260 else
1261 hdmi_v14_regs_dump(hdata, prefix);
1262}
1263
1264static int hdmi_v13_conf_index(struct drm_display_mode *mode)
1265{
1266 int i;
1267
1268 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1269 if (hdmi_v13_confs[i].width == mode->hdisplay &&
1270 hdmi_v13_confs[i].height == mode->vdisplay &&
1271 hdmi_v13_confs[i].vrefresh == mode->vrefresh &&
1272 hdmi_v13_confs[i].interlace ==
1273 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1274 true : false))
1275 return i;
1276
Inki Dae1de425b2012-03-16 18:47:04 +09001277 return -EINVAL;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001278}
1279
1280static int hdmi_v14_conf_index(struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001281{
1282 int i;
1283
1284 for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i)
1285 if (hdmi_confs[i].width == mode->hdisplay &&
1286 hdmi_confs[i].height == mode->vdisplay &&
1287 hdmi_confs[i].vrefresh == mode->vrefresh &&
1288 hdmi_confs[i].interlace ==
1289 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1290 true : false))
1291 return i;
1292
Inki Dae1de425b2012-03-16 18:47:04 +09001293 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001294}
1295
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001296static int hdmi_conf_index(struct hdmi_context *hdata,
1297 struct drm_display_mode *mode)
1298{
Rahul Sharma5a325072012-10-04 20:48:54 +05301299 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001300 return hdmi_v13_conf_index(mode);
Inki Dae1de425b2012-03-16 18:47:04 +09001301
1302 return hdmi_v14_conf_index(mode);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001303}
1304
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301305static u8 hdmi_chksum(struct hdmi_context *hdata,
1306 u32 start, u8 len, u32 hdr_sum)
1307{
1308 int i;
1309
1310 /* hdr_sum : header0 + header1 + header2
1311 * start : start address of packet byte1
1312 * len : packet bytes - 1 */
1313 for (i = 0; i < len; ++i)
1314 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
1315
1316 /* return 2's complement of 8 bit hdr_sum */
1317 return (u8)(~(hdr_sum & 0xff) + 1);
1318}
1319
1320static void hdmi_reg_infoframe(struct hdmi_context *hdata,
1321 struct hdmi_infoframe *infoframe)
1322{
1323 u32 hdr_sum;
1324 u8 chksum;
1325 u32 aspect_ratio;
1326 u32 mod;
1327 u32 vic;
1328
1329 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1330
1331 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
1332 if (hdata->dvi_mode) {
1333 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
1334 HDMI_VSI_CON_DO_NOT_TRANSMIT);
1335 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
1336 HDMI_AVI_CON_DO_NOT_TRANSMIT);
1337 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
1338 return;
1339 }
1340
1341 switch (infoframe->type) {
1342 case HDMI_PACKET_TYPE_AVI:
1343 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
1344 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type);
1345 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver);
1346 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len);
1347 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
1348
1349 /* Output format zero hardcoded ,RGB YBCR selection */
1350 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
1351 AVI_ACTIVE_FORMAT_VALID |
1352 AVI_UNDERSCANNED_DISPLAY_VALID);
1353
1354 aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9;
1355
1356 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio |
1357 AVI_SAME_AS_PIC_ASPECT_RATIO);
1358
1359 if (hdata->type == HDMI_TYPE13)
1360 vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id;
1361 else
1362 vic = hdmi_confs[hdata->cur_conf].cea_video_id;
1363
1364 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
1365
1366 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
1367 infoframe->len, hdr_sum);
1368 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
1369 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
1370 break;
1371 case HDMI_PACKET_TYPE_AUI:
1372 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
1373 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type);
1374 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver);
1375 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len);
1376 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
1377 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
1378 infoframe->len, hdr_sum);
1379 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
1380 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
1381 break;
1382 default:
1383 break;
1384 }
1385}
1386
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001387static bool hdmi_is_connected(void *ctx)
1388{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001389 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001390
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001391 return hdata->hpd;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001392}
1393
1394static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
1395 u8 *edid, int len)
1396{
1397 struct edid *raw_edid;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001398 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001399
1400 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1401
1402 if (!hdata->ddc_port)
1403 return -ENODEV;
1404
1405 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
1406 if (raw_edid) {
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001407 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001408 memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
1409 * EDID_LENGTH, len));
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001410 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
1411 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
1412 raw_edid->width_cm, raw_edid->height_cm);
Egbert Eich3dc5fa92012-11-20 04:30:16 -05001413 kfree(raw_edid);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001414 } else {
1415 return -ENODEV;
1416 }
1417
1418 return 0;
1419}
1420
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001421static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001422{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001423 int i;
1424
Inki Dae1de425b2012-03-16 18:47:04 +09001425 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1426 check_timing->xres, check_timing->yres,
1427 check_timing->refresh, (check_timing->vmode &
1428 FB_VMODE_INTERLACED) ? true : false);
1429
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001430 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1431 if (hdmi_v13_confs[i].width == check_timing->xres &&
1432 hdmi_v13_confs[i].height == check_timing->yres &&
1433 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1434 hdmi_v13_confs[i].interlace ==
1435 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1436 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001437 return 0;
1438
1439 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001440
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001441 return -EINVAL;
1442}
1443
1444static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1445{
1446 int i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001447
Inki Dae1de425b2012-03-16 18:47:04 +09001448 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1449 check_timing->xres, check_timing->yres,
1450 check_timing->refresh, (check_timing->vmode &
1451 FB_VMODE_INTERLACED) ? true : false);
1452
1453 for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001454 if (hdmi_confs[i].width == check_timing->xres &&
1455 hdmi_confs[i].height == check_timing->yres &&
1456 hdmi_confs[i].vrefresh == check_timing->refresh &&
1457 hdmi_confs[i].interlace ==
1458 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1459 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001460 return 0;
1461
1462 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001463
1464 return -EINVAL;
1465}
1466
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001467static int hdmi_check_timing(void *ctx, void *timing)
1468{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001469 struct hdmi_context *hdata = ctx;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001470 struct fb_videomode *check_timing = timing;
1471
1472 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1473
1474 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
1475 check_timing->yres, check_timing->refresh,
1476 check_timing->vmode);
1477
Rahul Sharma5a325072012-10-04 20:48:54 +05301478 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001479 return hdmi_v13_check_timing(check_timing);
1480 else
1481 return hdmi_v14_check_timing(check_timing);
1482}
1483
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001484static void hdmi_set_acr(u32 freq, u8 *acr)
1485{
1486 u32 n, cts;
1487
1488 switch (freq) {
1489 case 32000:
1490 n = 4096;
1491 cts = 27000;
1492 break;
1493 case 44100:
1494 n = 6272;
1495 cts = 30000;
1496 break;
1497 case 88200:
1498 n = 12544;
1499 cts = 30000;
1500 break;
1501 case 176400:
1502 n = 25088;
1503 cts = 30000;
1504 break;
1505 case 48000:
1506 n = 6144;
1507 cts = 27000;
1508 break;
1509 case 96000:
1510 n = 12288;
1511 cts = 27000;
1512 break;
1513 case 192000:
1514 n = 24576;
1515 cts = 27000;
1516 break;
1517 default:
1518 n = 0;
1519 cts = 0;
1520 break;
1521 }
1522
1523 acr[1] = cts >> 16;
1524 acr[2] = cts >> 8 & 0xff;
1525 acr[3] = cts & 0xff;
1526
1527 acr[4] = n >> 16;
1528 acr[5] = n >> 8 & 0xff;
1529 acr[6] = n & 0xff;
1530}
1531
1532static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1533{
1534 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1535 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1536 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1537 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1538 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1539 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1540 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1541 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1542 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1543
Rahul Sharma5a325072012-10-04 20:48:54 +05301544 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001545 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1546 else
1547 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1548}
1549
1550static void hdmi_audio_init(struct hdmi_context *hdata)
1551{
1552 u32 sample_rate, bits_per_sample, frame_size_code;
1553 u32 data_num, bit_ch, sample_frq;
1554 u32 val;
1555 u8 acr[7];
1556
1557 sample_rate = 44100;
1558 bits_per_sample = 16;
1559 frame_size_code = 0;
1560
1561 switch (bits_per_sample) {
1562 case 20:
1563 data_num = 2;
1564 bit_ch = 1;
1565 break;
1566 case 24:
1567 data_num = 3;
1568 bit_ch = 1;
1569 break;
1570 default:
1571 data_num = 1;
1572 bit_ch = 0;
1573 break;
1574 }
1575
1576 hdmi_set_acr(sample_rate, acr);
1577 hdmi_reg_acr(hdata, acr);
1578
1579 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1580 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1581 | HDMI_I2S_MUX_ENABLE);
1582
1583 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1584 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1585
1586 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1587
1588 sample_frq = (sample_rate == 44100) ? 0 :
1589 (sample_rate == 48000) ? 2 :
1590 (sample_rate == 32000) ? 3 :
1591 (sample_rate == 96000) ? 0xa : 0x0;
1592
1593 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1594 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1595
1596 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1597 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1598
1599 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1600 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1601 | HDMI_I2S_SEL_LRCK(6));
1602 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1603 | HDMI_I2S_SEL_SDATA2(4));
1604 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1605 | HDMI_I2S_SEL_SDATA2(2));
1606 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1607
1608 /* I2S_CON_1 & 2 */
1609 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1610 | HDMI_I2S_L_CH_LOW_POL);
1611 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1612 | HDMI_I2S_SET_BIT_CH(bit_ch)
1613 | HDMI_I2S_SET_SDATA_BIT(data_num)
1614 | HDMI_I2S_BASIC_FORMAT);
1615
1616 /* Configure register related to CUV information */
1617 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1618 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1619 | HDMI_I2S_COPYRIGHT
1620 | HDMI_I2S_LINEAR_PCM
1621 | HDMI_I2S_CONSUMER_FORMAT);
1622 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1623 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1624 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1625 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1626 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1627 HDMI_I2S_ORG_SMP_FREQ_44_1
1628 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1629 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1630
1631 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1632}
1633
1634static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1635{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001636 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001637 return;
1638
1639 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1640 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1641 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1642}
1643
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001644static void hdmi_conf_reset(struct hdmi_context *hdata)
1645{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001646 u32 reg;
1647
Rahul Sharma5a325072012-10-04 20:48:54 +05301648 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001649 reg = HDMI_V13_CORE_RSTOUT;
1650 else
1651 reg = HDMI_CORE_RSTOUT;
1652
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001653 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001654 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001655 mdelay(10);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001656 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001657 mdelay(10);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001658}
1659
1660static void hdmi_conf_init(struct hdmi_context *hdata)
1661{
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301662 struct hdmi_infoframe infoframe;
1663
Tomasz Stanislawski5295e53d2012-10-04 20:48:47 +05301664 /* disable HPD interrupts */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001665 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1666 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001667
1668 /* choose HDMI mode */
1669 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1670 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1671 /* disable bluescreen */
1672 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001673
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001674 if (hdata->dvi_mode) {
1675 /* choose DVI mode */
1676 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1677 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1678 hdmi_reg_writeb(hdata, HDMI_CON_2,
1679 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1680 }
1681
Rahul Sharma5a325072012-10-04 20:48:54 +05301682 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001683 /* choose bluescreen (fecal) color */
1684 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1685 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1686 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1687
1688 /* enable AVI packet every vsync, fixes purple line problem */
1689 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1690 /* force RGB, look to CEA-861-D, table 7 for more detail */
1691 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1692 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1693
1694 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1695 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1696 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1697 } else {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301698 infoframe.type = HDMI_PACKET_TYPE_AVI;
1699 infoframe.ver = HDMI_AVI_VERSION;
1700 infoframe.len = HDMI_AVI_LENGTH;
1701 hdmi_reg_infoframe(hdata, &infoframe);
1702
1703 infoframe.type = HDMI_PACKET_TYPE_AUI;
1704 infoframe.ver = HDMI_AUI_VERSION;
1705 infoframe.len = HDMI_AUI_LENGTH;
1706 hdmi_reg_infoframe(hdata, &infoframe);
1707
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001708 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001709 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1710 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001711}
1712
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001713static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001714{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001715 const struct hdmi_v13_preset_conf *conf =
1716 hdmi_v13_confs[hdata->cur_conf].conf;
1717 const struct hdmi_v13_core_regs *core = &conf->core;
1718 const struct hdmi_v13_tg_regs *tg = &conf->tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001719 int tries;
1720
1721 /* setting core registers */
1722 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1723 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001724 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1725 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1726 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1727 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1728 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1729 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001730 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1731 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001732 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1733 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1734 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1735 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1736 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1737 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1738 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1739 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1740 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1741 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1742 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1743 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1744 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1745 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1746 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001747 /* Timing generator registers */
1748 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1749 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1750 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1751 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1752 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1753 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1754 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1755 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1756 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1757 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1758 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1759 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1760 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1761 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1762 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1763 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1764 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1765 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1766 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1767 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1768 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1769 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1770 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1771 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1772 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1773 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1774 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1775 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1776
1777 /* waiting for HDMIPHY's PLL to get to steady state */
1778 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001779 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001780 if (val & HDMI_PHY_STATUS_READY)
1781 break;
1782 mdelay(1);
1783 }
1784 /* steady state not achieved */
1785 if (tries == 0) {
1786 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1787 hdmi_regs_dump(hdata, "timing apply");
1788 }
1789
1790 clk_disable(hdata->res.sclk_hdmi);
1791 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1792 clk_enable(hdata->res.sclk_hdmi);
1793
1794 /* enable HDMI and timing generator */
1795 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1796 if (core->int_pro_mode[0])
1797 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1798 HDMI_FIELD_EN);
1799 else
1800 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1801}
1802
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001803static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1804{
1805 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
1806 const struct hdmi_core_regs *core = &conf->core;
1807 const struct hdmi_tg_regs *tg = &conf->tg;
1808 int tries;
1809
1810 /* setting core registers */
1811 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1812 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1813 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1814 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1815 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1816 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1817 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1818 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1819 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1820 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1821 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1822 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1823 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1824 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1825 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1826 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1827 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1828 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1829 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1830 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1831 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1832 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1833 core->v_sync_line_bef_2[0]);
1834 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1835 core->v_sync_line_bef_2[1]);
1836 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1837 core->v_sync_line_bef_1[0]);
1838 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1839 core->v_sync_line_bef_1[1]);
1840 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1841 core->v_sync_line_aft_2[0]);
1842 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1843 core->v_sync_line_aft_2[1]);
1844 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1845 core->v_sync_line_aft_1[0]);
1846 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1847 core->v_sync_line_aft_1[1]);
1848 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1849 core->v_sync_line_aft_pxl_2[0]);
1850 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1851 core->v_sync_line_aft_pxl_2[1]);
1852 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1853 core->v_sync_line_aft_pxl_1[0]);
1854 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1855 core->v_sync_line_aft_pxl_1[1]);
1856 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1857 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1858 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1859 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1860 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1861 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1862 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1863 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1864 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1865 core->v_sync_line_aft_3[0]);
1866 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1867 core->v_sync_line_aft_3[1]);
1868 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1869 core->v_sync_line_aft_4[0]);
1870 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1871 core->v_sync_line_aft_4[1]);
1872 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1873 core->v_sync_line_aft_5[0]);
1874 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1875 core->v_sync_line_aft_5[1]);
1876 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1877 core->v_sync_line_aft_6[0]);
1878 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1879 core->v_sync_line_aft_6[1]);
1880 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1881 core->v_sync_line_aft_pxl_3[0]);
1882 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1883 core->v_sync_line_aft_pxl_3[1]);
1884 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1885 core->v_sync_line_aft_pxl_4[0]);
1886 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1887 core->v_sync_line_aft_pxl_4[1]);
1888 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1889 core->v_sync_line_aft_pxl_5[0]);
1890 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1891 core->v_sync_line_aft_pxl_5[1]);
1892 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1893 core->v_sync_line_aft_pxl_6[0]);
1894 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1895 core->v_sync_line_aft_pxl_6[1]);
1896 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1897 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1898 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1899 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1900 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1901 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1902 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1903 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1904 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1905 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1906 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1907 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1908
1909 /* Timing generator registers */
1910 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1911 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1912 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1913 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1914 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1915 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1916 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1917 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1918 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1919 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1920 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1921 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1922 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1923 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1924 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1925 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1926 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1927 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1928 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1929 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1930 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
1931 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
1932 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
1933 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
1934 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1935 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1936 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1937 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1938 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1939 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1940 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1941 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1942 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
1943
1944 /* waiting for HDMIPHY's PLL to get to steady state */
1945 for (tries = 100; tries; --tries) {
1946 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1947 if (val & HDMI_PHY_STATUS_READY)
1948 break;
1949 mdelay(1);
1950 }
1951 /* steady state not achieved */
1952 if (tries == 0) {
1953 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1954 hdmi_regs_dump(hdata, "timing apply");
1955 }
1956
1957 clk_disable(hdata->res.sclk_hdmi);
1958 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1959 clk_enable(hdata->res.sclk_hdmi);
1960
1961 /* enable HDMI and timing generator */
1962 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1963 if (core->int_pro_mode[0])
1964 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1965 HDMI_FIELD_EN);
1966 else
1967 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1968}
1969
1970static void hdmi_timing_apply(struct hdmi_context *hdata)
1971{
Rahul Sharma5a325072012-10-04 20:48:54 +05301972 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001973 hdmi_v13_timing_apply(hdata);
1974 else
1975 hdmi_v14_timing_apply(hdata);
1976}
1977
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001978static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1979{
1980 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001981 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001982
1983 clk_disable(hdata->res.sclk_hdmi);
1984 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1985 clk_enable(hdata->res.sclk_hdmi);
1986
1987 /* operation mode */
1988 buffer[0] = 0x1f;
1989 buffer[1] = 0x00;
1990
1991 if (hdata->hdmiphy_port)
1992 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1993
Rahul Sharma5a325072012-10-04 20:48:54 +05301994 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001995 reg = HDMI_V13_PHY_RSTOUT;
1996 else
1997 reg = HDMI_PHY_RSTOUT;
1998
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001999 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002000 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002001 mdelay(10);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002002 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002003 mdelay(10);
2004}
2005
2006static void hdmiphy_conf_apply(struct hdmi_context *hdata)
2007{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002008 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002009 u8 buffer[32];
2010 u8 operation[2];
2011 u8 read_buffer[32] = {0, };
2012 int ret;
2013 int i;
2014
2015 if (!hdata->hdmiphy_port) {
2016 DRM_ERROR("hdmiphy is not attached\n");
2017 return;
2018 }
2019
2020 /* pixel clock */
Rahul Sharma5a325072012-10-04 20:48:54 +05302021 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002022 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
2023 else
2024 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
2025
2026 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002027 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
2028 if (ret != 32) {
2029 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
2030 return;
2031 }
2032
2033 mdelay(10);
2034
2035 /* operation mode */
2036 operation[0] = 0x1f;
2037 operation[1] = 0x80;
2038
2039 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
2040 if (ret != 2) {
2041 DRM_ERROR("failed to enable hdmiphy\n");
2042 return;
2043 }
2044
2045 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
2046 if (ret < 0) {
2047 DRM_ERROR("failed to read hdmiphy config\n");
2048 return;
2049 }
2050
2051 for (i = 0; i < ret; i++)
2052 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
2053 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
2054}
2055
2056static void hdmi_conf_apply(struct hdmi_context *hdata)
2057{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002058 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2059
2060 hdmiphy_conf_reset(hdata);
2061 hdmiphy_conf_apply(hdata);
2062
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002063 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002064 hdmi_conf_reset(hdata);
2065 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002066 mutex_unlock(&hdata->hdmi_mutex);
2067
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09002068 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002069
2070 /* setting core registers */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002071 hdmi_timing_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09002072 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002073
2074 hdmi_regs_dump(hdata, "start");
2075}
2076
Inki Dae1de425b2012-03-16 18:47:04 +09002077static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
Laurent Pincharte811f5a2012-07-17 17:56:50 +02002078 const struct drm_display_mode *mode,
Inki Dae1de425b2012-03-16 18:47:04 +09002079 struct drm_display_mode *adjusted_mode)
2080{
2081 struct drm_display_mode *m;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002082 struct hdmi_context *hdata = ctx;
Inki Dae1de425b2012-03-16 18:47:04 +09002083 int index;
2084
2085 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2086
2087 drm_mode_set_crtcinfo(adjusted_mode, 0);
2088
Rahul Sharma5a325072012-10-04 20:48:54 +05302089 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09002090 index = hdmi_v13_conf_index(adjusted_mode);
2091 else
2092 index = hdmi_v14_conf_index(adjusted_mode);
2093
2094 /* just return if user desired mode exists. */
2095 if (index >= 0)
2096 return;
2097
2098 /*
2099 * otherwise, find the most suitable mode among modes and change it
2100 * to adjusted_mode.
2101 */
2102 list_for_each_entry(m, &connector->modes, head) {
Rahul Sharma5a325072012-10-04 20:48:54 +05302103 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09002104 index = hdmi_v13_conf_index(m);
2105 else
2106 index = hdmi_v14_conf_index(m);
2107
2108 if (index >= 0) {
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05302109 struct drm_mode_object base;
2110 struct list_head head;
2111
Inki Dae1de425b2012-03-16 18:47:04 +09002112 DRM_INFO("desired mode doesn't exist so\n");
2113 DRM_INFO("use the most suitable mode among modes.\n");
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05302114
2115 /* preserve display mode header while copying. */
2116 head = adjusted_mode->head;
2117 base = adjusted_mode->base;
Inki Dae1de425b2012-03-16 18:47:04 +09002118 memcpy(adjusted_mode, m, sizeof(*m));
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05302119 adjusted_mode->head = head;
2120 adjusted_mode->base = base;
Inki Dae1de425b2012-03-16 18:47:04 +09002121 break;
2122 }
2123 }
2124}
2125
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002126static void hdmi_mode_set(void *ctx, void *mode)
2127{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002128 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002129 int conf_idx;
2130
2131 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2132
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002133 conf_idx = hdmi_conf_index(hdata, mode);
2134 if (conf_idx >= 0)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002135 hdata->cur_conf = conf_idx;
2136 else
2137 DRM_DEBUG_KMS("not supported mode\n");
2138}
2139
Inki Dae1de425b2012-03-16 18:47:04 +09002140static void hdmi_get_max_resol(void *ctx, unsigned int *width,
2141 unsigned int *height)
2142{
2143 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2144
2145 *width = MAX_WIDTH;
2146 *height = MAX_HEIGHT;
2147}
2148
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002149static void hdmi_commit(void *ctx)
2150{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002151 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002152
2153 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2154
2155 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002156}
2157
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002158static void hdmi_poweron(struct hdmi_context *hdata)
2159{
2160 struct hdmi_resources *res = &hdata->res;
2161
2162 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2163
2164 mutex_lock(&hdata->hdmi_mutex);
2165 if (hdata->powered) {
2166 mutex_unlock(&hdata->hdmi_mutex);
2167 return;
2168 }
2169
2170 hdata->powered = true;
2171
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002172 mutex_unlock(&hdata->hdmi_mutex);
2173
2174 pm_runtime_get_sync(hdata->dev);
2175
2176 regulator_bulk_enable(res->regul_count, res->regul_bulk);
2177 clk_enable(res->hdmiphy);
2178 clk_enable(res->hdmi);
2179 clk_enable(res->sclk_hdmi);
2180}
2181
2182static void hdmi_poweroff(struct hdmi_context *hdata)
2183{
2184 struct hdmi_resources *res = &hdata->res;
2185
2186 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2187
2188 mutex_lock(&hdata->hdmi_mutex);
2189 if (!hdata->powered)
2190 goto out;
2191 mutex_unlock(&hdata->hdmi_mutex);
2192
2193 /*
2194 * The TV power domain needs any condition of hdmiphy to turn off and
2195 * its reset state seems to meet the condition.
2196 */
2197 hdmiphy_conf_reset(hdata);
2198
2199 clk_disable(res->sclk_hdmi);
2200 clk_disable(res->hdmi);
2201 clk_disable(res->hdmiphy);
2202 regulator_bulk_disable(res->regul_count, res->regul_bulk);
2203
2204 pm_runtime_put_sync(hdata->dev);
2205
2206 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002207
2208 hdata->powered = false;
2209
2210out:
2211 mutex_unlock(&hdata->hdmi_mutex);
2212}
2213
2214static void hdmi_dpms(void *ctx, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002215{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002216 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002217
2218 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2219
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002220 switch (mode) {
2221 case DRM_MODE_DPMS_ON:
2222 hdmi_poweron(hdata);
2223 break;
2224 case DRM_MODE_DPMS_STANDBY:
2225 case DRM_MODE_DPMS_SUSPEND:
2226 case DRM_MODE_DPMS_OFF:
2227 hdmi_poweroff(hdata);
2228 break;
2229 default:
2230 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
2231 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002232 }
2233}
2234
Joonyoung Shim578b6062012-04-05 20:49:26 +09002235static struct exynos_hdmi_ops hdmi_ops = {
2236 /* display */
2237 .is_connected = hdmi_is_connected,
2238 .get_edid = hdmi_get_edid,
2239 .check_timing = hdmi_check_timing,
Joonyoung Shim578b6062012-04-05 20:49:26 +09002240
2241 /* manager */
Inki Dae1de425b2012-03-16 18:47:04 +09002242 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002243 .mode_set = hdmi_mode_set,
Inki Dae1de425b2012-03-16 18:47:04 +09002244 .get_max_resol = hdmi_get_max_resol,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002245 .commit = hdmi_commit,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002246 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002247};
2248
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002249static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
2250{
2251 struct exynos_drm_hdmi_context *ctx = arg;
2252 struct hdmi_context *hdata = ctx->ctx;
2253
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002254 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302255 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002256 mutex_unlock(&hdata->hdmi_mutex);
2257
2258 if (ctx->drm_dev)
2259 drm_helper_hpd_irq_event(ctx->drm_dev);
2260
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002261 return IRQ_HANDLED;
2262}
2263
2264static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002265{
2266 struct exynos_drm_hdmi_context *ctx = arg;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002267 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002268 u32 intc_flag;
2269
2270 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
2271 /* clearing flags for HPD plug/unplug */
2272 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002273 DRM_DEBUG_KMS("unplugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002274 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2275 HDMI_INTC_FLAG_HPD_UNPLUG);
2276 }
2277 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002278 DRM_DEBUG_KMS("plugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002279 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2280 HDMI_INTC_FLAG_HPD_PLUG);
2281 }
2282
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002283 if (ctx->drm_dev)
Joonyoung Shim66265a22012-04-23 19:35:49 +09002284 drm_helper_hpd_irq_event(ctx->drm_dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002285
2286 return IRQ_HANDLED;
2287}
2288
2289static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
2290{
2291 struct device *dev = hdata->dev;
2292 struct hdmi_resources *res = &hdata->res;
2293 static char *supply[] = {
2294 "hdmi-en",
2295 "vdd",
2296 "vdd_osc",
2297 "vdd_pll",
2298 };
2299 int i, ret;
2300
2301 DRM_DEBUG_KMS("HDMI resource init\n");
2302
Sachin Kamatadc837a2012-08-31 15:50:47 +05302303 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002304
2305 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302306 res->hdmi = devm_clk_get(dev, "hdmi");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002307 if (IS_ERR_OR_NULL(res->hdmi)) {
2308 DRM_ERROR("failed to get clock 'hdmi'\n");
2309 goto fail;
2310 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302311 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002312 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
2313 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2314 goto fail;
2315 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302316 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002317 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
2318 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2319 goto fail;
2320 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302321 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002322 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
2323 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2324 goto fail;
2325 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302326 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002327 if (IS_ERR_OR_NULL(res->hdmiphy)) {
2328 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2329 goto fail;
2330 }
2331
2332 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
2333
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302334 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05302335 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002336 if (!res->regul_bulk) {
2337 DRM_ERROR("failed to get memory for regulators\n");
2338 goto fail;
2339 }
2340 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
2341 res->regul_bulk[i].supply = supply[i];
2342 res->regul_bulk[i].consumer = NULL;
2343 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302344 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002345 if (ret) {
2346 DRM_ERROR("failed to get regulators\n");
2347 goto fail;
2348 }
2349 res->regul_count = ARRAY_SIZE(supply);
2350
2351 return 0;
2352fail:
2353 DRM_ERROR("HDMI resource init - failed\n");
2354 return -ENODEV;
2355}
2356
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002357static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2358
2359void hdmi_attach_ddc_client(struct i2c_client *ddc)
2360{
2361 if (ddc)
2362 hdmi_ddc = ddc;
2363}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002364
2365void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2366{
2367 if (hdmiphy)
2368 hdmi_hdmiphy = hdmiphy;
2369}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002370
Rahul Sharma22c4f422012-10-04 20:48:55 +05302371#ifdef CONFIG_OF
2372static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2373 (struct device *dev)
2374{
2375 struct device_node *np = dev->of_node;
2376 struct s5p_hdmi_platform_data *pd;
2377 enum of_gpio_flags flags;
2378 u32 value;
2379
2380 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
2381 if (!pd) {
2382 DRM_ERROR("memory allocation for pdata failed\n");
2383 goto err_data;
2384 }
2385
2386 if (!of_find_property(np, "hpd-gpio", &value)) {
2387 DRM_ERROR("no hpd gpio property found\n");
2388 goto err_data;
2389 }
2390
2391 pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
2392
2393 return pd;
2394
2395err_data:
2396 return NULL;
2397}
2398#else
2399static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2400 (struct device *dev)
2401{
2402 return NULL;
2403}
2404#endif
2405
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302406static struct platform_device_id hdmi_driver_types[] = {
2407 {
2408 .name = "s5pv210-hdmi",
2409 .driver_data = HDMI_TYPE13,
2410 }, {
2411 .name = "exynos4-hdmi",
2412 .driver_data = HDMI_TYPE13,
2413 }, {
2414 .name = "exynos4-hdmi14",
Rahul Sharma22c4f422012-10-04 20:48:55 +05302415 .driver_data = HDMI_TYPE14,
2416 }, {
2417 .name = "exynos5-hdmi",
2418 .driver_data = HDMI_TYPE14,
2419 }, {
2420 /* end node */
2421 }
2422};
2423
2424static struct of_device_id hdmi_match_types[] = {
2425 {
2426 .compatible = "samsung,exynos5-hdmi",
2427 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302428 }, {
2429 /* end node */
2430 }
2431};
2432
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002433static int __devinit hdmi_probe(struct platform_device *pdev)
2434{
2435 struct device *dev = &pdev->dev;
2436 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2437 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302438 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002439 struct resource *res;
2440 int ret;
2441
2442 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2443
Rahul Sharma22c4f422012-10-04 20:48:55 +05302444 if (pdev->dev.of_node) {
2445 pdata = drm_hdmi_dt_parse_pdata(dev);
2446 if (IS_ERR(pdata)) {
2447 DRM_ERROR("failed to parse dt\n");
2448 return PTR_ERR(pdata);
2449 }
2450 } else {
2451 pdata = pdev->dev.platform_data;
2452 }
2453
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002454 if (!pdata) {
2455 DRM_ERROR("no platform data specified\n");
2456 return -EINVAL;
2457 }
2458
Sachin Kamata6e65072012-06-19 11:47:40 +05302459 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
2460 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002461 if (!drm_hdmi_ctx) {
2462 DRM_ERROR("failed to allocate common hdmi context.\n");
2463 return -ENOMEM;
2464 }
2465
Sachin Kamata6e65072012-06-19 11:47:40 +05302466 hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context),
2467 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002468 if (!hdata) {
2469 DRM_ERROR("out of memory\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002470 return -ENOMEM;
2471 }
2472
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002473 mutex_init(&hdata->hdmi_mutex);
2474
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002475 drm_hdmi_ctx->ctx = (void *)hdata;
2476 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2477
2478 platform_set_drvdata(pdev, drm_hdmi_ctx);
2479
Rahul Sharma22c4f422012-10-04 20:48:55 +05302480 if (dev->of_node) {
2481 const struct of_device_id *match;
2482 match = of_match_node(of_match_ptr(hdmi_match_types),
2483 pdev->dev.of_node);
2484 hdata->type = (enum hdmi_type)match->data;
2485 } else {
2486 hdata->type = (enum hdmi_type)platform_get_device_id
Rahul Sharma5a325072012-10-04 20:48:54 +05302487 (pdev)->driver_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302488 }
2489
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302490 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002491 hdata->dev = dev;
2492
2493 ret = hdmi_resources_init(hdata);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302494
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002495 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302496 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302497 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002498 }
2499
2500 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302501 if (!res) {
2502 DRM_ERROR("failed to find registers\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302503 return -ENOENT;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302504 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002505
Sachin Kamata6e65072012-06-19 11:47:40 +05302506 hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002507 if (!hdata->regs) {
2508 DRM_ERROR("failed to map registers\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302509 return -ENXIO;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002510 }
2511
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302512 ret = devm_gpio_request(&pdev->dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302513 if (ret) {
2514 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302515 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302516 }
2517
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002518 /* DDC i2c driver */
2519 if (i2c_add_driver(&ddc_driver)) {
2520 DRM_ERROR("failed to register ddc i2c driver\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302521 return -ENOENT;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002522 }
2523
2524 hdata->ddc_port = hdmi_ddc;
2525
2526 /* hdmiphy i2c driver */
2527 if (i2c_add_driver(&hdmiphy_driver)) {
2528 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2529 ret = -ENOENT;
2530 goto err_ddc;
2531 }
2532
2533 hdata->hdmiphy_port = hdmi_hdmiphy;
2534
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302535 hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002536 if (hdata->external_irq < 0) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302537 DRM_ERROR("failed to get GPIO external irq\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002538 ret = hdata->external_irq;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002539 goto err_hdmiphy;
2540 }
2541
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302542 hdata->internal_irq = platform_get_irq(pdev, 0);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002543 if (hdata->internal_irq < 0) {
2544 DRM_ERROR("failed to get platform internal irq\n");
2545 ret = hdata->internal_irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002546 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002547 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002548
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302549 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2550
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002551 ret = request_threaded_irq(hdata->external_irq, NULL,
2552 hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
2553 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
2554 "hdmi_external", drm_hdmi_ctx);
2555 if (ret) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302556 DRM_ERROR("failed to register hdmi external interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002557 goto err_hdmiphy;
2558 }
2559
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002560 ret = request_threaded_irq(hdata->internal_irq, NULL,
2561 hdmi_internal_irq_thread, IRQF_ONESHOT,
2562 "hdmi_internal", drm_hdmi_ctx);
2563 if (ret) {
2564 DRM_ERROR("failed to register hdmi internal interrupt\n");
2565 goto err_free_irq;
2566 }
2567
Rahul Sharma768c3052012-10-04 20:48:56 +05302568 /* Attach HDMI Driver to common hdmi. */
2569 exynos_hdmi_drv_attach(drm_hdmi_ctx);
2570
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002571 /* register specific callbacks to common hdmi. */
Joonyoung Shim578b6062012-04-05 20:49:26 +09002572 exynos_hdmi_ops_register(&hdmi_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002573
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002574 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002575
2576 return 0;
2577
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002578err_free_irq:
2579 free_irq(hdata->external_irq, drm_hdmi_ctx);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002580err_hdmiphy:
2581 i2c_del_driver(&hdmiphy_driver);
2582err_ddc:
2583 i2c_del_driver(&ddc_driver);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002584 return ret;
2585}
2586
2587static int __devexit hdmi_remove(struct platform_device *pdev)
2588{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002589 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002590 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002591 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002592
2593 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2594
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002595 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002596
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002597 free_irq(hdata->internal_irq, hdata);
Tomasz Stanislawski07c8bdd2012-10-04 20:48:45 +05302598 free_irq(hdata->external_irq, hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002599
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002600
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002601 /* hdmiphy i2c driver */
2602 i2c_del_driver(&hdmiphy_driver);
2603 /* DDC i2c driver */
2604 i2c_del_driver(&ddc_driver);
2605
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002606 return 0;
2607}
2608
Joonyoung Shimab27af82012-04-23 19:35:51 +09002609#ifdef CONFIG_PM_SLEEP
2610static int hdmi_suspend(struct device *dev)
2611{
2612 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2613 struct hdmi_context *hdata = ctx->ctx;
2614
2615 disable_irq(hdata->internal_irq);
2616 disable_irq(hdata->external_irq);
2617
2618 hdata->hpd = false;
2619 if (ctx->drm_dev)
2620 drm_helper_hpd_irq_event(ctx->drm_dev);
2621
2622 hdmi_poweroff(hdata);
2623
2624 return 0;
2625}
2626
2627static int hdmi_resume(struct device *dev)
2628{
2629 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2630 struct hdmi_context *hdata = ctx->ctx;
2631
2632 enable_irq(hdata->external_irq);
2633 enable_irq(hdata->internal_irq);
2634 return 0;
2635}
2636#endif
2637
2638static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume);
2639
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002640struct platform_driver hdmi_driver = {
2641 .probe = hdmi_probe,
2642 .remove = __devexit_p(hdmi_remove),
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302643 .id_table = hdmi_driver_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002644 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302645 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002646 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002647 .pm = &hdmi_pm_ops,
Rahul Sharma22c4f422012-10-04 20:48:55 +05302648 .of_match_table = hdmi_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002649 },
2650};