blob: 6d63f9090f943161072399fdd97d8aaaad4b0284 [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>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090037
38#include <drm/exynos_drm.h>
39
40#include "exynos_drm_drv.h"
41#include "exynos_drm_hdmi.h"
42
43#include "exynos_hdmi.h"
44
Tomasz Stanislawskifca57122012-10-04 20:48:46 +053045#include <linux/gpio.h>
46#include <media/s5p_hdmi.h>
47
Inki Dae1de425b2012-03-16 18:47:04 +090048#define MAX_WIDTH 1920
49#define MAX_HEIGHT 1080
Seung-Woo Kimd8408322011-12-21 17:39:39 +090050#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
51
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053052/* AVI header and aspect ratio */
53#define HDMI_AVI_VERSION 0x02
54#define HDMI_AVI_LENGTH 0x0D
55#define AVI_PIC_ASPECT_RATIO_16_9 (2 << 4)
56#define AVI_SAME_AS_PIC_ASPECT_RATIO 8
57
58/* AUI header info */
59#define HDMI_AUI_VERSION 0x01
60#define HDMI_AUI_LENGTH 0x0A
61
62/* HDMI infoframe to configure HDMI out packet header, AUI and AVI */
63enum HDMI_PACKET_TYPE {
64 /* refer to Table 5-8 Packet Type in HDMI specification v1.4a */
65 /* InfoFrame packet type */
66 HDMI_PACKET_TYPE_INFOFRAME = 0x80,
67 /* Vendor-Specific InfoFrame */
68 HDMI_PACKET_TYPE_VSI = HDMI_PACKET_TYPE_INFOFRAME + 1,
69 /* Auxiliary Video information InfoFrame */
70 HDMI_PACKET_TYPE_AVI = HDMI_PACKET_TYPE_INFOFRAME + 2,
71 /* Audio information InfoFrame */
72 HDMI_PACKET_TYPE_AUI = HDMI_PACKET_TYPE_INFOFRAME + 4
73};
74
Rahul Sharma5a325072012-10-04 20:48:54 +053075enum hdmi_type {
76 HDMI_TYPE13,
77 HDMI_TYPE14,
78};
79
Joonyoung Shim590f4182012-03-16 18:47:14 +090080struct hdmi_resources {
81 struct clk *hdmi;
82 struct clk *sclk_hdmi;
83 struct clk *sclk_pixel;
84 struct clk *sclk_hdmiphy;
85 struct clk *hdmiphy;
86 struct regulator_bulk_data *regul_bulk;
87 int regul_count;
88};
89
Sean Paul2f7e2ed2013-01-15 08:11:08 -050090struct hdmi_tg_regs {
91 u8 cmd[1];
92 u8 h_fsz[2];
93 u8 hact_st[2];
94 u8 hact_sz[2];
95 u8 v_fsz[2];
96 u8 vsync[2];
97 u8 vsync2[2];
98 u8 vact_st[2];
99 u8 vact_sz[2];
100 u8 field_chg[2];
101 u8 vact_st2[2];
102 u8 vact_st3[2];
103 u8 vact_st4[2];
104 u8 vsync_top_hdmi[2];
105 u8 vsync_bot_hdmi[2];
106 u8 field_top_hdmi[2];
107 u8 field_bot_hdmi[2];
108 u8 tg_3d[1];
109};
110
111struct hdmi_core_regs {
112 u8 h_blank[2];
113 u8 v2_blank[2];
114 u8 v1_blank[2];
115 u8 v_line[2];
116 u8 h_line[2];
117 u8 hsync_pol[1];
118 u8 vsync_pol[1];
119 u8 int_pro_mode[1];
120 u8 v_blank_f0[2];
121 u8 v_blank_f1[2];
122 u8 h_sync_start[2];
123 u8 h_sync_end[2];
124 u8 v_sync_line_bef_2[2];
125 u8 v_sync_line_bef_1[2];
126 u8 v_sync_line_aft_2[2];
127 u8 v_sync_line_aft_1[2];
128 u8 v_sync_line_aft_pxl_2[2];
129 u8 v_sync_line_aft_pxl_1[2];
130 u8 v_blank_f2[2]; /* for 3D mode */
131 u8 v_blank_f3[2]; /* for 3D mode */
132 u8 v_blank_f4[2]; /* for 3D mode */
133 u8 v_blank_f5[2]; /* for 3D mode */
134 u8 v_sync_line_aft_3[2];
135 u8 v_sync_line_aft_4[2];
136 u8 v_sync_line_aft_5[2];
137 u8 v_sync_line_aft_6[2];
138 u8 v_sync_line_aft_pxl_3[2];
139 u8 v_sync_line_aft_pxl_4[2];
140 u8 v_sync_line_aft_pxl_5[2];
141 u8 v_sync_line_aft_pxl_6[2];
142 u8 vact_space_1[2];
143 u8 vact_space_2[2];
144 u8 vact_space_3[2];
145 u8 vact_space_4[2];
146 u8 vact_space_5[2];
147 u8 vact_space_6[2];
148};
149
150struct hdmi_v14_conf {
151 int pixel_clock;
152 struct hdmi_core_regs core;
153 struct hdmi_tg_regs tg;
154 int cea_video_id;
155};
156
Joonyoung Shim590f4182012-03-16 18:47:14 +0900157struct hdmi_context {
158 struct device *dev;
159 struct drm_device *drm_dev;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900160 bool hpd;
161 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +0900162 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900163 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900164
Joonyoung Shim590f4182012-03-16 18:47:14 +0900165 void __iomem *regs;
Inki Dae1055b392012-10-19 17:37:35 +0900166 void *parent_ctx;
Sean Paul77006a72013-01-16 10:17:20 -0500167 int irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900168
169 struct i2c_client *ddc_port;
170 struct i2c_client *hdmiphy_port;
171
172 /* current hdmiphy conf index */
173 int cur_conf;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500174 struct hdmi_v14_conf mode_conf;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900175
176 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900177
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530178 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530179
180 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900181};
182
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900183/* HDMI Version 1.3 */
184static const u8 hdmiphy_v13_conf27[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900185 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
186 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
187 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
188 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
189};
190
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900191static const u8 hdmiphy_v13_conf27_027[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900192 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
193 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
194 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
195 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
196};
197
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900198static const u8 hdmiphy_v13_conf74_175[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900199 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
200 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
201 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
202 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
203};
204
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900205static const u8 hdmiphy_v13_conf74_25[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900206 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
207 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
208 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
209 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
210};
211
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900212static const u8 hdmiphy_v13_conf148_5[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900213 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
214 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
215 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
216 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
217};
218
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900219struct hdmi_v13_tg_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900220 u8 cmd;
221 u8 h_fsz_l;
222 u8 h_fsz_h;
223 u8 hact_st_l;
224 u8 hact_st_h;
225 u8 hact_sz_l;
226 u8 hact_sz_h;
227 u8 v_fsz_l;
228 u8 v_fsz_h;
229 u8 vsync_l;
230 u8 vsync_h;
231 u8 vsync2_l;
232 u8 vsync2_h;
233 u8 vact_st_l;
234 u8 vact_st_h;
235 u8 vact_sz_l;
236 u8 vact_sz_h;
237 u8 field_chg_l;
238 u8 field_chg_h;
239 u8 vact_st2_l;
240 u8 vact_st2_h;
241 u8 vsync_top_hdmi_l;
242 u8 vsync_top_hdmi_h;
243 u8 vsync_bot_hdmi_l;
244 u8 vsync_bot_hdmi_h;
245 u8 field_top_hdmi_l;
246 u8 field_top_hdmi_h;
247 u8 field_bot_hdmi_l;
248 u8 field_bot_hdmi_h;
249};
250
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900251struct hdmi_v13_core_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900252 u8 h_blank[2];
253 u8 v_blank[3];
254 u8 h_v_line[3];
255 u8 vsync_pol[1];
256 u8 int_pro_mode[1];
257 u8 v_blank_f[3];
258 u8 h_sync_gen[3];
259 u8 v_sync_gen1[3];
260 u8 v_sync_gen2[3];
261 u8 v_sync_gen3[3];
262};
263
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900264struct hdmi_v13_preset_conf {
265 struct hdmi_v13_core_regs core;
266 struct hdmi_v13_tg_regs tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900267};
268
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900269struct hdmi_v13_conf {
270 int width;
271 int height;
272 int vrefresh;
273 bool interlace;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530274 int cea_video_id;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900275 const u8 *hdmiphy_data;
276 const struct hdmi_v13_preset_conf *conf;
277};
278
279static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900280 .core = {
281 .h_blank = {0x8a, 0x00},
282 .v_blank = {0x0d, 0x6a, 0x01},
283 .h_v_line = {0x0d, 0xa2, 0x35},
284 .vsync_pol = {0x01},
285 .int_pro_mode = {0x00},
286 .v_blank_f = {0x00, 0x00, 0x00},
287 .h_sync_gen = {0x0e, 0x30, 0x11},
288 .v_sync_gen1 = {0x0f, 0x90, 0x00},
289 /* other don't care */
290 },
291 .tg = {
292 0x00, /* cmd */
293 0x5a, 0x03, /* h_fsz */
294 0x8a, 0x00, 0xd0, 0x02, /* hact */
295 0x0d, 0x02, /* v_fsz */
296 0x01, 0x00, 0x33, 0x02, /* vsync */
297 0x2d, 0x00, 0xe0, 0x01, /* vact */
298 0x33, 0x02, /* field_chg */
299 0x49, 0x02, /* vact_st2 */
300 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
301 0x01, 0x00, 0x33, 0x02, /* field top/bot */
302 },
303};
304
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900305static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900306 .core = {
307 .h_blank = {0x72, 0x01},
308 .v_blank = {0xee, 0xf2, 0x00},
309 .h_v_line = {0xee, 0x22, 0x67},
310 .vsync_pol = {0x00},
311 .int_pro_mode = {0x00},
312 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
313 .h_sync_gen = {0x6c, 0x50, 0x02},
314 .v_sync_gen1 = {0x0a, 0x50, 0x00},
315 .v_sync_gen2 = {0x01, 0x10, 0x00},
316 .v_sync_gen3 = {0x01, 0x10, 0x00},
317 /* other don't care */
318 },
319 .tg = {
320 0x00, /* cmd */
321 0x72, 0x06, /* h_fsz */
322 0x71, 0x01, 0x01, 0x05, /* hact */
323 0xee, 0x02, /* v_fsz */
324 0x01, 0x00, 0x33, 0x02, /* vsync */
325 0x1e, 0x00, 0xd0, 0x02, /* vact */
326 0x33, 0x02, /* field_chg */
327 0x49, 0x02, /* vact_st2 */
328 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
329 0x01, 0x00, 0x33, 0x02, /* field top/bot */
330 },
331};
332
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900333static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900334 .core = {
335 .h_blank = {0xd0, 0x02},
336 .v_blank = {0x32, 0xB2, 0x00},
337 .h_v_line = {0x65, 0x04, 0xa5},
338 .vsync_pol = {0x00},
339 .int_pro_mode = {0x01},
340 .v_blank_f = {0x49, 0x2A, 0x23},
341 .h_sync_gen = {0x0E, 0xEA, 0x08},
342 .v_sync_gen1 = {0x07, 0x20, 0x00},
343 .v_sync_gen2 = {0x39, 0x42, 0x23},
344 .v_sync_gen3 = {0x38, 0x87, 0x73},
345 /* other don't care */
346 },
347 .tg = {
348 0x00, /* cmd */
349 0x50, 0x0A, /* h_fsz */
350 0xCF, 0x02, 0x81, 0x07, /* hact */
351 0x65, 0x04, /* v_fsz */
352 0x01, 0x00, 0x33, 0x02, /* vsync */
353 0x16, 0x00, 0x1c, 0x02, /* vact */
354 0x33, 0x02, /* field_chg */
355 0x49, 0x02, /* vact_st2 */
356 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
357 0x01, 0x00, 0x33, 0x02, /* field top/bot */
358 },
359};
360
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900361static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900362 .core = {
363 .h_blank = {0xd0, 0x02},
364 .v_blank = {0x65, 0x6c, 0x01},
365 .h_v_line = {0x65, 0x04, 0xa5},
366 .vsync_pol = {0x00},
367 .int_pro_mode = {0x00},
368 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
369 .h_sync_gen = {0x0e, 0xea, 0x08},
370 .v_sync_gen1 = {0x09, 0x40, 0x00},
371 .v_sync_gen2 = {0x01, 0x10, 0x00},
372 .v_sync_gen3 = {0x01, 0x10, 0x00},
373 /* other don't care */
374 },
375 .tg = {
376 0x00, /* cmd */
377 0x50, 0x0A, /* h_fsz */
378 0xCF, 0x02, 0x81, 0x07, /* hact */
379 0x65, 0x04, /* v_fsz */
380 0x01, 0x00, 0x33, 0x02, /* vsync */
381 0x2d, 0x00, 0x38, 0x04, /* vact */
382 0x33, 0x02, /* field_chg */
383 0x48, 0x02, /* vact_st2 */
384 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
385 0x01, 0x00, 0x33, 0x02, /* field top/bot */
386 },
387};
388
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900389static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900390 .core = {
391 .h_blank = {0x18, 0x01},
392 .v_blank = {0x32, 0xB2, 0x00},
393 .h_v_line = {0x65, 0x84, 0x89},
394 .vsync_pol = {0x00},
395 .int_pro_mode = {0x01},
396 .v_blank_f = {0x49, 0x2A, 0x23},
397 .h_sync_gen = {0x56, 0x08, 0x02},
398 .v_sync_gen1 = {0x07, 0x20, 0x00},
399 .v_sync_gen2 = {0x39, 0x42, 0x23},
400 .v_sync_gen3 = {0xa4, 0x44, 0x4a},
401 /* other don't care */
402 },
403 .tg = {
404 0x00, /* cmd */
405 0x98, 0x08, /* h_fsz */
406 0x17, 0x01, 0x81, 0x07, /* hact */
407 0x65, 0x04, /* v_fsz */
408 0x01, 0x00, 0x33, 0x02, /* vsync */
409 0x16, 0x00, 0x1c, 0x02, /* vact */
410 0x33, 0x02, /* field_chg */
411 0x49, 0x02, /* vact_st2 */
412 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
413 0x01, 0x00, 0x33, 0x02, /* field top/bot */
414 },
415};
416
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900417static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900418 .core = {
419 .h_blank = {0x18, 0x01},
420 .v_blank = {0x65, 0x6c, 0x01},
421 .h_v_line = {0x65, 0x84, 0x89},
422 .vsync_pol = {0x00},
423 .int_pro_mode = {0x00},
424 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
425 .h_sync_gen = {0x56, 0x08, 0x02},
426 .v_sync_gen1 = {0x09, 0x40, 0x00},
427 .v_sync_gen2 = {0x01, 0x10, 0x00},
428 .v_sync_gen3 = {0x01, 0x10, 0x00},
429 /* other don't care */
430 },
431 .tg = {
432 0x00, /* cmd */
433 0x98, 0x08, /* h_fsz */
434 0x17, 0x01, 0x81, 0x07, /* hact */
435 0x65, 0x04, /* v_fsz */
436 0x01, 0x00, 0x33, 0x02, /* vsync */
437 0x2d, 0x00, 0x38, 0x04, /* vact */
438 0x33, 0x02, /* field_chg */
439 0x48, 0x02, /* vact_st2 */
440 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
441 0x01, 0x00, 0x33, 0x02, /* field top/bot */
442 },
443};
444
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900445static const struct hdmi_v13_conf hdmi_v13_confs[] = {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530446 { 1280, 720, 60, false, 4, hdmiphy_v13_conf74_25,
447 &hdmi_v13_conf_720p60 },
448 { 1280, 720, 50, false, 19, hdmiphy_v13_conf74_25,
449 &hdmi_v13_conf_720p60 },
450 { 720, 480, 60, false, 3, hdmiphy_v13_conf27_027,
451 &hdmi_v13_conf_480p },
452 { 1920, 1080, 50, true, 20, hdmiphy_v13_conf74_25,
453 &hdmi_v13_conf_1080i50 },
454 { 1920, 1080, 50, false, 31, hdmiphy_v13_conf148_5,
455 &hdmi_v13_conf_1080p50 },
456 { 1920, 1080, 60, true, 5, hdmiphy_v13_conf74_25,
457 &hdmi_v13_conf_1080i60 },
458 { 1920, 1080, 60, false, 16, hdmiphy_v13_conf148_5,
459 &hdmi_v13_conf_1080p60 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900460};
461
462/* HDMI Version 1.4 */
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500463struct hdmiphy_config {
464 int pixel_clock;
465 u8 conf[32];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900466};
467
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500468/* list of all required phy config settings */
469static const struct hdmiphy_config hdmiphy_v14_configs[] = {
470 {
471 .pixel_clock = 25200000,
472 .conf = {
473 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
474 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
475 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
476 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
477 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900478 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500479 {
480 .pixel_clock = 27000000,
481 .conf = {
482 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
483 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
484 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
485 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
486 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900487 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500488 {
489 .pixel_clock = 27027000,
490 .conf = {
491 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
492 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
493 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
494 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
495 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900496 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500497 {
498 .pixel_clock = 36000000,
499 .conf = {
500 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
501 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
502 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
503 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
504 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900505 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500506 {
507 .pixel_clock = 40000000,
508 .conf = {
509 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
510 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
511 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
512 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
513 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900514 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500515 {
516 .pixel_clock = 65000000,
517 .conf = {
518 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
519 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
520 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
521 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
522 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900523 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500524 {
525 .pixel_clock = 74176000,
526 .conf = {
527 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
528 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
529 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
530 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
531 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900532 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500533 {
534 .pixel_clock = 74250000,
535 .conf = {
536 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
537 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
538 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
539 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
540 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900541 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500542 {
543 .pixel_clock = 83500000,
544 .conf = {
545 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
546 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
547 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
548 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
549 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900550 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500551 {
552 .pixel_clock = 106500000,
553 .conf = {
554 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
555 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
556 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
557 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
558 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900559 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500560 {
561 .pixel_clock = 108000000,
562 .conf = {
563 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
564 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
565 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
566 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
567 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900568 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500569 {
570 .pixel_clock = 146250000,
571 .conf = {
572 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
573 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
574 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
575 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
576 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900577 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500578 {
579 .pixel_clock = 148500000,
580 .conf = {
581 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
582 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
583 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
584 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
585 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900586 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900587};
588
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530589struct hdmi_infoframe {
590 enum HDMI_PACKET_TYPE type;
591 u8 ver;
592 u8 len;
593};
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900594
595static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
596{
597 return readl(hdata->regs + reg_id);
598}
599
600static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
601 u32 reg_id, u8 value)
602{
603 writeb(value, hdata->regs + reg_id);
604}
605
606static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
607 u32 reg_id, u32 value, u32 mask)
608{
609 u32 old = readl(hdata->regs + reg_id);
610 value = (value & mask) | (old & ~mask);
611 writel(value, hdata->regs + reg_id);
612}
613
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900614static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900615{
616#define DUMPREG(reg_id) \
617 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
618 readl(hdata->regs + reg_id))
619 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
620 DUMPREG(HDMI_INTC_FLAG);
621 DUMPREG(HDMI_INTC_CON);
622 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900623 DUMPREG(HDMI_V13_PHY_RSTOUT);
624 DUMPREG(HDMI_V13_PHY_VPLL);
625 DUMPREG(HDMI_V13_PHY_CMU);
626 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900627
628 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
629 DUMPREG(HDMI_CON_0);
630 DUMPREG(HDMI_CON_1);
631 DUMPREG(HDMI_CON_2);
632 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900633 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900634 DUMPREG(HDMI_STATUS_EN);
635 DUMPREG(HDMI_HPD);
636 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900637 DUMPREG(HDMI_V13_HPD_GEN);
638 DUMPREG(HDMI_V13_DC_CONTROL);
639 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900640
641 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
642 DUMPREG(HDMI_H_BLANK_0);
643 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900644 DUMPREG(HDMI_V13_V_BLANK_0);
645 DUMPREG(HDMI_V13_V_BLANK_1);
646 DUMPREG(HDMI_V13_V_BLANK_2);
647 DUMPREG(HDMI_V13_H_V_LINE_0);
648 DUMPREG(HDMI_V13_H_V_LINE_1);
649 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900650 DUMPREG(HDMI_VSYNC_POL);
651 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900652 DUMPREG(HDMI_V13_V_BLANK_F_0);
653 DUMPREG(HDMI_V13_V_BLANK_F_1);
654 DUMPREG(HDMI_V13_V_BLANK_F_2);
655 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
656 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
657 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
658 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
659 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
660 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
661 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
662 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
663 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
664 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
665 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
666 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900667
668 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
669 DUMPREG(HDMI_TG_CMD);
670 DUMPREG(HDMI_TG_H_FSZ_L);
671 DUMPREG(HDMI_TG_H_FSZ_H);
672 DUMPREG(HDMI_TG_HACT_ST_L);
673 DUMPREG(HDMI_TG_HACT_ST_H);
674 DUMPREG(HDMI_TG_HACT_SZ_L);
675 DUMPREG(HDMI_TG_HACT_SZ_H);
676 DUMPREG(HDMI_TG_V_FSZ_L);
677 DUMPREG(HDMI_TG_V_FSZ_H);
678 DUMPREG(HDMI_TG_VSYNC_L);
679 DUMPREG(HDMI_TG_VSYNC_H);
680 DUMPREG(HDMI_TG_VSYNC2_L);
681 DUMPREG(HDMI_TG_VSYNC2_H);
682 DUMPREG(HDMI_TG_VACT_ST_L);
683 DUMPREG(HDMI_TG_VACT_ST_H);
684 DUMPREG(HDMI_TG_VACT_SZ_L);
685 DUMPREG(HDMI_TG_VACT_SZ_H);
686 DUMPREG(HDMI_TG_FIELD_CHG_L);
687 DUMPREG(HDMI_TG_FIELD_CHG_H);
688 DUMPREG(HDMI_TG_VACT_ST2_L);
689 DUMPREG(HDMI_TG_VACT_ST2_H);
690 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
691 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
692 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
693 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
694 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
695 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
696 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
697 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
698#undef DUMPREG
699}
700
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900701static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
702{
703 int i;
704
705#define DUMPREG(reg_id) \
706 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
707 readl(hdata->regs + reg_id))
708
709 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
710 DUMPREG(HDMI_INTC_CON);
711 DUMPREG(HDMI_INTC_FLAG);
712 DUMPREG(HDMI_HPD_STATUS);
713 DUMPREG(HDMI_INTC_CON_1);
714 DUMPREG(HDMI_INTC_FLAG_1);
715 DUMPREG(HDMI_PHY_STATUS_0);
716 DUMPREG(HDMI_PHY_STATUS_PLL);
717 DUMPREG(HDMI_PHY_CON_0);
718 DUMPREG(HDMI_PHY_RSTOUT);
719 DUMPREG(HDMI_PHY_VPLL);
720 DUMPREG(HDMI_PHY_CMU);
721 DUMPREG(HDMI_CORE_RSTOUT);
722
723 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
724 DUMPREG(HDMI_CON_0);
725 DUMPREG(HDMI_CON_1);
726 DUMPREG(HDMI_CON_2);
727 DUMPREG(HDMI_SYS_STATUS);
728 DUMPREG(HDMI_PHY_STATUS_0);
729 DUMPREG(HDMI_STATUS_EN);
730 DUMPREG(HDMI_HPD);
731 DUMPREG(HDMI_MODE_SEL);
732 DUMPREG(HDMI_ENC_EN);
733 DUMPREG(HDMI_DC_CONTROL);
734 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
735
736 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
737 DUMPREG(HDMI_H_BLANK_0);
738 DUMPREG(HDMI_H_BLANK_1);
739 DUMPREG(HDMI_V2_BLANK_0);
740 DUMPREG(HDMI_V2_BLANK_1);
741 DUMPREG(HDMI_V1_BLANK_0);
742 DUMPREG(HDMI_V1_BLANK_1);
743 DUMPREG(HDMI_V_LINE_0);
744 DUMPREG(HDMI_V_LINE_1);
745 DUMPREG(HDMI_H_LINE_0);
746 DUMPREG(HDMI_H_LINE_1);
747 DUMPREG(HDMI_HSYNC_POL);
748
749 DUMPREG(HDMI_VSYNC_POL);
750 DUMPREG(HDMI_INT_PRO_MODE);
751 DUMPREG(HDMI_V_BLANK_F0_0);
752 DUMPREG(HDMI_V_BLANK_F0_1);
753 DUMPREG(HDMI_V_BLANK_F1_0);
754 DUMPREG(HDMI_V_BLANK_F1_1);
755
756 DUMPREG(HDMI_H_SYNC_START_0);
757 DUMPREG(HDMI_H_SYNC_START_1);
758 DUMPREG(HDMI_H_SYNC_END_0);
759 DUMPREG(HDMI_H_SYNC_END_1);
760
761 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
762 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
763 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
764 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
765
766 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
767 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
768 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
769 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
770
771 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
772 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
773 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
774 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
775
776 DUMPREG(HDMI_V_BLANK_F2_0);
777 DUMPREG(HDMI_V_BLANK_F2_1);
778 DUMPREG(HDMI_V_BLANK_F3_0);
779 DUMPREG(HDMI_V_BLANK_F3_1);
780 DUMPREG(HDMI_V_BLANK_F4_0);
781 DUMPREG(HDMI_V_BLANK_F4_1);
782 DUMPREG(HDMI_V_BLANK_F5_0);
783 DUMPREG(HDMI_V_BLANK_F5_1);
784
785 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
786 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
787 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
788 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
789 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
790 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
791 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
792 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
793
794 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
795 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
796 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
797 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
798 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
799 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
800 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
801 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
802
803 DUMPREG(HDMI_VACT_SPACE_1_0);
804 DUMPREG(HDMI_VACT_SPACE_1_1);
805 DUMPREG(HDMI_VACT_SPACE_2_0);
806 DUMPREG(HDMI_VACT_SPACE_2_1);
807 DUMPREG(HDMI_VACT_SPACE_3_0);
808 DUMPREG(HDMI_VACT_SPACE_3_1);
809 DUMPREG(HDMI_VACT_SPACE_4_0);
810 DUMPREG(HDMI_VACT_SPACE_4_1);
811 DUMPREG(HDMI_VACT_SPACE_5_0);
812 DUMPREG(HDMI_VACT_SPACE_5_1);
813 DUMPREG(HDMI_VACT_SPACE_6_0);
814 DUMPREG(HDMI_VACT_SPACE_6_1);
815
816 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
817 DUMPREG(HDMI_TG_CMD);
818 DUMPREG(HDMI_TG_H_FSZ_L);
819 DUMPREG(HDMI_TG_H_FSZ_H);
820 DUMPREG(HDMI_TG_HACT_ST_L);
821 DUMPREG(HDMI_TG_HACT_ST_H);
822 DUMPREG(HDMI_TG_HACT_SZ_L);
823 DUMPREG(HDMI_TG_HACT_SZ_H);
824 DUMPREG(HDMI_TG_V_FSZ_L);
825 DUMPREG(HDMI_TG_V_FSZ_H);
826 DUMPREG(HDMI_TG_VSYNC_L);
827 DUMPREG(HDMI_TG_VSYNC_H);
828 DUMPREG(HDMI_TG_VSYNC2_L);
829 DUMPREG(HDMI_TG_VSYNC2_H);
830 DUMPREG(HDMI_TG_VACT_ST_L);
831 DUMPREG(HDMI_TG_VACT_ST_H);
832 DUMPREG(HDMI_TG_VACT_SZ_L);
833 DUMPREG(HDMI_TG_VACT_SZ_H);
834 DUMPREG(HDMI_TG_FIELD_CHG_L);
835 DUMPREG(HDMI_TG_FIELD_CHG_H);
836 DUMPREG(HDMI_TG_VACT_ST2_L);
837 DUMPREG(HDMI_TG_VACT_ST2_H);
838 DUMPREG(HDMI_TG_VACT_ST3_L);
839 DUMPREG(HDMI_TG_VACT_ST3_H);
840 DUMPREG(HDMI_TG_VACT_ST4_L);
841 DUMPREG(HDMI_TG_VACT_ST4_H);
842 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
843 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
844 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
845 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
846 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
847 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
848 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
849 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
850 DUMPREG(HDMI_TG_3D);
851
852 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
853 DUMPREG(HDMI_AVI_CON);
854 DUMPREG(HDMI_AVI_HEADER0);
855 DUMPREG(HDMI_AVI_HEADER1);
856 DUMPREG(HDMI_AVI_HEADER2);
857 DUMPREG(HDMI_AVI_CHECK_SUM);
858 DUMPREG(HDMI_VSI_CON);
859 DUMPREG(HDMI_VSI_HEADER0);
860 DUMPREG(HDMI_VSI_HEADER1);
861 DUMPREG(HDMI_VSI_HEADER2);
862 for (i = 0; i < 7; ++i)
863 DUMPREG(HDMI_VSI_DATA(i));
864
865#undef DUMPREG
866}
867
868static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
869{
Rahul Sharma5a325072012-10-04 20:48:54 +0530870 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900871 hdmi_v13_regs_dump(hdata, prefix);
872 else
873 hdmi_v14_regs_dump(hdata, prefix);
874}
875
876static int hdmi_v13_conf_index(struct drm_display_mode *mode)
877{
878 int i;
879
880 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
881 if (hdmi_v13_confs[i].width == mode->hdisplay &&
882 hdmi_v13_confs[i].height == mode->vdisplay &&
883 hdmi_v13_confs[i].vrefresh == mode->vrefresh &&
884 hdmi_v13_confs[i].interlace ==
885 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
886 true : false))
887 return i;
888
Inki Dae1de425b2012-03-16 18:47:04 +0900889 return -EINVAL;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900890}
891
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530892static u8 hdmi_chksum(struct hdmi_context *hdata,
893 u32 start, u8 len, u32 hdr_sum)
894{
895 int i;
896
897 /* hdr_sum : header0 + header1 + header2
898 * start : start address of packet byte1
899 * len : packet bytes - 1 */
900 for (i = 0; i < len; ++i)
901 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
902
903 /* return 2's complement of 8 bit hdr_sum */
904 return (u8)(~(hdr_sum & 0xff) + 1);
905}
906
907static void hdmi_reg_infoframe(struct hdmi_context *hdata,
908 struct hdmi_infoframe *infoframe)
909{
910 u32 hdr_sum;
911 u8 chksum;
912 u32 aspect_ratio;
913 u32 mod;
914 u32 vic;
915
916 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
917
918 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
919 if (hdata->dvi_mode) {
920 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
921 HDMI_VSI_CON_DO_NOT_TRANSMIT);
922 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
923 HDMI_AVI_CON_DO_NOT_TRANSMIT);
924 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
925 return;
926 }
927
928 switch (infoframe->type) {
929 case HDMI_PACKET_TYPE_AVI:
930 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
931 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type);
932 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver);
933 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len);
934 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
935
936 /* Output format zero hardcoded ,RGB YBCR selection */
937 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
938 AVI_ACTIVE_FORMAT_VALID |
939 AVI_UNDERSCANNED_DISPLAY_VALID);
940
941 aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9;
942
943 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio |
944 AVI_SAME_AS_PIC_ASPECT_RATIO);
945
946 if (hdata->type == HDMI_TYPE13)
947 vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id;
948 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500949 vic = hdata->mode_conf.cea_video_id;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530950
951 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
952
953 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
954 infoframe->len, hdr_sum);
955 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
956 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
957 break;
958 case HDMI_PACKET_TYPE_AUI:
959 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
960 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type);
961 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver);
962 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len);
963 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
964 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
965 infoframe->len, hdr_sum);
966 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
967 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
968 break;
969 default:
970 break;
971 }
972}
973
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900974static bool hdmi_is_connected(void *ctx)
975{
Joonyoung Shimf9309d12012-04-05 20:49:22 +0900976 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900977
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900978 return hdata->hpd;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900979}
980
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500981static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900982{
983 struct edid *raw_edid;
Joonyoung Shimf9309d12012-04-05 20:49:22 +0900984 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900985
986 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
987
988 if (!hdata->ddc_port)
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500989 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900990
991 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500992 if (!raw_edid)
993 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900994
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500995 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
996 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
997 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
998 raw_edid->width_cm, raw_edid->height_cm);
999
1000 return raw_edid;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001001}
1002
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001003static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001004{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001005 int i;
1006
Inki Dae1de425b2012-03-16 18:47:04 +09001007 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1008 check_timing->xres, check_timing->yres,
1009 check_timing->refresh, (check_timing->vmode &
1010 FB_VMODE_INTERLACED) ? true : false);
1011
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001012 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1013 if (hdmi_v13_confs[i].width == check_timing->xres &&
1014 hdmi_v13_confs[i].height == check_timing->yres &&
1015 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1016 hdmi_v13_confs[i].interlace ==
1017 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1018 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001019 return 0;
1020
1021 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001022
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001023 return -EINVAL;
1024}
1025
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001026static int hdmi_v14_find_phy_conf(int pixel_clock)
1027{
1028 int i;
1029
1030 for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++) {
1031 if (hdmiphy_v14_configs[i].pixel_clock == pixel_clock)
1032 return i;
1033 }
1034
1035 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
1036 return -EINVAL;
1037}
1038
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001039static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1040{
1041 int i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001042
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001043 DRM_DEBUG_KMS("mode: xres=%d, yres=%d, refresh=%d, clock=%d, intl=%d\n",
Inki Dae1de425b2012-03-16 18:47:04 +09001044 check_timing->xres, check_timing->yres,
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001045 check_timing->refresh, check_timing->pixclock,
1046 (check_timing->vmode & FB_VMODE_INTERLACED) ?
1047 true : false);
Inki Dae1de425b2012-03-16 18:47:04 +09001048
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001049 for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++)
1050 if (hdmiphy_v14_configs[i].pixel_clock ==
1051 check_timing->pixclock)
1052 return 0;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001053
1054 return -EINVAL;
1055}
1056
Rahul Sharma438c0f82013-01-15 08:11:05 -05001057static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001058{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001059 struct hdmi_context *hdata = ctx;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001060
1061 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1062
Rahul Sharma438c0f82013-01-15 08:11:05 -05001063 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres,
1064 timing->yres, timing->refresh,
1065 timing->vmode);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001066
Rahul Sharma5a325072012-10-04 20:48:54 +05301067 if (hdata->type == HDMI_TYPE13)
Rahul Sharma438c0f82013-01-15 08:11:05 -05001068 return hdmi_v13_check_timing(timing);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001069 else
Rahul Sharma438c0f82013-01-15 08:11:05 -05001070 return hdmi_v14_check_timing(timing);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001071}
1072
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001073static void hdmi_set_acr(u32 freq, u8 *acr)
1074{
1075 u32 n, cts;
1076
1077 switch (freq) {
1078 case 32000:
1079 n = 4096;
1080 cts = 27000;
1081 break;
1082 case 44100:
1083 n = 6272;
1084 cts = 30000;
1085 break;
1086 case 88200:
1087 n = 12544;
1088 cts = 30000;
1089 break;
1090 case 176400:
1091 n = 25088;
1092 cts = 30000;
1093 break;
1094 case 48000:
1095 n = 6144;
1096 cts = 27000;
1097 break;
1098 case 96000:
1099 n = 12288;
1100 cts = 27000;
1101 break;
1102 case 192000:
1103 n = 24576;
1104 cts = 27000;
1105 break;
1106 default:
1107 n = 0;
1108 cts = 0;
1109 break;
1110 }
1111
1112 acr[1] = cts >> 16;
1113 acr[2] = cts >> 8 & 0xff;
1114 acr[3] = cts & 0xff;
1115
1116 acr[4] = n >> 16;
1117 acr[5] = n >> 8 & 0xff;
1118 acr[6] = n & 0xff;
1119}
1120
1121static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1122{
1123 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1124 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1125 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1126 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1127 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1128 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1129 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1130 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1131 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1132
Rahul Sharma5a325072012-10-04 20:48:54 +05301133 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001134 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1135 else
1136 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1137}
1138
1139static void hdmi_audio_init(struct hdmi_context *hdata)
1140{
1141 u32 sample_rate, bits_per_sample, frame_size_code;
1142 u32 data_num, bit_ch, sample_frq;
1143 u32 val;
1144 u8 acr[7];
1145
1146 sample_rate = 44100;
1147 bits_per_sample = 16;
1148 frame_size_code = 0;
1149
1150 switch (bits_per_sample) {
1151 case 20:
1152 data_num = 2;
1153 bit_ch = 1;
1154 break;
1155 case 24:
1156 data_num = 3;
1157 bit_ch = 1;
1158 break;
1159 default:
1160 data_num = 1;
1161 bit_ch = 0;
1162 break;
1163 }
1164
1165 hdmi_set_acr(sample_rate, acr);
1166 hdmi_reg_acr(hdata, acr);
1167
1168 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1169 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1170 | HDMI_I2S_MUX_ENABLE);
1171
1172 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1173 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1174
1175 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1176
1177 sample_frq = (sample_rate == 44100) ? 0 :
1178 (sample_rate == 48000) ? 2 :
1179 (sample_rate == 32000) ? 3 :
1180 (sample_rate == 96000) ? 0xa : 0x0;
1181
1182 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1183 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1184
1185 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1186 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1187
1188 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1189 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1190 | HDMI_I2S_SEL_LRCK(6));
1191 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1192 | HDMI_I2S_SEL_SDATA2(4));
1193 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1194 | HDMI_I2S_SEL_SDATA2(2));
1195 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1196
1197 /* I2S_CON_1 & 2 */
1198 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1199 | HDMI_I2S_L_CH_LOW_POL);
1200 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1201 | HDMI_I2S_SET_BIT_CH(bit_ch)
1202 | HDMI_I2S_SET_SDATA_BIT(data_num)
1203 | HDMI_I2S_BASIC_FORMAT);
1204
1205 /* Configure register related to CUV information */
1206 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1207 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1208 | HDMI_I2S_COPYRIGHT
1209 | HDMI_I2S_LINEAR_PCM
1210 | HDMI_I2S_CONSUMER_FORMAT);
1211 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1212 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1213 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1214 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1215 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1216 HDMI_I2S_ORG_SMP_FREQ_44_1
1217 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1218 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1219
1220 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1221}
1222
1223static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1224{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001225 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001226 return;
1227
1228 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1229 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1230 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1231}
1232
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001233static void hdmi_conf_reset(struct hdmi_context *hdata)
1234{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001235 u32 reg;
1236
Rahul Sharma5a325072012-10-04 20:48:54 +05301237 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001238 reg = HDMI_V13_CORE_RSTOUT;
1239 else
1240 reg = HDMI_CORE_RSTOUT;
1241
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001242 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001243 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001244 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001245 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001246 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001247}
1248
1249static void hdmi_conf_init(struct hdmi_context *hdata)
1250{
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301251 struct hdmi_infoframe infoframe;
1252
Sean Paul77006a72013-01-16 10:17:20 -05001253 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001254 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1255 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001256
1257 /* choose HDMI mode */
1258 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1259 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1260 /* disable bluescreen */
1261 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001262
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001263 if (hdata->dvi_mode) {
1264 /* choose DVI mode */
1265 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1266 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1267 hdmi_reg_writeb(hdata, HDMI_CON_2,
1268 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1269 }
1270
Rahul Sharma5a325072012-10-04 20:48:54 +05301271 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001272 /* choose bluescreen (fecal) color */
1273 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1274 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1275 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1276
1277 /* enable AVI packet every vsync, fixes purple line problem */
1278 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1279 /* force RGB, look to CEA-861-D, table 7 for more detail */
1280 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1281 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1282
1283 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1284 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1285 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1286 } else {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301287 infoframe.type = HDMI_PACKET_TYPE_AVI;
1288 infoframe.ver = HDMI_AVI_VERSION;
1289 infoframe.len = HDMI_AVI_LENGTH;
1290 hdmi_reg_infoframe(hdata, &infoframe);
1291
1292 infoframe.type = HDMI_PACKET_TYPE_AUI;
1293 infoframe.ver = HDMI_AUI_VERSION;
1294 infoframe.len = HDMI_AUI_LENGTH;
1295 hdmi_reg_infoframe(hdata, &infoframe);
1296
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001297 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001298 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1299 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001300}
1301
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001302static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001303{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001304 const struct hdmi_v13_preset_conf *conf =
1305 hdmi_v13_confs[hdata->cur_conf].conf;
1306 const struct hdmi_v13_core_regs *core = &conf->core;
1307 const struct hdmi_v13_tg_regs *tg = &conf->tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001308 int tries;
1309
1310 /* setting core registers */
1311 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1312 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001313 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1314 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1315 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1316 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1317 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1318 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001319 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1320 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001321 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1322 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1323 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1324 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1325 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1326 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1327 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1328 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1329 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1330 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1331 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1332 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1333 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1334 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1335 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001336 /* Timing generator registers */
1337 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1338 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1339 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1340 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1341 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1342 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1343 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1344 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1345 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1346 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1347 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1348 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1349 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1350 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1351 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1352 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1353 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1354 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1355 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1356 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1357 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1358 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1359 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1360 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1361 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1362 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1363 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1364 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1365
1366 /* waiting for HDMIPHY's PLL to get to steady state */
1367 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001368 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001369 if (val & HDMI_PHY_STATUS_READY)
1370 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001371 usleep_range(1000, 2000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001372 }
1373 /* steady state not achieved */
1374 if (tries == 0) {
1375 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1376 hdmi_regs_dump(hdata, "timing apply");
1377 }
1378
1379 clk_disable(hdata->res.sclk_hdmi);
1380 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1381 clk_enable(hdata->res.sclk_hdmi);
1382
1383 /* enable HDMI and timing generator */
1384 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1385 if (core->int_pro_mode[0])
1386 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1387 HDMI_FIELD_EN);
1388 else
1389 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1390}
1391
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001392static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1393{
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001394 struct hdmi_core_regs *core = &hdata->mode_conf.core;
1395 struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001396 int tries;
1397
1398 /* setting core registers */
1399 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1400 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1401 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1402 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1403 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1404 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1405 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1406 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1407 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1408 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1409 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1410 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1411 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1412 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1413 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1414 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1415 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1416 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1417 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1418 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1419 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1420 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1421 core->v_sync_line_bef_2[0]);
1422 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1423 core->v_sync_line_bef_2[1]);
1424 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1425 core->v_sync_line_bef_1[0]);
1426 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1427 core->v_sync_line_bef_1[1]);
1428 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1429 core->v_sync_line_aft_2[0]);
1430 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1431 core->v_sync_line_aft_2[1]);
1432 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1433 core->v_sync_line_aft_1[0]);
1434 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1435 core->v_sync_line_aft_1[1]);
1436 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1437 core->v_sync_line_aft_pxl_2[0]);
1438 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1439 core->v_sync_line_aft_pxl_2[1]);
1440 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1441 core->v_sync_line_aft_pxl_1[0]);
1442 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1443 core->v_sync_line_aft_pxl_1[1]);
1444 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1445 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1446 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1447 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1448 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1449 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1450 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1451 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1452 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1453 core->v_sync_line_aft_3[0]);
1454 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1455 core->v_sync_line_aft_3[1]);
1456 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1457 core->v_sync_line_aft_4[0]);
1458 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1459 core->v_sync_line_aft_4[1]);
1460 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1461 core->v_sync_line_aft_5[0]);
1462 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1463 core->v_sync_line_aft_5[1]);
1464 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1465 core->v_sync_line_aft_6[0]);
1466 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1467 core->v_sync_line_aft_6[1]);
1468 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1469 core->v_sync_line_aft_pxl_3[0]);
1470 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1471 core->v_sync_line_aft_pxl_3[1]);
1472 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1473 core->v_sync_line_aft_pxl_4[0]);
1474 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1475 core->v_sync_line_aft_pxl_4[1]);
1476 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1477 core->v_sync_line_aft_pxl_5[0]);
1478 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1479 core->v_sync_line_aft_pxl_5[1]);
1480 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1481 core->v_sync_line_aft_pxl_6[0]);
1482 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1483 core->v_sync_line_aft_pxl_6[1]);
1484 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1485 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1486 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1487 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1488 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1489 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1490 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1491 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1492 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1493 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1494 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1495 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1496
1497 /* Timing generator registers */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001498 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1499 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1500 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1501 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1502 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1503 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1504 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1505 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1506 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1507 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1508 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1509 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1510 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1511 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1512 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1513 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1514 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1515 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1516 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1517 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1518 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
1519 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
1520 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
1521 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
1522 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1523 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1524 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1525 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1526 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1527 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1528 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1529 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1530 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001531
1532 /* waiting for HDMIPHY's PLL to get to steady state */
1533 for (tries = 100; tries; --tries) {
1534 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1535 if (val & HDMI_PHY_STATUS_READY)
1536 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001537 usleep_range(1000, 2000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001538 }
1539 /* steady state not achieved */
1540 if (tries == 0) {
1541 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1542 hdmi_regs_dump(hdata, "timing apply");
1543 }
1544
1545 clk_disable(hdata->res.sclk_hdmi);
1546 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1547 clk_enable(hdata->res.sclk_hdmi);
1548
1549 /* enable HDMI and timing generator */
1550 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1551 if (core->int_pro_mode[0])
1552 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1553 HDMI_FIELD_EN);
1554 else
1555 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1556}
1557
1558static void hdmi_timing_apply(struct hdmi_context *hdata)
1559{
Rahul Sharma5a325072012-10-04 20:48:54 +05301560 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001561 hdmi_v13_timing_apply(hdata);
1562 else
1563 hdmi_v14_timing_apply(hdata);
1564}
1565
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001566static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1567{
1568 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001569 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001570
1571 clk_disable(hdata->res.sclk_hdmi);
1572 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1573 clk_enable(hdata->res.sclk_hdmi);
1574
1575 /* operation mode */
1576 buffer[0] = 0x1f;
1577 buffer[1] = 0x00;
1578
1579 if (hdata->hdmiphy_port)
1580 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1581
Rahul Sharma5a325072012-10-04 20:48:54 +05301582 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001583 reg = HDMI_V13_PHY_RSTOUT;
1584 else
1585 reg = HDMI_PHY_RSTOUT;
1586
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001587 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001588 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001589 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001590 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001591 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001592}
1593
Rahul Sharmaa5562252012-11-28 11:30:25 +05301594static void hdmiphy_poweron(struct hdmi_context *hdata)
1595{
1596 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1597
1598 if (hdata->type == HDMI_TYPE14)
1599 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
1600 HDMI_PHY_POWER_OFF_EN);
1601}
1602
1603static void hdmiphy_poweroff(struct hdmi_context *hdata)
1604{
1605 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1606
1607 if (hdata->type == HDMI_TYPE14)
1608 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
1609 HDMI_PHY_POWER_OFF_EN);
1610}
1611
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001612static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1613{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001614 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001615 u8 buffer[32];
1616 u8 operation[2];
1617 u8 read_buffer[32] = {0, };
1618 int ret;
1619 int i;
1620
1621 if (!hdata->hdmiphy_port) {
1622 DRM_ERROR("hdmiphy is not attached\n");
1623 return;
1624 }
1625
1626 /* pixel clock */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001627 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001628 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001629 } else {
1630 i = hdmi_v14_find_phy_conf(hdata->mode_conf.pixel_clock);
1631 if (i < 0) {
1632 DRM_ERROR("failed to find hdmiphy conf\n");
1633 return;
1634 }
1635
1636 hdmiphy_data = hdmiphy_v14_configs[i].conf;
1637 }
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001638
1639 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001640 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1641 if (ret != 32) {
1642 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1643 return;
1644 }
1645
Sean Paul09760ea2013-01-14 17:03:20 -05001646 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001647
1648 /* operation mode */
1649 operation[0] = 0x1f;
1650 operation[1] = 0x80;
1651
1652 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1653 if (ret != 2) {
1654 DRM_ERROR("failed to enable hdmiphy\n");
1655 return;
1656 }
1657
1658 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1659 if (ret < 0) {
1660 DRM_ERROR("failed to read hdmiphy config\n");
1661 return;
1662 }
1663
1664 for (i = 0; i < ret; i++)
1665 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1666 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1667}
1668
1669static void hdmi_conf_apply(struct hdmi_context *hdata)
1670{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001671 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1672
1673 hdmiphy_conf_reset(hdata);
1674 hdmiphy_conf_apply(hdata);
1675
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001676 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001677 hdmi_conf_reset(hdata);
1678 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001679 mutex_unlock(&hdata->hdmi_mutex);
1680
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001681 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001682
1683 /* setting core registers */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001684 hdmi_timing_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001685 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001686
1687 hdmi_regs_dump(hdata, "start");
1688}
1689
Inki Dae1de425b2012-03-16 18:47:04 +09001690static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
Laurent Pincharte811f5a2012-07-17 17:56:50 +02001691 const struct drm_display_mode *mode,
Inki Dae1de425b2012-03-16 18:47:04 +09001692 struct drm_display_mode *adjusted_mode)
1693{
1694 struct drm_display_mode *m;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001695 struct hdmi_context *hdata = ctx;
Inki Dae1de425b2012-03-16 18:47:04 +09001696 int index;
1697
1698 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1699
1700 drm_mode_set_crtcinfo(adjusted_mode, 0);
1701
Rahul Sharma5a325072012-10-04 20:48:54 +05301702 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09001703 index = hdmi_v13_conf_index(adjusted_mode);
1704 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001705 index = hdmi_v14_find_phy_conf(adjusted_mode->clock * 1000);
Inki Dae1de425b2012-03-16 18:47:04 +09001706
1707 /* just return if user desired mode exists. */
1708 if (index >= 0)
1709 return;
1710
1711 /*
1712 * otherwise, find the most suitable mode among modes and change it
1713 * to adjusted_mode.
1714 */
1715 list_for_each_entry(m, &connector->modes, head) {
Rahul Sharma5a325072012-10-04 20:48:54 +05301716 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09001717 index = hdmi_v13_conf_index(m);
1718 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001719 index = hdmi_v14_find_phy_conf(m->clock * 1000);
Inki Dae1de425b2012-03-16 18:47:04 +09001720
1721 if (index >= 0) {
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05301722 struct drm_mode_object base;
1723 struct list_head head;
1724
Inki Dae1de425b2012-03-16 18:47:04 +09001725 DRM_INFO("desired mode doesn't exist so\n");
1726 DRM_INFO("use the most suitable mode among modes.\n");
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05301727
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001728 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
1729 m->hdisplay, m->vdisplay, m->vrefresh);
1730
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05301731 /* preserve display mode header while copying. */
1732 head = adjusted_mode->head;
1733 base = adjusted_mode->base;
Inki Dae1de425b2012-03-16 18:47:04 +09001734 memcpy(adjusted_mode, m, sizeof(*m));
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05301735 adjusted_mode->head = head;
1736 adjusted_mode->base = base;
Inki Dae1de425b2012-03-16 18:47:04 +09001737 break;
1738 }
1739 }
1740}
1741
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001742static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1743{
1744 int i;
1745 BUG_ON(num_bytes > 4);
1746 for (i = 0; i < num_bytes; i++)
1747 reg_pair[i] = (value >> (8 * i)) & 0xff;
1748}
1749
1750static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1751 struct drm_display_mode *m)
1752{
1753 struct hdmi_core_regs *core = &hdata->mode_conf.core;
1754 struct hdmi_tg_regs *tg = &hdata->mode_conf.tg;
1755
1756 hdata->mode_conf.cea_video_id = drm_match_cea_mode(m);
1757
1758 hdata->mode_conf.pixel_clock = m->clock * 1000;
1759 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1760 hdmi_set_reg(core->v_line, 2, m->vtotal);
1761 hdmi_set_reg(core->h_line, 2, m->htotal);
1762 hdmi_set_reg(core->hsync_pol, 1,
1763 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1764 hdmi_set_reg(core->vsync_pol, 1,
1765 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1766 hdmi_set_reg(core->int_pro_mode, 1,
1767 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1768
1769 /*
1770 * Quirk requirement for exynos 5 HDMI IP design,
1771 * 2 pixels less than the actual calculation for hsync_start
1772 * and end.
1773 */
1774
1775 /* Following values & calculations differ for different type of modes */
1776 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1777 /* Interlaced Mode */
1778 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1779 (m->vsync_end - m->vdisplay) / 2);
1780 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1781 (m->vsync_start - m->vdisplay) / 2);
1782 hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
1783 hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
1784 hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal +
1785 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2);
1786 hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
1787 hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
1788 hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
1789 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
1790 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1791 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
1792 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1793 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1794 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1795 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1796 hdmi_set_reg(tg->vact_st3, 2, 0x0);
1797 hdmi_set_reg(tg->vact_st4, 2, 0x0);
1798 } else {
1799 /* Progressive Mode */
1800 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1801 m->vsync_end - m->vdisplay);
1802 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1803 m->vsync_start - m->vdisplay);
1804 hdmi_set_reg(core->v2_blank, 2, m->vtotal);
1805 hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
1806 hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
1807 hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
1808 hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
1809 hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
1810 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
1811 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
1812 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1813 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1814 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1815 hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
1816 hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
1817 }
1818
1819 /* Following values & calculations are same irrespective of mode type */
1820 hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
1821 hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
1822 hdmi_set_reg(core->vact_space_1, 2, 0xffff);
1823 hdmi_set_reg(core->vact_space_2, 2, 0xffff);
1824 hdmi_set_reg(core->vact_space_3, 2, 0xffff);
1825 hdmi_set_reg(core->vact_space_4, 2, 0xffff);
1826 hdmi_set_reg(core->vact_space_5, 2, 0xffff);
1827 hdmi_set_reg(core->vact_space_6, 2, 0xffff);
1828 hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
1829 hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
1830 hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
1831 hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
1832 hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
1833 hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
1834 hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
1835 hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
1836 hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
1837 hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
1838 hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
1839 hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
1840
1841 /* Timing generator registers */
1842 hdmi_set_reg(tg->cmd, 1, 0x0);
1843 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1844 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1845 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1846 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1847 hdmi_set_reg(tg->vsync, 2, 0x1);
1848 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1849 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1850 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1851 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1852 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1853 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1854 hdmi_set_reg(tg->tg_3d, 1, 0x0);
1855
1856}
1857
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001858static void hdmi_mode_set(void *ctx, void *mode)
1859{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001860 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001861 int conf_idx;
1862
1863 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1864
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001865 if (hdata->type == HDMI_TYPE13) {
1866 conf_idx = hdmi_v13_conf_index(mode);
1867 if (conf_idx >= 0)
1868 hdata->cur_conf = conf_idx;
1869 else
1870 DRM_DEBUG_KMS("not supported mode\n");
1871 } else {
1872 hdmi_v14_mode_set(hdata, mode);
1873 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001874}
1875
Inki Dae1de425b2012-03-16 18:47:04 +09001876static void hdmi_get_max_resol(void *ctx, unsigned int *width,
1877 unsigned int *height)
1878{
1879 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1880
1881 *width = MAX_WIDTH;
1882 *height = MAX_HEIGHT;
1883}
1884
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001885static void hdmi_commit(void *ctx)
1886{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001887 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001888
1889 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1890
Shirish Sdda90122013-01-23 22:03:18 -05001891 mutex_lock(&hdata->hdmi_mutex);
1892 if (!hdata->powered) {
1893 mutex_unlock(&hdata->hdmi_mutex);
1894 return;
1895 }
1896 mutex_unlock(&hdata->hdmi_mutex);
1897
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001898 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001899}
1900
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001901static void hdmi_poweron(struct hdmi_context *hdata)
1902{
1903 struct hdmi_resources *res = &hdata->res;
1904
1905 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1906
1907 mutex_lock(&hdata->hdmi_mutex);
1908 if (hdata->powered) {
1909 mutex_unlock(&hdata->hdmi_mutex);
1910 return;
1911 }
1912
1913 hdata->powered = true;
1914
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001915 mutex_unlock(&hdata->hdmi_mutex);
1916
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001917 regulator_bulk_enable(res->regul_count, res->regul_bulk);
1918 clk_enable(res->hdmiphy);
1919 clk_enable(res->hdmi);
1920 clk_enable(res->sclk_hdmi);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301921
1922 hdmiphy_poweron(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001923}
1924
1925static void hdmi_poweroff(struct hdmi_context *hdata)
1926{
1927 struct hdmi_resources *res = &hdata->res;
1928
1929 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1930
1931 mutex_lock(&hdata->hdmi_mutex);
1932 if (!hdata->powered)
1933 goto out;
1934 mutex_unlock(&hdata->hdmi_mutex);
1935
1936 /*
1937 * The TV power domain needs any condition of hdmiphy to turn off and
1938 * its reset state seems to meet the condition.
1939 */
1940 hdmiphy_conf_reset(hdata);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301941 hdmiphy_poweroff(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001942
1943 clk_disable(res->sclk_hdmi);
1944 clk_disable(res->hdmi);
1945 clk_disable(res->hdmiphy);
1946 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1947
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001948 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001949
1950 hdata->powered = false;
1951
1952out:
1953 mutex_unlock(&hdata->hdmi_mutex);
1954}
1955
1956static void hdmi_dpms(void *ctx, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001957{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001958 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001959
Rahul Sharma64327cb2012-11-28 11:30:23 +05301960 DRM_DEBUG_KMS("[%d] %s mode %d\n", __LINE__, __func__, mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001961
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001962 switch (mode) {
1963 case DRM_MODE_DPMS_ON:
Rahul Sharma64327cb2012-11-28 11:30:23 +05301964 if (pm_runtime_suspended(hdata->dev))
1965 pm_runtime_get_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001966 break;
1967 case DRM_MODE_DPMS_STANDBY:
1968 case DRM_MODE_DPMS_SUSPEND:
1969 case DRM_MODE_DPMS_OFF:
Rahul Sharma64327cb2012-11-28 11:30:23 +05301970 if (!pm_runtime_suspended(hdata->dev))
1971 pm_runtime_put_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001972 break;
1973 default:
1974 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1975 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001976 }
1977}
1978
Joonyoung Shim578b6062012-04-05 20:49:26 +09001979static struct exynos_hdmi_ops hdmi_ops = {
1980 /* display */
1981 .is_connected = hdmi_is_connected,
1982 .get_edid = hdmi_get_edid,
1983 .check_timing = hdmi_check_timing,
Joonyoung Shim578b6062012-04-05 20:49:26 +09001984
1985 /* manager */
Inki Dae1de425b2012-03-16 18:47:04 +09001986 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001987 .mode_set = hdmi_mode_set,
Inki Dae1de425b2012-03-16 18:47:04 +09001988 .get_max_resol = hdmi_get_max_resol,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001989 .commit = hdmi_commit,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001990 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001991};
1992
Sean Paul77006a72013-01-16 10:17:20 -05001993static irqreturn_t hdmi_irq_thread(int irq, void *arg)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001994{
1995 struct exynos_drm_hdmi_context *ctx = arg;
1996 struct hdmi_context *hdata = ctx->ctx;
1997
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001998 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301999 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002000 mutex_unlock(&hdata->hdmi_mutex);
2001
2002 if (ctx->drm_dev)
2003 drm_helper_hpd_irq_event(ctx->drm_dev);
2004
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002005 return IRQ_HANDLED;
2006}
2007
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002008static int hdmi_resources_init(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002009{
2010 struct device *dev = hdata->dev;
2011 struct hdmi_resources *res = &hdata->res;
2012 static char *supply[] = {
2013 "hdmi-en",
2014 "vdd",
2015 "vdd_osc",
2016 "vdd_pll",
2017 };
2018 int i, ret;
2019
2020 DRM_DEBUG_KMS("HDMI resource init\n");
2021
Sachin Kamatadc837a2012-08-31 15:50:47 +05302022 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002023
2024 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302025 res->hdmi = devm_clk_get(dev, "hdmi");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002026 if (IS_ERR_OR_NULL(res->hdmi)) {
2027 DRM_ERROR("failed to get clock 'hdmi'\n");
2028 goto fail;
2029 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302030 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002031 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
2032 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2033 goto fail;
2034 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302035 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002036 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
2037 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2038 goto fail;
2039 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302040 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002041 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
2042 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2043 goto fail;
2044 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302045 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002046 if (IS_ERR_OR_NULL(res->hdmiphy)) {
2047 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2048 goto fail;
2049 }
2050
2051 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
2052
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302053 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05302054 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002055 if (!res->regul_bulk) {
2056 DRM_ERROR("failed to get memory for regulators\n");
2057 goto fail;
2058 }
2059 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
2060 res->regul_bulk[i].supply = supply[i];
2061 res->regul_bulk[i].consumer = NULL;
2062 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302063 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002064 if (ret) {
2065 DRM_ERROR("failed to get regulators\n");
2066 goto fail;
2067 }
2068 res->regul_count = ARRAY_SIZE(supply);
2069
2070 return 0;
2071fail:
2072 DRM_ERROR("HDMI resource init - failed\n");
2073 return -ENODEV;
2074}
2075
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002076static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2077
2078void hdmi_attach_ddc_client(struct i2c_client *ddc)
2079{
2080 if (ddc)
2081 hdmi_ddc = ddc;
2082}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002083
2084void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2085{
2086 if (hdmiphy)
2087 hdmi_hdmiphy = hdmiphy;
2088}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002089
Rahul Sharma22c4f422012-10-04 20:48:55 +05302090#ifdef CONFIG_OF
2091static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2092 (struct device *dev)
2093{
2094 struct device_node *np = dev->of_node;
2095 struct s5p_hdmi_platform_data *pd;
2096 enum of_gpio_flags flags;
2097 u32 value;
2098
2099 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
2100 if (!pd) {
2101 DRM_ERROR("memory allocation for pdata failed\n");
2102 goto err_data;
2103 }
2104
2105 if (!of_find_property(np, "hpd-gpio", &value)) {
2106 DRM_ERROR("no hpd gpio property found\n");
2107 goto err_data;
2108 }
2109
2110 pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
2111
2112 return pd;
2113
2114err_data:
2115 return NULL;
2116}
2117#else
2118static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2119 (struct device *dev)
2120{
2121 return NULL;
2122}
2123#endif
2124
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302125static struct platform_device_id hdmi_driver_types[] = {
2126 {
2127 .name = "s5pv210-hdmi",
2128 .driver_data = HDMI_TYPE13,
2129 }, {
2130 .name = "exynos4-hdmi",
2131 .driver_data = HDMI_TYPE13,
2132 }, {
2133 .name = "exynos4-hdmi14",
Rahul Sharma22c4f422012-10-04 20:48:55 +05302134 .driver_data = HDMI_TYPE14,
2135 }, {
2136 .name = "exynos5-hdmi",
2137 .driver_data = HDMI_TYPE14,
2138 }, {
2139 /* end node */
2140 }
2141};
2142
Sachin Kamat65da0352012-12-12 14:24:07 +05302143#ifdef CONFIG_OF
Rahul Sharma22c4f422012-10-04 20:48:55 +05302144static struct of_device_id hdmi_match_types[] = {
2145 {
2146 .compatible = "samsung,exynos5-hdmi",
2147 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302148 }, {
2149 /* end node */
2150 }
2151};
Sachin Kamat65da0352012-12-12 14:24:07 +05302152#endif
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302153
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002154static int hdmi_probe(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002155{
2156 struct device *dev = &pdev->dev;
2157 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2158 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302159 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002160 struct resource *res;
2161 int ret;
2162
2163 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2164
Rahul Sharma22c4f422012-10-04 20:48:55 +05302165 if (pdev->dev.of_node) {
2166 pdata = drm_hdmi_dt_parse_pdata(dev);
2167 if (IS_ERR(pdata)) {
2168 DRM_ERROR("failed to parse dt\n");
2169 return PTR_ERR(pdata);
2170 }
2171 } else {
2172 pdata = pdev->dev.platform_data;
2173 }
2174
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002175 if (!pdata) {
2176 DRM_ERROR("no platform data specified\n");
2177 return -EINVAL;
2178 }
2179
Sachin Kamata6e65072012-06-19 11:47:40 +05302180 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
2181 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002182 if (!drm_hdmi_ctx) {
2183 DRM_ERROR("failed to allocate common hdmi context.\n");
2184 return -ENOMEM;
2185 }
2186
Sachin Kamata6e65072012-06-19 11:47:40 +05302187 hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context),
2188 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002189 if (!hdata) {
2190 DRM_ERROR("out of memory\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002191 return -ENOMEM;
2192 }
2193
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002194 mutex_init(&hdata->hdmi_mutex);
2195
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002196 drm_hdmi_ctx->ctx = (void *)hdata;
2197 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2198
2199 platform_set_drvdata(pdev, drm_hdmi_ctx);
2200
Rahul Sharma22c4f422012-10-04 20:48:55 +05302201 if (dev->of_node) {
2202 const struct of_device_id *match;
2203 match = of_match_node(of_match_ptr(hdmi_match_types),
2204 pdev->dev.of_node);
Sachin Kamat1a4513b2012-12-12 14:24:08 +05302205 if (match == NULL)
2206 return -ENODEV;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302207 hdata->type = (enum hdmi_type)match->data;
2208 } else {
2209 hdata->type = (enum hdmi_type)platform_get_device_id
Rahul Sharma5a325072012-10-04 20:48:54 +05302210 (pdev)->driver_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302211 }
2212
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302213 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002214 hdata->dev = dev;
2215
2216 ret = hdmi_resources_init(hdata);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302217
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002218 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302219 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302220 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002221 }
2222
2223 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302224 if (!res) {
2225 DRM_ERROR("failed to find registers\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302226 return -ENOENT;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302227 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002228
Sachin Kamata6e65072012-06-19 11:47:40 +05302229 hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002230 if (!hdata->regs) {
2231 DRM_ERROR("failed to map registers\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302232 return -ENXIO;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002233 }
2234
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302235 ret = devm_gpio_request(&pdev->dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302236 if (ret) {
2237 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302238 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302239 }
2240
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002241 /* DDC i2c driver */
2242 if (i2c_add_driver(&ddc_driver)) {
2243 DRM_ERROR("failed to register ddc i2c driver\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302244 return -ENOENT;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002245 }
2246
2247 hdata->ddc_port = hdmi_ddc;
2248
2249 /* hdmiphy i2c driver */
2250 if (i2c_add_driver(&hdmiphy_driver)) {
2251 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2252 ret = -ENOENT;
2253 goto err_ddc;
2254 }
2255
2256 hdata->hdmiphy_port = hdmi_hdmiphy;
2257
Sean Paul77006a72013-01-16 10:17:20 -05002258 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
2259 if (hdata->irq < 0) {
2260 DRM_ERROR("failed to get GPIO irq\n");
2261 ret = hdata->irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002262 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002263 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002264
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302265 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2266
Sean Paul77006a72013-01-16 10:17:20 -05002267 ret = request_threaded_irq(hdata->irq, NULL,
2268 hdmi_irq_thread, IRQF_TRIGGER_RISING |
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002269 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sean Paul77006a72013-01-16 10:17:20 -05002270 "hdmi", drm_hdmi_ctx);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002271 if (ret) {
Sean Paul77006a72013-01-16 10:17:20 -05002272 DRM_ERROR("failed to register hdmi interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002273 goto err_hdmiphy;
2274 }
2275
Rahul Sharma768c3052012-10-04 20:48:56 +05302276 /* Attach HDMI Driver to common hdmi. */
2277 exynos_hdmi_drv_attach(drm_hdmi_ctx);
2278
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002279 /* register specific callbacks to common hdmi. */
Joonyoung Shim578b6062012-04-05 20:49:26 +09002280 exynos_hdmi_ops_register(&hdmi_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002281
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002282 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002283
2284 return 0;
2285
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002286err_hdmiphy:
2287 i2c_del_driver(&hdmiphy_driver);
2288err_ddc:
2289 i2c_del_driver(&ddc_driver);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002290 return ret;
2291}
2292
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002293static int hdmi_remove(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002294{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002295 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002296 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002297 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002298
2299 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2300
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002301 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002302
Sean Paul77006a72013-01-16 10:17:20 -05002303 free_irq(hdata->irq, hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002304
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002305
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002306 /* hdmiphy i2c driver */
2307 i2c_del_driver(&hdmiphy_driver);
2308 /* DDC i2c driver */
2309 i2c_del_driver(&ddc_driver);
2310
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002311 return 0;
2312}
2313
Joonyoung Shimab27af82012-04-23 19:35:51 +09002314#ifdef CONFIG_PM_SLEEP
2315static int hdmi_suspend(struct device *dev)
2316{
2317 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2318 struct hdmi_context *hdata = ctx->ctx;
2319
Rahul Sharma64327cb2012-11-28 11:30:23 +05302320 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2321
Sean Paul77006a72013-01-16 10:17:20 -05002322 disable_irq(hdata->irq);
Joonyoung Shimab27af82012-04-23 19:35:51 +09002323
2324 hdata->hpd = false;
2325 if (ctx->drm_dev)
2326 drm_helper_hpd_irq_event(ctx->drm_dev);
2327
Rahul Sharma64327cb2012-11-28 11:30:23 +05302328 if (pm_runtime_suspended(dev)) {
2329 DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
2330 return 0;
2331 }
2332
Joonyoung Shimab27af82012-04-23 19:35:51 +09002333 hdmi_poweroff(hdata);
2334
2335 return 0;
2336}
2337
2338static int hdmi_resume(struct device *dev)
2339{
2340 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2341 struct hdmi_context *hdata = ctx->ctx;
2342
Rahul Sharma64327cb2012-11-28 11:30:23 +05302343 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2344
2345 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2346
Sean Paul77006a72013-01-16 10:17:20 -05002347 enable_irq(hdata->irq);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302348
2349 if (!pm_runtime_suspended(dev)) {
2350 DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
2351 return 0;
2352 }
2353
2354 hdmi_poweron(hdata);
2355
Joonyoung Shimab27af82012-04-23 19:35:51 +09002356 return 0;
2357}
2358#endif
2359
Rahul Sharma64327cb2012-11-28 11:30:23 +05302360#ifdef CONFIG_PM_RUNTIME
2361static int hdmi_runtime_suspend(struct device *dev)
2362{
2363 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2364 struct hdmi_context *hdata = ctx->ctx;
2365 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2366
2367 hdmi_poweroff(hdata);
2368
2369 return 0;
2370}
2371
2372static int hdmi_runtime_resume(struct device *dev)
2373{
2374 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2375 struct hdmi_context *hdata = ctx->ctx;
2376 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2377
2378 hdmi_poweron(hdata);
2379
2380 return 0;
2381}
2382#endif
2383
2384static const struct dev_pm_ops hdmi_pm_ops = {
2385 SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
2386 SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
2387};
Joonyoung Shimab27af82012-04-23 19:35:51 +09002388
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002389struct platform_driver hdmi_driver = {
2390 .probe = hdmi_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002391 .remove = hdmi_remove,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302392 .id_table = hdmi_driver_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002393 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302394 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002395 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002396 .pm = &hdmi_pm_ops,
Sachin Kamat65da0352012-12-12 14:24:07 +05302397 .of_match_table = of_match_ptr(hdmi_match_types),
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002398 },
2399};