blob: ba330157552568129ed3abc3d3354c49b330fe3f [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
90struct hdmi_context {
91 struct device *dev;
92 struct drm_device *drm_dev;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +090093 bool hpd;
94 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +090095 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +090096 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +090097
Joonyoung Shim590f4182012-03-16 18:47:14 +090098 void __iomem *regs;
Inki Dae1055b392012-10-19 17:37:35 +090099 void *parent_ctx;
Sean Paul77006a72013-01-16 10:17:20 -0500100 int irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900101
102 struct i2c_client *ddc_port;
103 struct i2c_client *hdmiphy_port;
104
105 /* current hdmiphy conf index */
106 int cur_conf;
107
108 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900109
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530110 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530111
112 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900113};
114
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900115/* HDMI Version 1.3 */
116static const u8 hdmiphy_v13_conf27[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900117 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
118 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
119 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
120 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
121};
122
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900123static const u8 hdmiphy_v13_conf27_027[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900124 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
125 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
126 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
127 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
128};
129
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900130static const u8 hdmiphy_v13_conf74_175[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900131 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
132 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
133 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
134 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
135};
136
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900137static const u8 hdmiphy_v13_conf74_25[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900138 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
139 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
140 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
141 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
142};
143
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900144static const u8 hdmiphy_v13_conf148_5[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900145 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
146 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
147 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
148 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
149};
150
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900151struct hdmi_v13_tg_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900152 u8 cmd;
153 u8 h_fsz_l;
154 u8 h_fsz_h;
155 u8 hact_st_l;
156 u8 hact_st_h;
157 u8 hact_sz_l;
158 u8 hact_sz_h;
159 u8 v_fsz_l;
160 u8 v_fsz_h;
161 u8 vsync_l;
162 u8 vsync_h;
163 u8 vsync2_l;
164 u8 vsync2_h;
165 u8 vact_st_l;
166 u8 vact_st_h;
167 u8 vact_sz_l;
168 u8 vact_sz_h;
169 u8 field_chg_l;
170 u8 field_chg_h;
171 u8 vact_st2_l;
172 u8 vact_st2_h;
173 u8 vsync_top_hdmi_l;
174 u8 vsync_top_hdmi_h;
175 u8 vsync_bot_hdmi_l;
176 u8 vsync_bot_hdmi_h;
177 u8 field_top_hdmi_l;
178 u8 field_top_hdmi_h;
179 u8 field_bot_hdmi_l;
180 u8 field_bot_hdmi_h;
181};
182
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900183struct hdmi_v13_core_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900184 u8 h_blank[2];
185 u8 v_blank[3];
186 u8 h_v_line[3];
187 u8 vsync_pol[1];
188 u8 int_pro_mode[1];
189 u8 v_blank_f[3];
190 u8 h_sync_gen[3];
191 u8 v_sync_gen1[3];
192 u8 v_sync_gen2[3];
193 u8 v_sync_gen3[3];
194};
195
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900196struct hdmi_v13_preset_conf {
197 struct hdmi_v13_core_regs core;
198 struct hdmi_v13_tg_regs tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900199};
200
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900201struct hdmi_v13_conf {
202 int width;
203 int height;
204 int vrefresh;
205 bool interlace;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530206 int cea_video_id;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900207 const u8 *hdmiphy_data;
208 const struct hdmi_v13_preset_conf *conf;
209};
210
211static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900212 .core = {
213 .h_blank = {0x8a, 0x00},
214 .v_blank = {0x0d, 0x6a, 0x01},
215 .h_v_line = {0x0d, 0xa2, 0x35},
216 .vsync_pol = {0x01},
217 .int_pro_mode = {0x00},
218 .v_blank_f = {0x00, 0x00, 0x00},
219 .h_sync_gen = {0x0e, 0x30, 0x11},
220 .v_sync_gen1 = {0x0f, 0x90, 0x00},
221 /* other don't care */
222 },
223 .tg = {
224 0x00, /* cmd */
225 0x5a, 0x03, /* h_fsz */
226 0x8a, 0x00, 0xd0, 0x02, /* hact */
227 0x0d, 0x02, /* v_fsz */
228 0x01, 0x00, 0x33, 0x02, /* vsync */
229 0x2d, 0x00, 0xe0, 0x01, /* vact */
230 0x33, 0x02, /* field_chg */
231 0x49, 0x02, /* vact_st2 */
232 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
233 0x01, 0x00, 0x33, 0x02, /* field top/bot */
234 },
235};
236
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900237static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900238 .core = {
239 .h_blank = {0x72, 0x01},
240 .v_blank = {0xee, 0xf2, 0x00},
241 .h_v_line = {0xee, 0x22, 0x67},
242 .vsync_pol = {0x00},
243 .int_pro_mode = {0x00},
244 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
245 .h_sync_gen = {0x6c, 0x50, 0x02},
246 .v_sync_gen1 = {0x0a, 0x50, 0x00},
247 .v_sync_gen2 = {0x01, 0x10, 0x00},
248 .v_sync_gen3 = {0x01, 0x10, 0x00},
249 /* other don't care */
250 },
251 .tg = {
252 0x00, /* cmd */
253 0x72, 0x06, /* h_fsz */
254 0x71, 0x01, 0x01, 0x05, /* hact */
255 0xee, 0x02, /* v_fsz */
256 0x01, 0x00, 0x33, 0x02, /* vsync */
257 0x1e, 0x00, 0xd0, 0x02, /* vact */
258 0x33, 0x02, /* field_chg */
259 0x49, 0x02, /* vact_st2 */
260 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
261 0x01, 0x00, 0x33, 0x02, /* field top/bot */
262 },
263};
264
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900265static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900266 .core = {
267 .h_blank = {0xd0, 0x02},
268 .v_blank = {0x32, 0xB2, 0x00},
269 .h_v_line = {0x65, 0x04, 0xa5},
270 .vsync_pol = {0x00},
271 .int_pro_mode = {0x01},
272 .v_blank_f = {0x49, 0x2A, 0x23},
273 .h_sync_gen = {0x0E, 0xEA, 0x08},
274 .v_sync_gen1 = {0x07, 0x20, 0x00},
275 .v_sync_gen2 = {0x39, 0x42, 0x23},
276 .v_sync_gen3 = {0x38, 0x87, 0x73},
277 /* other don't care */
278 },
279 .tg = {
280 0x00, /* cmd */
281 0x50, 0x0A, /* h_fsz */
282 0xCF, 0x02, 0x81, 0x07, /* hact */
283 0x65, 0x04, /* v_fsz */
284 0x01, 0x00, 0x33, 0x02, /* vsync */
285 0x16, 0x00, 0x1c, 0x02, /* vact */
286 0x33, 0x02, /* field_chg */
287 0x49, 0x02, /* vact_st2 */
288 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
289 0x01, 0x00, 0x33, 0x02, /* field top/bot */
290 },
291};
292
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900293static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900294 .core = {
295 .h_blank = {0xd0, 0x02},
296 .v_blank = {0x65, 0x6c, 0x01},
297 .h_v_line = {0x65, 0x04, 0xa5},
298 .vsync_pol = {0x00},
299 .int_pro_mode = {0x00},
300 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
301 .h_sync_gen = {0x0e, 0xea, 0x08},
302 .v_sync_gen1 = {0x09, 0x40, 0x00},
303 .v_sync_gen2 = {0x01, 0x10, 0x00},
304 .v_sync_gen3 = {0x01, 0x10, 0x00},
305 /* other don't care */
306 },
307 .tg = {
308 0x00, /* cmd */
309 0x50, 0x0A, /* h_fsz */
310 0xCF, 0x02, 0x81, 0x07, /* hact */
311 0x65, 0x04, /* v_fsz */
312 0x01, 0x00, 0x33, 0x02, /* vsync */
313 0x2d, 0x00, 0x38, 0x04, /* vact */
314 0x33, 0x02, /* field_chg */
315 0x48, 0x02, /* vact_st2 */
316 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
317 0x01, 0x00, 0x33, 0x02, /* field top/bot */
318 },
319};
320
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900321static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900322 .core = {
323 .h_blank = {0x18, 0x01},
324 .v_blank = {0x32, 0xB2, 0x00},
325 .h_v_line = {0x65, 0x84, 0x89},
326 .vsync_pol = {0x00},
327 .int_pro_mode = {0x01},
328 .v_blank_f = {0x49, 0x2A, 0x23},
329 .h_sync_gen = {0x56, 0x08, 0x02},
330 .v_sync_gen1 = {0x07, 0x20, 0x00},
331 .v_sync_gen2 = {0x39, 0x42, 0x23},
332 .v_sync_gen3 = {0xa4, 0x44, 0x4a},
333 /* other don't care */
334 },
335 .tg = {
336 0x00, /* cmd */
337 0x98, 0x08, /* h_fsz */
338 0x17, 0x01, 0x81, 0x07, /* hact */
339 0x65, 0x04, /* v_fsz */
340 0x01, 0x00, 0x33, 0x02, /* vsync */
341 0x16, 0x00, 0x1c, 0x02, /* vact */
342 0x33, 0x02, /* field_chg */
343 0x49, 0x02, /* vact_st2 */
344 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
345 0x01, 0x00, 0x33, 0x02, /* field top/bot */
346 },
347};
348
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900349static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900350 .core = {
351 .h_blank = {0x18, 0x01},
352 .v_blank = {0x65, 0x6c, 0x01},
353 .h_v_line = {0x65, 0x84, 0x89},
354 .vsync_pol = {0x00},
355 .int_pro_mode = {0x00},
356 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
357 .h_sync_gen = {0x56, 0x08, 0x02},
358 .v_sync_gen1 = {0x09, 0x40, 0x00},
359 .v_sync_gen2 = {0x01, 0x10, 0x00},
360 .v_sync_gen3 = {0x01, 0x10, 0x00},
361 /* other don't care */
362 },
363 .tg = {
364 0x00, /* cmd */
365 0x98, 0x08, /* h_fsz */
366 0x17, 0x01, 0x81, 0x07, /* hact */
367 0x65, 0x04, /* v_fsz */
368 0x01, 0x00, 0x33, 0x02, /* vsync */
369 0x2d, 0x00, 0x38, 0x04, /* vact */
370 0x33, 0x02, /* field_chg */
371 0x48, 0x02, /* vact_st2 */
372 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
373 0x01, 0x00, 0x33, 0x02, /* field top/bot */
374 },
375};
376
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900377static const struct hdmi_v13_conf hdmi_v13_confs[] = {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530378 { 1280, 720, 60, false, 4, hdmiphy_v13_conf74_25,
379 &hdmi_v13_conf_720p60 },
380 { 1280, 720, 50, false, 19, hdmiphy_v13_conf74_25,
381 &hdmi_v13_conf_720p60 },
382 { 720, 480, 60, false, 3, hdmiphy_v13_conf27_027,
383 &hdmi_v13_conf_480p },
384 { 1920, 1080, 50, true, 20, hdmiphy_v13_conf74_25,
385 &hdmi_v13_conf_1080i50 },
386 { 1920, 1080, 50, false, 31, hdmiphy_v13_conf148_5,
387 &hdmi_v13_conf_1080p50 },
388 { 1920, 1080, 60, true, 5, hdmiphy_v13_conf74_25,
389 &hdmi_v13_conf_1080i60 },
390 { 1920, 1080, 60, false, 16, hdmiphy_v13_conf148_5,
391 &hdmi_v13_conf_1080p60 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900392};
393
394/* HDMI Version 1.4 */
395static const u8 hdmiphy_conf27_027[32] = {
396 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
397 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
398 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
399 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
400};
401
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900402static const u8 hdmiphy_conf74_176[32] = {
403 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08,
404 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80,
405 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
406 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
407};
408
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900409static const u8 hdmiphy_conf74_25[32] = {
410 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
411 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
412 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
413 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
414};
415
416static const u8 hdmiphy_conf148_5[32] = {
417 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
418 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
419 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
420 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
421};
422
423struct hdmi_tg_regs {
424 u8 cmd;
425 u8 h_fsz_l;
426 u8 h_fsz_h;
427 u8 hact_st_l;
428 u8 hact_st_h;
429 u8 hact_sz_l;
430 u8 hact_sz_h;
431 u8 v_fsz_l;
432 u8 v_fsz_h;
433 u8 vsync_l;
434 u8 vsync_h;
435 u8 vsync2_l;
436 u8 vsync2_h;
437 u8 vact_st_l;
438 u8 vact_st_h;
439 u8 vact_sz_l;
440 u8 vact_sz_h;
441 u8 field_chg_l;
442 u8 field_chg_h;
443 u8 vact_st2_l;
444 u8 vact_st2_h;
445 u8 vact_st3_l;
446 u8 vact_st3_h;
447 u8 vact_st4_l;
448 u8 vact_st4_h;
449 u8 vsync_top_hdmi_l;
450 u8 vsync_top_hdmi_h;
451 u8 vsync_bot_hdmi_l;
452 u8 vsync_bot_hdmi_h;
453 u8 field_top_hdmi_l;
454 u8 field_top_hdmi_h;
455 u8 field_bot_hdmi_l;
456 u8 field_bot_hdmi_h;
457 u8 tg_3d;
458};
459
460struct hdmi_core_regs {
461 u8 h_blank[2];
462 u8 v2_blank[2];
463 u8 v1_blank[2];
464 u8 v_line[2];
465 u8 h_line[2];
466 u8 hsync_pol[1];
467 u8 vsync_pol[1];
468 u8 int_pro_mode[1];
469 u8 v_blank_f0[2];
470 u8 v_blank_f1[2];
471 u8 h_sync_start[2];
472 u8 h_sync_end[2];
473 u8 v_sync_line_bef_2[2];
474 u8 v_sync_line_bef_1[2];
475 u8 v_sync_line_aft_2[2];
476 u8 v_sync_line_aft_1[2];
477 u8 v_sync_line_aft_pxl_2[2];
478 u8 v_sync_line_aft_pxl_1[2];
479 u8 v_blank_f2[2]; /* for 3D mode */
480 u8 v_blank_f3[2]; /* for 3D mode */
481 u8 v_blank_f4[2]; /* for 3D mode */
482 u8 v_blank_f5[2]; /* for 3D mode */
483 u8 v_sync_line_aft_3[2];
484 u8 v_sync_line_aft_4[2];
485 u8 v_sync_line_aft_5[2];
486 u8 v_sync_line_aft_6[2];
487 u8 v_sync_line_aft_pxl_3[2];
488 u8 v_sync_line_aft_pxl_4[2];
489 u8 v_sync_line_aft_pxl_5[2];
490 u8 v_sync_line_aft_pxl_6[2];
491 u8 vact_space_1[2];
492 u8 vact_space_2[2];
493 u8 vact_space_3[2];
494 u8 vact_space_4[2];
495 u8 vact_space_5[2];
496 u8 vact_space_6[2];
497};
498
499struct hdmi_preset_conf {
500 struct hdmi_core_regs core;
501 struct hdmi_tg_regs tg;
502};
503
504struct hdmi_conf {
505 int width;
506 int height;
507 int vrefresh;
508 bool interlace;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530509 int cea_video_id;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900510 const u8 *hdmiphy_data;
511 const struct hdmi_preset_conf *conf;
512};
513
514static const struct hdmi_preset_conf hdmi_conf_480p60 = {
515 .core = {
516 .h_blank = {0x8a, 0x00},
517 .v2_blank = {0x0d, 0x02},
518 .v1_blank = {0x2d, 0x00},
519 .v_line = {0x0d, 0x02},
520 .h_line = {0x5a, 0x03},
521 .hsync_pol = {0x01},
522 .vsync_pol = {0x01},
523 .int_pro_mode = {0x00},
524 .v_blank_f0 = {0xff, 0xff},
525 .v_blank_f1 = {0xff, 0xff},
526 .h_sync_start = {0x0e, 0x00},
527 .h_sync_end = {0x4c, 0x00},
528 .v_sync_line_bef_2 = {0x0f, 0x00},
529 .v_sync_line_bef_1 = {0x09, 0x00},
530 .v_sync_line_aft_2 = {0xff, 0xff},
531 .v_sync_line_aft_1 = {0xff, 0xff},
532 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
533 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
534 .v_blank_f2 = {0xff, 0xff},
535 .v_blank_f3 = {0xff, 0xff},
536 .v_blank_f4 = {0xff, 0xff},
537 .v_blank_f5 = {0xff, 0xff},
538 .v_sync_line_aft_3 = {0xff, 0xff},
539 .v_sync_line_aft_4 = {0xff, 0xff},
540 .v_sync_line_aft_5 = {0xff, 0xff},
541 .v_sync_line_aft_6 = {0xff, 0xff},
542 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
543 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
544 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
545 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
546 .vact_space_1 = {0xff, 0xff},
547 .vact_space_2 = {0xff, 0xff},
548 .vact_space_3 = {0xff, 0xff},
549 .vact_space_4 = {0xff, 0xff},
550 .vact_space_5 = {0xff, 0xff},
551 .vact_space_6 = {0xff, 0xff},
552 /* other don't care */
553 },
554 .tg = {
555 0x00, /* cmd */
556 0x5a, 0x03, /* h_fsz */
557 0x8a, 0x00, 0xd0, 0x02, /* hact */
558 0x0d, 0x02, /* v_fsz */
559 0x01, 0x00, 0x33, 0x02, /* vsync */
560 0x2d, 0x00, 0xe0, 0x01, /* vact */
561 0x33, 0x02, /* field_chg */
562 0x48, 0x02, /* vact_st2 */
563 0x00, 0x00, /* vact_st3 */
564 0x00, 0x00, /* vact_st4 */
565 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
566 0x01, 0x00, 0x33, 0x02, /* field top/bot */
567 0x00, /* 3d FP */
568 },
569};
570
571static const struct hdmi_preset_conf hdmi_conf_720p50 = {
572 .core = {
573 .h_blank = {0xbc, 0x02},
574 .v2_blank = {0xee, 0x02},
575 .v1_blank = {0x1e, 0x00},
576 .v_line = {0xee, 0x02},
577 .h_line = {0xbc, 0x07},
578 .hsync_pol = {0x00},
579 .vsync_pol = {0x00},
580 .int_pro_mode = {0x00},
581 .v_blank_f0 = {0xff, 0xff},
582 .v_blank_f1 = {0xff, 0xff},
583 .h_sync_start = {0xb6, 0x01},
584 .h_sync_end = {0xde, 0x01},
585 .v_sync_line_bef_2 = {0x0a, 0x00},
586 .v_sync_line_bef_1 = {0x05, 0x00},
587 .v_sync_line_aft_2 = {0xff, 0xff},
588 .v_sync_line_aft_1 = {0xff, 0xff},
589 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
590 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
591 .v_blank_f2 = {0xff, 0xff},
592 .v_blank_f3 = {0xff, 0xff},
593 .v_blank_f4 = {0xff, 0xff},
594 .v_blank_f5 = {0xff, 0xff},
595 .v_sync_line_aft_3 = {0xff, 0xff},
596 .v_sync_line_aft_4 = {0xff, 0xff},
597 .v_sync_line_aft_5 = {0xff, 0xff},
598 .v_sync_line_aft_6 = {0xff, 0xff},
599 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
600 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
601 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
602 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
603 .vact_space_1 = {0xff, 0xff},
604 .vact_space_2 = {0xff, 0xff},
605 .vact_space_3 = {0xff, 0xff},
606 .vact_space_4 = {0xff, 0xff},
607 .vact_space_5 = {0xff, 0xff},
608 .vact_space_6 = {0xff, 0xff},
609 /* other don't care */
610 },
611 .tg = {
612 0x00, /* cmd */
613 0xbc, 0x07, /* h_fsz */
614 0xbc, 0x02, 0x00, 0x05, /* hact */
615 0xee, 0x02, /* v_fsz */
616 0x01, 0x00, 0x33, 0x02, /* vsync */
617 0x1e, 0x00, 0xd0, 0x02, /* vact */
618 0x33, 0x02, /* field_chg */
619 0x48, 0x02, /* vact_st2 */
620 0x00, 0x00, /* vact_st3 */
621 0x00, 0x00, /* vact_st4 */
622 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
623 0x01, 0x00, 0x33, 0x02, /* field top/bot */
624 0x00, /* 3d FP */
625 },
626};
627
628static const struct hdmi_preset_conf hdmi_conf_720p60 = {
629 .core = {
630 .h_blank = {0x72, 0x01},
631 .v2_blank = {0xee, 0x02},
632 .v1_blank = {0x1e, 0x00},
633 .v_line = {0xee, 0x02},
634 .h_line = {0x72, 0x06},
635 .hsync_pol = {0x00},
636 .vsync_pol = {0x00},
637 .int_pro_mode = {0x00},
638 .v_blank_f0 = {0xff, 0xff},
639 .v_blank_f1 = {0xff, 0xff},
640 .h_sync_start = {0x6c, 0x00},
641 .h_sync_end = {0x94, 0x00},
642 .v_sync_line_bef_2 = {0x0a, 0x00},
643 .v_sync_line_bef_1 = {0x05, 0x00},
644 .v_sync_line_aft_2 = {0xff, 0xff},
645 .v_sync_line_aft_1 = {0xff, 0xff},
646 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
647 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
648 .v_blank_f2 = {0xff, 0xff},
649 .v_blank_f3 = {0xff, 0xff},
650 .v_blank_f4 = {0xff, 0xff},
651 .v_blank_f5 = {0xff, 0xff},
652 .v_sync_line_aft_3 = {0xff, 0xff},
653 .v_sync_line_aft_4 = {0xff, 0xff},
654 .v_sync_line_aft_5 = {0xff, 0xff},
655 .v_sync_line_aft_6 = {0xff, 0xff},
656 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
657 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
658 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
659 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
660 .vact_space_1 = {0xff, 0xff},
661 .vact_space_2 = {0xff, 0xff},
662 .vact_space_3 = {0xff, 0xff},
663 .vact_space_4 = {0xff, 0xff},
664 .vact_space_5 = {0xff, 0xff},
665 .vact_space_6 = {0xff, 0xff},
666 /* other don't care */
667 },
668 .tg = {
669 0x00, /* cmd */
670 0x72, 0x06, /* h_fsz */
671 0x72, 0x01, 0x00, 0x05, /* hact */
672 0xee, 0x02, /* v_fsz */
673 0x01, 0x00, 0x33, 0x02, /* vsync */
674 0x1e, 0x00, 0xd0, 0x02, /* vact */
675 0x33, 0x02, /* field_chg */
676 0x48, 0x02, /* vact_st2 */
677 0x00, 0x00, /* vact_st3 */
678 0x00, 0x00, /* vact_st4 */
679 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
680 0x01, 0x00, 0x33, 0x02, /* field top/bot */
681 0x00, /* 3d FP */
682 },
683};
684
685static const struct hdmi_preset_conf hdmi_conf_1080i50 = {
686 .core = {
687 .h_blank = {0xd0, 0x02},
688 .v2_blank = {0x32, 0x02},
689 .v1_blank = {0x16, 0x00},
690 .v_line = {0x65, 0x04},
691 .h_line = {0x50, 0x0a},
692 .hsync_pol = {0x00},
693 .vsync_pol = {0x00},
694 .int_pro_mode = {0x01},
695 .v_blank_f0 = {0x49, 0x02},
696 .v_blank_f1 = {0x65, 0x04},
697 .h_sync_start = {0x0e, 0x02},
698 .h_sync_end = {0x3a, 0x02},
699 .v_sync_line_bef_2 = {0x07, 0x00},
700 .v_sync_line_bef_1 = {0x02, 0x00},
701 .v_sync_line_aft_2 = {0x39, 0x02},
702 .v_sync_line_aft_1 = {0x34, 0x02},
703 .v_sync_line_aft_pxl_2 = {0x38, 0x07},
704 .v_sync_line_aft_pxl_1 = {0x38, 0x07},
705 .v_blank_f2 = {0xff, 0xff},
706 .v_blank_f3 = {0xff, 0xff},
707 .v_blank_f4 = {0xff, 0xff},
708 .v_blank_f5 = {0xff, 0xff},
709 .v_sync_line_aft_3 = {0xff, 0xff},
710 .v_sync_line_aft_4 = {0xff, 0xff},
711 .v_sync_line_aft_5 = {0xff, 0xff},
712 .v_sync_line_aft_6 = {0xff, 0xff},
713 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
714 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
715 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
716 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
717 .vact_space_1 = {0xff, 0xff},
718 .vact_space_2 = {0xff, 0xff},
719 .vact_space_3 = {0xff, 0xff},
720 .vact_space_4 = {0xff, 0xff},
721 .vact_space_5 = {0xff, 0xff},
722 .vact_space_6 = {0xff, 0xff},
723 /* other don't care */
724 },
725 .tg = {
726 0x00, /* cmd */
727 0x50, 0x0a, /* h_fsz */
728 0xd0, 0x02, 0x80, 0x07, /* hact */
729 0x65, 0x04, /* v_fsz */
730 0x01, 0x00, 0x33, 0x02, /* vsync */
731 0x16, 0x00, 0x1c, 0x02, /* vact */
732 0x33, 0x02, /* field_chg */
733 0x49, 0x02, /* vact_st2 */
734 0x00, 0x00, /* vact_st3 */
735 0x00, 0x00, /* vact_st4 */
736 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
737 0x01, 0x00, 0x33, 0x02, /* field top/bot */
738 0x00, /* 3d FP */
739 },
740};
741
742static const struct hdmi_preset_conf hdmi_conf_1080i60 = {
743 .core = {
744 .h_blank = {0x18, 0x01},
745 .v2_blank = {0x32, 0x02},
746 .v1_blank = {0x16, 0x00},
747 .v_line = {0x65, 0x04},
748 .h_line = {0x98, 0x08},
749 .hsync_pol = {0x00},
750 .vsync_pol = {0x00},
751 .int_pro_mode = {0x01},
752 .v_blank_f0 = {0x49, 0x02},
753 .v_blank_f1 = {0x65, 0x04},
754 .h_sync_start = {0x56, 0x00},
755 .h_sync_end = {0x82, 0x00},
756 .v_sync_line_bef_2 = {0x07, 0x00},
757 .v_sync_line_bef_1 = {0x02, 0x00},
758 .v_sync_line_aft_2 = {0x39, 0x02},
759 .v_sync_line_aft_1 = {0x34, 0x02},
760 .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
761 .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
762 .v_blank_f2 = {0xff, 0xff},
763 .v_blank_f3 = {0xff, 0xff},
764 .v_blank_f4 = {0xff, 0xff},
765 .v_blank_f5 = {0xff, 0xff},
766 .v_sync_line_aft_3 = {0xff, 0xff},
767 .v_sync_line_aft_4 = {0xff, 0xff},
768 .v_sync_line_aft_5 = {0xff, 0xff},
769 .v_sync_line_aft_6 = {0xff, 0xff},
770 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
771 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
772 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
773 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
774 .vact_space_1 = {0xff, 0xff},
775 .vact_space_2 = {0xff, 0xff},
776 .vact_space_3 = {0xff, 0xff},
777 .vact_space_4 = {0xff, 0xff},
778 .vact_space_5 = {0xff, 0xff},
779 .vact_space_6 = {0xff, 0xff},
780 /* other don't care */
781 },
782 .tg = {
783 0x00, /* cmd */
784 0x98, 0x08, /* h_fsz */
785 0x18, 0x01, 0x80, 0x07, /* hact */
786 0x65, 0x04, /* v_fsz */
787 0x01, 0x00, 0x33, 0x02, /* vsync */
788 0x16, 0x00, 0x1c, 0x02, /* vact */
789 0x33, 0x02, /* field_chg */
790 0x49, 0x02, /* vact_st2 */
791 0x00, 0x00, /* vact_st3 */
792 0x00, 0x00, /* vact_st4 */
793 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
794 0x01, 0x00, 0x33, 0x02, /* field top/bot */
795 0x00, /* 3d FP */
796 },
797};
798
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900799static const struct hdmi_preset_conf hdmi_conf_1080p30 = {
800 .core = {
801 .h_blank = {0x18, 0x01},
802 .v2_blank = {0x65, 0x04},
803 .v1_blank = {0x2d, 0x00},
804 .v_line = {0x65, 0x04},
805 .h_line = {0x98, 0x08},
806 .hsync_pol = {0x00},
807 .vsync_pol = {0x00},
808 .int_pro_mode = {0x00},
809 .v_blank_f0 = {0xff, 0xff},
810 .v_blank_f1 = {0xff, 0xff},
811 .h_sync_start = {0x56, 0x00},
812 .h_sync_end = {0x82, 0x00},
813 .v_sync_line_bef_2 = {0x09, 0x00},
814 .v_sync_line_bef_1 = {0x04, 0x00},
815 .v_sync_line_aft_2 = {0xff, 0xff},
816 .v_sync_line_aft_1 = {0xff, 0xff},
817 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
818 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
819 .v_blank_f2 = {0xff, 0xff},
820 .v_blank_f3 = {0xff, 0xff},
821 .v_blank_f4 = {0xff, 0xff},
822 .v_blank_f5 = {0xff, 0xff},
823 .v_sync_line_aft_3 = {0xff, 0xff},
824 .v_sync_line_aft_4 = {0xff, 0xff},
825 .v_sync_line_aft_5 = {0xff, 0xff},
826 .v_sync_line_aft_6 = {0xff, 0xff},
827 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
828 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
829 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
830 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
831 .vact_space_1 = {0xff, 0xff},
832 .vact_space_2 = {0xff, 0xff},
833 .vact_space_3 = {0xff, 0xff},
834 .vact_space_4 = {0xff, 0xff},
835 .vact_space_5 = {0xff, 0xff},
836 .vact_space_6 = {0xff, 0xff},
837 /* other don't care */
838 },
839 .tg = {
840 0x00, /* cmd */
841 0x98, 0x08, /* h_fsz */
842 0x18, 0x01, 0x80, 0x07, /* hact */
843 0x65, 0x04, /* v_fsz */
844 0x01, 0x00, 0x33, 0x02, /* vsync */
845 0x2d, 0x00, 0x38, 0x04, /* vact */
846 0x33, 0x02, /* field_chg */
847 0x48, 0x02, /* vact_st2 */
848 0x00, 0x00, /* vact_st3 */
849 0x00, 0x00, /* vact_st4 */
850 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
851 0x01, 0x00, 0x33, 0x02, /* field top/bot */
852 0x00, /* 3d FP */
853 },
854};
855
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900856static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
857 .core = {
858 .h_blank = {0xd0, 0x02},
859 .v2_blank = {0x65, 0x04},
860 .v1_blank = {0x2d, 0x00},
861 .v_line = {0x65, 0x04},
862 .h_line = {0x50, 0x0a},
863 .hsync_pol = {0x00},
864 .vsync_pol = {0x00},
865 .int_pro_mode = {0x00},
866 .v_blank_f0 = {0xff, 0xff},
867 .v_blank_f1 = {0xff, 0xff},
868 .h_sync_start = {0x0e, 0x02},
869 .h_sync_end = {0x3a, 0x02},
870 .v_sync_line_bef_2 = {0x09, 0x00},
871 .v_sync_line_bef_1 = {0x04, 0x00},
872 .v_sync_line_aft_2 = {0xff, 0xff},
873 .v_sync_line_aft_1 = {0xff, 0xff},
874 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
875 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
876 .v_blank_f2 = {0xff, 0xff},
877 .v_blank_f3 = {0xff, 0xff},
878 .v_blank_f4 = {0xff, 0xff},
879 .v_blank_f5 = {0xff, 0xff},
880 .v_sync_line_aft_3 = {0xff, 0xff},
881 .v_sync_line_aft_4 = {0xff, 0xff},
882 .v_sync_line_aft_5 = {0xff, 0xff},
883 .v_sync_line_aft_6 = {0xff, 0xff},
884 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
885 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
886 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
887 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
888 .vact_space_1 = {0xff, 0xff},
889 .vact_space_2 = {0xff, 0xff},
890 .vact_space_3 = {0xff, 0xff},
891 .vact_space_4 = {0xff, 0xff},
892 .vact_space_5 = {0xff, 0xff},
893 .vact_space_6 = {0xff, 0xff},
894 /* other don't care */
895 },
896 .tg = {
897 0x00, /* cmd */
898 0x50, 0x0a, /* h_fsz */
899 0xd0, 0x02, 0x80, 0x07, /* hact */
900 0x65, 0x04, /* v_fsz */
901 0x01, 0x00, 0x33, 0x02, /* vsync */
902 0x2d, 0x00, 0x38, 0x04, /* vact */
903 0x33, 0x02, /* field_chg */
904 0x48, 0x02, /* vact_st2 */
905 0x00, 0x00, /* vact_st3 */
906 0x00, 0x00, /* vact_st4 */
907 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
908 0x01, 0x00, 0x33, 0x02, /* field top/bot */
909 0x00, /* 3d FP */
910 },
911};
912
913static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
914 .core = {
915 .h_blank = {0x18, 0x01},
916 .v2_blank = {0x65, 0x04},
917 .v1_blank = {0x2d, 0x00},
918 .v_line = {0x65, 0x04},
919 .h_line = {0x98, 0x08},
920 .hsync_pol = {0x00},
921 .vsync_pol = {0x00},
922 .int_pro_mode = {0x00},
923 .v_blank_f0 = {0xff, 0xff},
924 .v_blank_f1 = {0xff, 0xff},
925 .h_sync_start = {0x56, 0x00},
926 .h_sync_end = {0x82, 0x00},
927 .v_sync_line_bef_2 = {0x09, 0x00},
928 .v_sync_line_bef_1 = {0x04, 0x00},
929 .v_sync_line_aft_2 = {0xff, 0xff},
930 .v_sync_line_aft_1 = {0xff, 0xff},
931 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
932 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
933 .v_blank_f2 = {0xff, 0xff},
934 .v_blank_f3 = {0xff, 0xff},
935 .v_blank_f4 = {0xff, 0xff},
936 .v_blank_f5 = {0xff, 0xff},
937 .v_sync_line_aft_3 = {0xff, 0xff},
938 .v_sync_line_aft_4 = {0xff, 0xff},
939 .v_sync_line_aft_5 = {0xff, 0xff},
940 .v_sync_line_aft_6 = {0xff, 0xff},
941 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
942 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
943 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
944 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
945 /* other don't care */
946 },
947 .tg = {
948 0x00, /* cmd */
949 0x98, 0x08, /* h_fsz */
950 0x18, 0x01, 0x80, 0x07, /* hact */
951 0x65, 0x04, /* v_fsz */
952 0x01, 0x00, 0x33, 0x02, /* vsync */
953 0x2d, 0x00, 0x38, 0x04, /* vact */
954 0x33, 0x02, /* field_chg */
955 0x48, 0x02, /* vact_st2 */
956 0x00, 0x00, /* vact_st3 */
957 0x00, 0x00, /* vact_st4 */
958 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
959 0x01, 0x00, 0x33, 0x02, /* field top/bot */
960 0x00, /* 3d FP */
961 },
962};
963
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900964static const struct hdmi_conf hdmi_confs[] = {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530965 { 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 },
966 { 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 },
967 { 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 },
968 { 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
969 { 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
970 { 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
971 { 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
972 { 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900973};
974
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530975struct hdmi_infoframe {
976 enum HDMI_PACKET_TYPE type;
977 u8 ver;
978 u8 len;
979};
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900980
981static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
982{
983 return readl(hdata->regs + reg_id);
984}
985
986static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
987 u32 reg_id, u8 value)
988{
989 writeb(value, hdata->regs + reg_id);
990}
991
992static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
993 u32 reg_id, u32 value, u32 mask)
994{
995 u32 old = readl(hdata->regs + reg_id);
996 value = (value & mask) | (old & ~mask);
997 writel(value, hdata->regs + reg_id);
998}
999
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001000static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001001{
1002#define DUMPREG(reg_id) \
1003 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
1004 readl(hdata->regs + reg_id))
1005 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
1006 DUMPREG(HDMI_INTC_FLAG);
1007 DUMPREG(HDMI_INTC_CON);
1008 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001009 DUMPREG(HDMI_V13_PHY_RSTOUT);
1010 DUMPREG(HDMI_V13_PHY_VPLL);
1011 DUMPREG(HDMI_V13_PHY_CMU);
1012 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001013
1014 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
1015 DUMPREG(HDMI_CON_0);
1016 DUMPREG(HDMI_CON_1);
1017 DUMPREG(HDMI_CON_2);
1018 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001019 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001020 DUMPREG(HDMI_STATUS_EN);
1021 DUMPREG(HDMI_HPD);
1022 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001023 DUMPREG(HDMI_V13_HPD_GEN);
1024 DUMPREG(HDMI_V13_DC_CONTROL);
1025 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001026
1027 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
1028 DUMPREG(HDMI_H_BLANK_0);
1029 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001030 DUMPREG(HDMI_V13_V_BLANK_0);
1031 DUMPREG(HDMI_V13_V_BLANK_1);
1032 DUMPREG(HDMI_V13_V_BLANK_2);
1033 DUMPREG(HDMI_V13_H_V_LINE_0);
1034 DUMPREG(HDMI_V13_H_V_LINE_1);
1035 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001036 DUMPREG(HDMI_VSYNC_POL);
1037 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001038 DUMPREG(HDMI_V13_V_BLANK_F_0);
1039 DUMPREG(HDMI_V13_V_BLANK_F_1);
1040 DUMPREG(HDMI_V13_V_BLANK_F_2);
1041 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
1042 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
1043 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
1044 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
1045 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
1046 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
1047 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
1048 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
1049 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
1050 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
1051 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
1052 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001053
1054 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
1055 DUMPREG(HDMI_TG_CMD);
1056 DUMPREG(HDMI_TG_H_FSZ_L);
1057 DUMPREG(HDMI_TG_H_FSZ_H);
1058 DUMPREG(HDMI_TG_HACT_ST_L);
1059 DUMPREG(HDMI_TG_HACT_ST_H);
1060 DUMPREG(HDMI_TG_HACT_SZ_L);
1061 DUMPREG(HDMI_TG_HACT_SZ_H);
1062 DUMPREG(HDMI_TG_V_FSZ_L);
1063 DUMPREG(HDMI_TG_V_FSZ_H);
1064 DUMPREG(HDMI_TG_VSYNC_L);
1065 DUMPREG(HDMI_TG_VSYNC_H);
1066 DUMPREG(HDMI_TG_VSYNC2_L);
1067 DUMPREG(HDMI_TG_VSYNC2_H);
1068 DUMPREG(HDMI_TG_VACT_ST_L);
1069 DUMPREG(HDMI_TG_VACT_ST_H);
1070 DUMPREG(HDMI_TG_VACT_SZ_L);
1071 DUMPREG(HDMI_TG_VACT_SZ_H);
1072 DUMPREG(HDMI_TG_FIELD_CHG_L);
1073 DUMPREG(HDMI_TG_FIELD_CHG_H);
1074 DUMPREG(HDMI_TG_VACT_ST2_L);
1075 DUMPREG(HDMI_TG_VACT_ST2_H);
1076 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
1077 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
1078 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
1079 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
1080 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
1081 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
1082 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
1083 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
1084#undef DUMPREG
1085}
1086
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001087static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
1088{
1089 int i;
1090
1091#define DUMPREG(reg_id) \
1092 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
1093 readl(hdata->regs + reg_id))
1094
1095 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
1096 DUMPREG(HDMI_INTC_CON);
1097 DUMPREG(HDMI_INTC_FLAG);
1098 DUMPREG(HDMI_HPD_STATUS);
1099 DUMPREG(HDMI_INTC_CON_1);
1100 DUMPREG(HDMI_INTC_FLAG_1);
1101 DUMPREG(HDMI_PHY_STATUS_0);
1102 DUMPREG(HDMI_PHY_STATUS_PLL);
1103 DUMPREG(HDMI_PHY_CON_0);
1104 DUMPREG(HDMI_PHY_RSTOUT);
1105 DUMPREG(HDMI_PHY_VPLL);
1106 DUMPREG(HDMI_PHY_CMU);
1107 DUMPREG(HDMI_CORE_RSTOUT);
1108
1109 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
1110 DUMPREG(HDMI_CON_0);
1111 DUMPREG(HDMI_CON_1);
1112 DUMPREG(HDMI_CON_2);
1113 DUMPREG(HDMI_SYS_STATUS);
1114 DUMPREG(HDMI_PHY_STATUS_0);
1115 DUMPREG(HDMI_STATUS_EN);
1116 DUMPREG(HDMI_HPD);
1117 DUMPREG(HDMI_MODE_SEL);
1118 DUMPREG(HDMI_ENC_EN);
1119 DUMPREG(HDMI_DC_CONTROL);
1120 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
1121
1122 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
1123 DUMPREG(HDMI_H_BLANK_0);
1124 DUMPREG(HDMI_H_BLANK_1);
1125 DUMPREG(HDMI_V2_BLANK_0);
1126 DUMPREG(HDMI_V2_BLANK_1);
1127 DUMPREG(HDMI_V1_BLANK_0);
1128 DUMPREG(HDMI_V1_BLANK_1);
1129 DUMPREG(HDMI_V_LINE_0);
1130 DUMPREG(HDMI_V_LINE_1);
1131 DUMPREG(HDMI_H_LINE_0);
1132 DUMPREG(HDMI_H_LINE_1);
1133 DUMPREG(HDMI_HSYNC_POL);
1134
1135 DUMPREG(HDMI_VSYNC_POL);
1136 DUMPREG(HDMI_INT_PRO_MODE);
1137 DUMPREG(HDMI_V_BLANK_F0_0);
1138 DUMPREG(HDMI_V_BLANK_F0_1);
1139 DUMPREG(HDMI_V_BLANK_F1_0);
1140 DUMPREG(HDMI_V_BLANK_F1_1);
1141
1142 DUMPREG(HDMI_H_SYNC_START_0);
1143 DUMPREG(HDMI_H_SYNC_START_1);
1144 DUMPREG(HDMI_H_SYNC_END_0);
1145 DUMPREG(HDMI_H_SYNC_END_1);
1146
1147 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
1148 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
1149 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
1150 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
1151
1152 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
1153 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
1154 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
1155 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
1156
1157 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
1158 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
1159 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
1160 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
1161
1162 DUMPREG(HDMI_V_BLANK_F2_0);
1163 DUMPREG(HDMI_V_BLANK_F2_1);
1164 DUMPREG(HDMI_V_BLANK_F3_0);
1165 DUMPREG(HDMI_V_BLANK_F3_1);
1166 DUMPREG(HDMI_V_BLANK_F4_0);
1167 DUMPREG(HDMI_V_BLANK_F4_1);
1168 DUMPREG(HDMI_V_BLANK_F5_0);
1169 DUMPREG(HDMI_V_BLANK_F5_1);
1170
1171 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
1172 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
1173 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
1174 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
1175 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
1176 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
1177 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
1178 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
1179
1180 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
1181 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
1182 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
1183 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
1184 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
1185 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
1186 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
1187 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
1188
1189 DUMPREG(HDMI_VACT_SPACE_1_0);
1190 DUMPREG(HDMI_VACT_SPACE_1_1);
1191 DUMPREG(HDMI_VACT_SPACE_2_0);
1192 DUMPREG(HDMI_VACT_SPACE_2_1);
1193 DUMPREG(HDMI_VACT_SPACE_3_0);
1194 DUMPREG(HDMI_VACT_SPACE_3_1);
1195 DUMPREG(HDMI_VACT_SPACE_4_0);
1196 DUMPREG(HDMI_VACT_SPACE_4_1);
1197 DUMPREG(HDMI_VACT_SPACE_5_0);
1198 DUMPREG(HDMI_VACT_SPACE_5_1);
1199 DUMPREG(HDMI_VACT_SPACE_6_0);
1200 DUMPREG(HDMI_VACT_SPACE_6_1);
1201
1202 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
1203 DUMPREG(HDMI_TG_CMD);
1204 DUMPREG(HDMI_TG_H_FSZ_L);
1205 DUMPREG(HDMI_TG_H_FSZ_H);
1206 DUMPREG(HDMI_TG_HACT_ST_L);
1207 DUMPREG(HDMI_TG_HACT_ST_H);
1208 DUMPREG(HDMI_TG_HACT_SZ_L);
1209 DUMPREG(HDMI_TG_HACT_SZ_H);
1210 DUMPREG(HDMI_TG_V_FSZ_L);
1211 DUMPREG(HDMI_TG_V_FSZ_H);
1212 DUMPREG(HDMI_TG_VSYNC_L);
1213 DUMPREG(HDMI_TG_VSYNC_H);
1214 DUMPREG(HDMI_TG_VSYNC2_L);
1215 DUMPREG(HDMI_TG_VSYNC2_H);
1216 DUMPREG(HDMI_TG_VACT_ST_L);
1217 DUMPREG(HDMI_TG_VACT_ST_H);
1218 DUMPREG(HDMI_TG_VACT_SZ_L);
1219 DUMPREG(HDMI_TG_VACT_SZ_H);
1220 DUMPREG(HDMI_TG_FIELD_CHG_L);
1221 DUMPREG(HDMI_TG_FIELD_CHG_H);
1222 DUMPREG(HDMI_TG_VACT_ST2_L);
1223 DUMPREG(HDMI_TG_VACT_ST2_H);
1224 DUMPREG(HDMI_TG_VACT_ST3_L);
1225 DUMPREG(HDMI_TG_VACT_ST3_H);
1226 DUMPREG(HDMI_TG_VACT_ST4_L);
1227 DUMPREG(HDMI_TG_VACT_ST4_H);
1228 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
1229 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
1230 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
1231 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
1232 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
1233 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
1234 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
1235 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
1236 DUMPREG(HDMI_TG_3D);
1237
1238 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
1239 DUMPREG(HDMI_AVI_CON);
1240 DUMPREG(HDMI_AVI_HEADER0);
1241 DUMPREG(HDMI_AVI_HEADER1);
1242 DUMPREG(HDMI_AVI_HEADER2);
1243 DUMPREG(HDMI_AVI_CHECK_SUM);
1244 DUMPREG(HDMI_VSI_CON);
1245 DUMPREG(HDMI_VSI_HEADER0);
1246 DUMPREG(HDMI_VSI_HEADER1);
1247 DUMPREG(HDMI_VSI_HEADER2);
1248 for (i = 0; i < 7; ++i)
1249 DUMPREG(HDMI_VSI_DATA(i));
1250
1251#undef DUMPREG
1252}
1253
1254static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
1255{
Rahul Sharma5a325072012-10-04 20:48:54 +05301256 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001257 hdmi_v13_regs_dump(hdata, prefix);
1258 else
1259 hdmi_v14_regs_dump(hdata, prefix);
1260}
1261
1262static int hdmi_v13_conf_index(struct drm_display_mode *mode)
1263{
1264 int i;
1265
1266 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1267 if (hdmi_v13_confs[i].width == mode->hdisplay &&
1268 hdmi_v13_confs[i].height == mode->vdisplay &&
1269 hdmi_v13_confs[i].vrefresh == mode->vrefresh &&
1270 hdmi_v13_confs[i].interlace ==
1271 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1272 true : false))
1273 return i;
1274
Inki Dae1de425b2012-03-16 18:47:04 +09001275 return -EINVAL;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001276}
1277
1278static int hdmi_v14_conf_index(struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001279{
1280 int i;
1281
1282 for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i)
1283 if (hdmi_confs[i].width == mode->hdisplay &&
1284 hdmi_confs[i].height == mode->vdisplay &&
1285 hdmi_confs[i].vrefresh == mode->vrefresh &&
1286 hdmi_confs[i].interlace ==
1287 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1288 true : false))
1289 return i;
1290
Inki Dae1de425b2012-03-16 18:47:04 +09001291 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001292}
1293
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001294static int hdmi_conf_index(struct hdmi_context *hdata,
1295 struct drm_display_mode *mode)
1296{
Rahul Sharma5a325072012-10-04 20:48:54 +05301297 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001298 return hdmi_v13_conf_index(mode);
Inki Dae1de425b2012-03-16 18:47:04 +09001299
1300 return hdmi_v14_conf_index(mode);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001301}
1302
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301303static u8 hdmi_chksum(struct hdmi_context *hdata,
1304 u32 start, u8 len, u32 hdr_sum)
1305{
1306 int i;
1307
1308 /* hdr_sum : header0 + header1 + header2
1309 * start : start address of packet byte1
1310 * len : packet bytes - 1 */
1311 for (i = 0; i < len; ++i)
1312 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
1313
1314 /* return 2's complement of 8 bit hdr_sum */
1315 return (u8)(~(hdr_sum & 0xff) + 1);
1316}
1317
1318static void hdmi_reg_infoframe(struct hdmi_context *hdata,
1319 struct hdmi_infoframe *infoframe)
1320{
1321 u32 hdr_sum;
1322 u8 chksum;
1323 u32 aspect_ratio;
1324 u32 mod;
1325 u32 vic;
1326
1327 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1328
1329 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
1330 if (hdata->dvi_mode) {
1331 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
1332 HDMI_VSI_CON_DO_NOT_TRANSMIT);
1333 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
1334 HDMI_AVI_CON_DO_NOT_TRANSMIT);
1335 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
1336 return;
1337 }
1338
1339 switch (infoframe->type) {
1340 case HDMI_PACKET_TYPE_AVI:
1341 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
1342 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type);
1343 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver);
1344 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len);
1345 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
1346
1347 /* Output format zero hardcoded ,RGB YBCR selection */
1348 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
1349 AVI_ACTIVE_FORMAT_VALID |
1350 AVI_UNDERSCANNED_DISPLAY_VALID);
1351
1352 aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9;
1353
1354 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio |
1355 AVI_SAME_AS_PIC_ASPECT_RATIO);
1356
1357 if (hdata->type == HDMI_TYPE13)
1358 vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id;
1359 else
1360 vic = hdmi_confs[hdata->cur_conf].cea_video_id;
1361
1362 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
1363
1364 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
1365 infoframe->len, hdr_sum);
1366 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
1367 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
1368 break;
1369 case HDMI_PACKET_TYPE_AUI:
1370 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
1371 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type);
1372 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver);
1373 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len);
1374 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
1375 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
1376 infoframe->len, hdr_sum);
1377 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
1378 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
1379 break;
1380 default:
1381 break;
1382 }
1383}
1384
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001385static bool hdmi_is_connected(void *ctx)
1386{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001387 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001388
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001389 return hdata->hpd;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001390}
1391
Rahul Sharma9c08e4b2013-01-04 07:59:11 -05001392static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001393{
1394 struct edid *raw_edid;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001395 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001396
1397 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1398
1399 if (!hdata->ddc_port)
Rahul Sharma9c08e4b2013-01-04 07:59:11 -05001400 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001401
1402 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -05001403 if (!raw_edid)
1404 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001405
Rahul Sharma9c08e4b2013-01-04 07:59:11 -05001406 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
1407 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
1408 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
1409 raw_edid->width_cm, raw_edid->height_cm);
1410
1411 return raw_edid;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001412}
1413
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001414static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001415{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001416 int i;
1417
Inki Dae1de425b2012-03-16 18:47:04 +09001418 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1419 check_timing->xres, check_timing->yres,
1420 check_timing->refresh, (check_timing->vmode &
1421 FB_VMODE_INTERLACED) ? true : false);
1422
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001423 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1424 if (hdmi_v13_confs[i].width == check_timing->xres &&
1425 hdmi_v13_confs[i].height == check_timing->yres &&
1426 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1427 hdmi_v13_confs[i].interlace ==
1428 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1429 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001430 return 0;
1431
1432 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001433
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001434 return -EINVAL;
1435}
1436
1437static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1438{
1439 int i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001440
Inki Dae1de425b2012-03-16 18:47:04 +09001441 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1442 check_timing->xres, check_timing->yres,
1443 check_timing->refresh, (check_timing->vmode &
1444 FB_VMODE_INTERLACED) ? true : false);
1445
1446 for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001447 if (hdmi_confs[i].width == check_timing->xres &&
1448 hdmi_confs[i].height == check_timing->yres &&
1449 hdmi_confs[i].vrefresh == check_timing->refresh &&
1450 hdmi_confs[i].interlace ==
1451 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1452 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001453 return 0;
1454
1455 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001456
1457 return -EINVAL;
1458}
1459
Rahul Sharma438c0f82013-01-15 08:11:05 -05001460static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001461{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001462 struct hdmi_context *hdata = ctx;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001463
1464 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1465
Rahul Sharma438c0f82013-01-15 08:11:05 -05001466 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres,
1467 timing->yres, timing->refresh,
1468 timing->vmode);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001469
Rahul Sharma5a325072012-10-04 20:48:54 +05301470 if (hdata->type == HDMI_TYPE13)
Rahul Sharma438c0f82013-01-15 08:11:05 -05001471 return hdmi_v13_check_timing(timing);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001472 else
Rahul Sharma438c0f82013-01-15 08:11:05 -05001473 return hdmi_v14_check_timing(timing);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001474}
1475
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001476static void hdmi_set_acr(u32 freq, u8 *acr)
1477{
1478 u32 n, cts;
1479
1480 switch (freq) {
1481 case 32000:
1482 n = 4096;
1483 cts = 27000;
1484 break;
1485 case 44100:
1486 n = 6272;
1487 cts = 30000;
1488 break;
1489 case 88200:
1490 n = 12544;
1491 cts = 30000;
1492 break;
1493 case 176400:
1494 n = 25088;
1495 cts = 30000;
1496 break;
1497 case 48000:
1498 n = 6144;
1499 cts = 27000;
1500 break;
1501 case 96000:
1502 n = 12288;
1503 cts = 27000;
1504 break;
1505 case 192000:
1506 n = 24576;
1507 cts = 27000;
1508 break;
1509 default:
1510 n = 0;
1511 cts = 0;
1512 break;
1513 }
1514
1515 acr[1] = cts >> 16;
1516 acr[2] = cts >> 8 & 0xff;
1517 acr[3] = cts & 0xff;
1518
1519 acr[4] = n >> 16;
1520 acr[5] = n >> 8 & 0xff;
1521 acr[6] = n & 0xff;
1522}
1523
1524static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1525{
1526 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1527 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1528 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1529 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1530 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1531 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1532 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1533 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1534 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1535
Rahul Sharma5a325072012-10-04 20:48:54 +05301536 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001537 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1538 else
1539 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1540}
1541
1542static void hdmi_audio_init(struct hdmi_context *hdata)
1543{
1544 u32 sample_rate, bits_per_sample, frame_size_code;
1545 u32 data_num, bit_ch, sample_frq;
1546 u32 val;
1547 u8 acr[7];
1548
1549 sample_rate = 44100;
1550 bits_per_sample = 16;
1551 frame_size_code = 0;
1552
1553 switch (bits_per_sample) {
1554 case 20:
1555 data_num = 2;
1556 bit_ch = 1;
1557 break;
1558 case 24:
1559 data_num = 3;
1560 bit_ch = 1;
1561 break;
1562 default:
1563 data_num = 1;
1564 bit_ch = 0;
1565 break;
1566 }
1567
1568 hdmi_set_acr(sample_rate, acr);
1569 hdmi_reg_acr(hdata, acr);
1570
1571 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1572 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1573 | HDMI_I2S_MUX_ENABLE);
1574
1575 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1576 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1577
1578 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1579
1580 sample_frq = (sample_rate == 44100) ? 0 :
1581 (sample_rate == 48000) ? 2 :
1582 (sample_rate == 32000) ? 3 :
1583 (sample_rate == 96000) ? 0xa : 0x0;
1584
1585 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1586 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1587
1588 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1589 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1590
1591 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1592 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1593 | HDMI_I2S_SEL_LRCK(6));
1594 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1595 | HDMI_I2S_SEL_SDATA2(4));
1596 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1597 | HDMI_I2S_SEL_SDATA2(2));
1598 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1599
1600 /* I2S_CON_1 & 2 */
1601 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1602 | HDMI_I2S_L_CH_LOW_POL);
1603 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1604 | HDMI_I2S_SET_BIT_CH(bit_ch)
1605 | HDMI_I2S_SET_SDATA_BIT(data_num)
1606 | HDMI_I2S_BASIC_FORMAT);
1607
1608 /* Configure register related to CUV information */
1609 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1610 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1611 | HDMI_I2S_COPYRIGHT
1612 | HDMI_I2S_LINEAR_PCM
1613 | HDMI_I2S_CONSUMER_FORMAT);
1614 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1615 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1616 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1617 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1618 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1619 HDMI_I2S_ORG_SMP_FREQ_44_1
1620 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1621 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1622
1623 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1624}
1625
1626static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1627{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001628 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001629 return;
1630
1631 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1632 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1633 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1634}
1635
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001636static void hdmi_conf_reset(struct hdmi_context *hdata)
1637{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001638 u32 reg;
1639
Rahul Sharma5a325072012-10-04 20:48:54 +05301640 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001641 reg = HDMI_V13_CORE_RSTOUT;
1642 else
1643 reg = HDMI_CORE_RSTOUT;
1644
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001645 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001646 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001647 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001648 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001649 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001650}
1651
1652static void hdmi_conf_init(struct hdmi_context *hdata)
1653{
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301654 struct hdmi_infoframe infoframe;
1655
Sean Paul77006a72013-01-16 10:17:20 -05001656 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001657 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1658 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001659
1660 /* choose HDMI mode */
1661 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1662 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1663 /* disable bluescreen */
1664 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001665
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001666 if (hdata->dvi_mode) {
1667 /* choose DVI mode */
1668 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1669 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1670 hdmi_reg_writeb(hdata, HDMI_CON_2,
1671 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1672 }
1673
Rahul Sharma5a325072012-10-04 20:48:54 +05301674 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001675 /* choose bluescreen (fecal) color */
1676 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1677 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1678 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1679
1680 /* enable AVI packet every vsync, fixes purple line problem */
1681 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1682 /* force RGB, look to CEA-861-D, table 7 for more detail */
1683 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1684 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1685
1686 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1687 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1688 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1689 } else {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301690 infoframe.type = HDMI_PACKET_TYPE_AVI;
1691 infoframe.ver = HDMI_AVI_VERSION;
1692 infoframe.len = HDMI_AVI_LENGTH;
1693 hdmi_reg_infoframe(hdata, &infoframe);
1694
1695 infoframe.type = HDMI_PACKET_TYPE_AUI;
1696 infoframe.ver = HDMI_AUI_VERSION;
1697 infoframe.len = HDMI_AUI_LENGTH;
1698 hdmi_reg_infoframe(hdata, &infoframe);
1699
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001700 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001701 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1702 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001703}
1704
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001705static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001706{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001707 const struct hdmi_v13_preset_conf *conf =
1708 hdmi_v13_confs[hdata->cur_conf].conf;
1709 const struct hdmi_v13_core_regs *core = &conf->core;
1710 const struct hdmi_v13_tg_regs *tg = &conf->tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001711 int tries;
1712
1713 /* setting core registers */
1714 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1715 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001716 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1717 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1718 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1719 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1720 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1721 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001722 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1723 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001724 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1725 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1726 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1727 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1728 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1729 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1730 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1731 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1732 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1733 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1734 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1735 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1736 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1737 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1738 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001739 /* Timing generator registers */
1740 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1741 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1742 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1743 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1744 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1745 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1746 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1747 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1748 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1749 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1750 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1751 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1752 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1753 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1754 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1755 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1756 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1757 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1758 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1759 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1760 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1761 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1762 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1763 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1764 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1765 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1766 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1767 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1768
1769 /* waiting for HDMIPHY's PLL to get to steady state */
1770 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001771 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001772 if (val & HDMI_PHY_STATUS_READY)
1773 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001774 usleep_range(1000, 2000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001775 }
1776 /* steady state not achieved */
1777 if (tries == 0) {
1778 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1779 hdmi_regs_dump(hdata, "timing apply");
1780 }
1781
1782 clk_disable(hdata->res.sclk_hdmi);
1783 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1784 clk_enable(hdata->res.sclk_hdmi);
1785
1786 /* enable HDMI and timing generator */
1787 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1788 if (core->int_pro_mode[0])
1789 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1790 HDMI_FIELD_EN);
1791 else
1792 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1793}
1794
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001795static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1796{
1797 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
1798 const struct hdmi_core_regs *core = &conf->core;
1799 const struct hdmi_tg_regs *tg = &conf->tg;
1800 int tries;
1801
1802 /* setting core registers */
1803 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1804 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1805 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1806 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1807 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1808 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1809 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1810 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1811 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1812 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1813 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1814 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1815 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1816 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1817 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1818 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1819 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1820 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1821 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1822 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1823 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1824 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1825 core->v_sync_line_bef_2[0]);
1826 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1827 core->v_sync_line_bef_2[1]);
1828 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1829 core->v_sync_line_bef_1[0]);
1830 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1831 core->v_sync_line_bef_1[1]);
1832 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1833 core->v_sync_line_aft_2[0]);
1834 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1835 core->v_sync_line_aft_2[1]);
1836 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1837 core->v_sync_line_aft_1[0]);
1838 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1839 core->v_sync_line_aft_1[1]);
1840 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1841 core->v_sync_line_aft_pxl_2[0]);
1842 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1843 core->v_sync_line_aft_pxl_2[1]);
1844 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1845 core->v_sync_line_aft_pxl_1[0]);
1846 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1847 core->v_sync_line_aft_pxl_1[1]);
1848 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1849 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1850 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1851 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1852 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1853 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1854 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1855 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1856 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1857 core->v_sync_line_aft_3[0]);
1858 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1859 core->v_sync_line_aft_3[1]);
1860 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1861 core->v_sync_line_aft_4[0]);
1862 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1863 core->v_sync_line_aft_4[1]);
1864 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1865 core->v_sync_line_aft_5[0]);
1866 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1867 core->v_sync_line_aft_5[1]);
1868 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1869 core->v_sync_line_aft_6[0]);
1870 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1871 core->v_sync_line_aft_6[1]);
1872 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1873 core->v_sync_line_aft_pxl_3[0]);
1874 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1875 core->v_sync_line_aft_pxl_3[1]);
1876 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1877 core->v_sync_line_aft_pxl_4[0]);
1878 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1879 core->v_sync_line_aft_pxl_4[1]);
1880 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1881 core->v_sync_line_aft_pxl_5[0]);
1882 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1883 core->v_sync_line_aft_pxl_5[1]);
1884 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1885 core->v_sync_line_aft_pxl_6[0]);
1886 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1887 core->v_sync_line_aft_pxl_6[1]);
1888 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1889 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1890 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1891 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1892 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1893 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1894 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1895 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1896 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1897 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1898 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1899 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1900
1901 /* Timing generator registers */
1902 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1903 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1904 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1905 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1906 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1907 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1908 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1909 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1910 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1911 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1912 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1913 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1914 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1915 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1916 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1917 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1918 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1919 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1920 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1921 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1922 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
1923 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
1924 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
1925 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
1926 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1927 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1928 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1929 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1930 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1931 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1932 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1933 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1934 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
1935
1936 /* waiting for HDMIPHY's PLL to get to steady state */
1937 for (tries = 100; tries; --tries) {
1938 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1939 if (val & HDMI_PHY_STATUS_READY)
1940 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001941 usleep_range(1000, 2000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001942 }
1943 /* steady state not achieved */
1944 if (tries == 0) {
1945 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1946 hdmi_regs_dump(hdata, "timing apply");
1947 }
1948
1949 clk_disable(hdata->res.sclk_hdmi);
1950 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1951 clk_enable(hdata->res.sclk_hdmi);
1952
1953 /* enable HDMI and timing generator */
1954 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1955 if (core->int_pro_mode[0])
1956 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1957 HDMI_FIELD_EN);
1958 else
1959 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1960}
1961
1962static void hdmi_timing_apply(struct hdmi_context *hdata)
1963{
Rahul Sharma5a325072012-10-04 20:48:54 +05301964 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001965 hdmi_v13_timing_apply(hdata);
1966 else
1967 hdmi_v14_timing_apply(hdata);
1968}
1969
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001970static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1971{
1972 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001973 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001974
1975 clk_disable(hdata->res.sclk_hdmi);
1976 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1977 clk_enable(hdata->res.sclk_hdmi);
1978
1979 /* operation mode */
1980 buffer[0] = 0x1f;
1981 buffer[1] = 0x00;
1982
1983 if (hdata->hdmiphy_port)
1984 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1985
Rahul Sharma5a325072012-10-04 20:48:54 +05301986 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001987 reg = HDMI_V13_PHY_RSTOUT;
1988 else
1989 reg = HDMI_PHY_RSTOUT;
1990
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001991 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001992 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001993 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001994 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001995 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001996}
1997
Rahul Sharmaa5562252012-11-28 11:30:25 +05301998static void hdmiphy_poweron(struct hdmi_context *hdata)
1999{
2000 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2001
2002 if (hdata->type == HDMI_TYPE14)
2003 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
2004 HDMI_PHY_POWER_OFF_EN);
2005}
2006
2007static void hdmiphy_poweroff(struct hdmi_context *hdata)
2008{
2009 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2010
2011 if (hdata->type == HDMI_TYPE14)
2012 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
2013 HDMI_PHY_POWER_OFF_EN);
2014}
2015
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002016static void hdmiphy_conf_apply(struct hdmi_context *hdata)
2017{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002018 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002019 u8 buffer[32];
2020 u8 operation[2];
2021 u8 read_buffer[32] = {0, };
2022 int ret;
2023 int i;
2024
2025 if (!hdata->hdmiphy_port) {
2026 DRM_ERROR("hdmiphy is not attached\n");
2027 return;
2028 }
2029
2030 /* pixel clock */
Rahul Sharma5a325072012-10-04 20:48:54 +05302031 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002032 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
2033 else
2034 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
2035
2036 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002037 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
2038 if (ret != 32) {
2039 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
2040 return;
2041 }
2042
Sean Paul09760ea2013-01-14 17:03:20 -05002043 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002044
2045 /* operation mode */
2046 operation[0] = 0x1f;
2047 operation[1] = 0x80;
2048
2049 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
2050 if (ret != 2) {
2051 DRM_ERROR("failed to enable hdmiphy\n");
2052 return;
2053 }
2054
2055 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
2056 if (ret < 0) {
2057 DRM_ERROR("failed to read hdmiphy config\n");
2058 return;
2059 }
2060
2061 for (i = 0; i < ret; i++)
2062 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
2063 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
2064}
2065
2066static void hdmi_conf_apply(struct hdmi_context *hdata)
2067{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002068 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2069
2070 hdmiphy_conf_reset(hdata);
2071 hdmiphy_conf_apply(hdata);
2072
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002073 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002074 hdmi_conf_reset(hdata);
2075 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002076 mutex_unlock(&hdata->hdmi_mutex);
2077
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09002078 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002079
2080 /* setting core registers */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002081 hdmi_timing_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09002082 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002083
2084 hdmi_regs_dump(hdata, "start");
2085}
2086
Inki Dae1de425b2012-03-16 18:47:04 +09002087static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
Laurent Pincharte811f5a2012-07-17 17:56:50 +02002088 const struct drm_display_mode *mode,
Inki Dae1de425b2012-03-16 18:47:04 +09002089 struct drm_display_mode *adjusted_mode)
2090{
2091 struct drm_display_mode *m;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002092 struct hdmi_context *hdata = ctx;
Inki Dae1de425b2012-03-16 18:47:04 +09002093 int index;
2094
2095 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2096
2097 drm_mode_set_crtcinfo(adjusted_mode, 0);
2098
Rahul Sharma5a325072012-10-04 20:48:54 +05302099 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09002100 index = hdmi_v13_conf_index(adjusted_mode);
2101 else
2102 index = hdmi_v14_conf_index(adjusted_mode);
2103
2104 /* just return if user desired mode exists. */
2105 if (index >= 0)
2106 return;
2107
2108 /*
2109 * otherwise, find the most suitable mode among modes and change it
2110 * to adjusted_mode.
2111 */
2112 list_for_each_entry(m, &connector->modes, head) {
Rahul Sharma5a325072012-10-04 20:48:54 +05302113 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09002114 index = hdmi_v13_conf_index(m);
2115 else
2116 index = hdmi_v14_conf_index(m);
2117
2118 if (index >= 0) {
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05302119 struct drm_mode_object base;
2120 struct list_head head;
2121
Inki Dae1de425b2012-03-16 18:47:04 +09002122 DRM_INFO("desired mode doesn't exist so\n");
2123 DRM_INFO("use the most suitable mode among modes.\n");
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05302124
2125 /* preserve display mode header while copying. */
2126 head = adjusted_mode->head;
2127 base = adjusted_mode->base;
Inki Dae1de425b2012-03-16 18:47:04 +09002128 memcpy(adjusted_mode, m, sizeof(*m));
Rahul Sharmaa3f9bca2012-11-20 16:58:26 +05302129 adjusted_mode->head = head;
2130 adjusted_mode->base = base;
Inki Dae1de425b2012-03-16 18:47:04 +09002131 break;
2132 }
2133 }
2134}
2135
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002136static void hdmi_mode_set(void *ctx, void *mode)
2137{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002138 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002139 int conf_idx;
2140
2141 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2142
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09002143 conf_idx = hdmi_conf_index(hdata, mode);
2144 if (conf_idx >= 0)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002145 hdata->cur_conf = conf_idx;
2146 else
2147 DRM_DEBUG_KMS("not supported mode\n");
2148}
2149
Inki Dae1de425b2012-03-16 18:47:04 +09002150static void hdmi_get_max_resol(void *ctx, unsigned int *width,
2151 unsigned int *height)
2152{
2153 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2154
2155 *width = MAX_WIDTH;
2156 *height = MAX_HEIGHT;
2157}
2158
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002159static void hdmi_commit(void *ctx)
2160{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002161 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002162
2163 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2164
Shirish Sdda90122013-01-23 22:03:18 -05002165 mutex_lock(&hdata->hdmi_mutex);
2166 if (!hdata->powered) {
2167 mutex_unlock(&hdata->hdmi_mutex);
2168 return;
2169 }
2170 mutex_unlock(&hdata->hdmi_mutex);
2171
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002172 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002173}
2174
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002175static void hdmi_poweron(struct hdmi_context *hdata)
2176{
2177 struct hdmi_resources *res = &hdata->res;
2178
2179 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2180
2181 mutex_lock(&hdata->hdmi_mutex);
2182 if (hdata->powered) {
2183 mutex_unlock(&hdata->hdmi_mutex);
2184 return;
2185 }
2186
2187 hdata->powered = true;
2188
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002189 mutex_unlock(&hdata->hdmi_mutex);
2190
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002191 regulator_bulk_enable(res->regul_count, res->regul_bulk);
2192 clk_enable(res->hdmiphy);
2193 clk_enable(res->hdmi);
2194 clk_enable(res->sclk_hdmi);
Rahul Sharmaa5562252012-11-28 11:30:25 +05302195
2196 hdmiphy_poweron(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002197}
2198
2199static void hdmi_poweroff(struct hdmi_context *hdata)
2200{
2201 struct hdmi_resources *res = &hdata->res;
2202
2203 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2204
2205 mutex_lock(&hdata->hdmi_mutex);
2206 if (!hdata->powered)
2207 goto out;
2208 mutex_unlock(&hdata->hdmi_mutex);
2209
2210 /*
2211 * The TV power domain needs any condition of hdmiphy to turn off and
2212 * its reset state seems to meet the condition.
2213 */
2214 hdmiphy_conf_reset(hdata);
Rahul Sharmaa5562252012-11-28 11:30:25 +05302215 hdmiphy_poweroff(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002216
2217 clk_disable(res->sclk_hdmi);
2218 clk_disable(res->hdmi);
2219 clk_disable(res->hdmiphy);
2220 regulator_bulk_disable(res->regul_count, res->regul_bulk);
2221
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002222 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002223
2224 hdata->powered = false;
2225
2226out:
2227 mutex_unlock(&hdata->hdmi_mutex);
2228}
2229
2230static void hdmi_dpms(void *ctx, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002231{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002232 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002233
Rahul Sharma64327cb2012-11-28 11:30:23 +05302234 DRM_DEBUG_KMS("[%d] %s mode %d\n", __LINE__, __func__, mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002235
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002236 switch (mode) {
2237 case DRM_MODE_DPMS_ON:
Rahul Sharma64327cb2012-11-28 11:30:23 +05302238 if (pm_runtime_suspended(hdata->dev))
2239 pm_runtime_get_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002240 break;
2241 case DRM_MODE_DPMS_STANDBY:
2242 case DRM_MODE_DPMS_SUSPEND:
2243 case DRM_MODE_DPMS_OFF:
Rahul Sharma64327cb2012-11-28 11:30:23 +05302244 if (!pm_runtime_suspended(hdata->dev))
2245 pm_runtime_put_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002246 break;
2247 default:
2248 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
2249 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002250 }
2251}
2252
Joonyoung Shim578b6062012-04-05 20:49:26 +09002253static struct exynos_hdmi_ops hdmi_ops = {
2254 /* display */
2255 .is_connected = hdmi_is_connected,
2256 .get_edid = hdmi_get_edid,
2257 .check_timing = hdmi_check_timing,
Joonyoung Shim578b6062012-04-05 20:49:26 +09002258
2259 /* manager */
Inki Dae1de425b2012-03-16 18:47:04 +09002260 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002261 .mode_set = hdmi_mode_set,
Inki Dae1de425b2012-03-16 18:47:04 +09002262 .get_max_resol = hdmi_get_max_resol,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002263 .commit = hdmi_commit,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002264 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002265};
2266
Sean Paul77006a72013-01-16 10:17:20 -05002267static irqreturn_t hdmi_irq_thread(int irq, void *arg)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002268{
2269 struct exynos_drm_hdmi_context *ctx = arg;
2270 struct hdmi_context *hdata = ctx->ctx;
2271
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002272 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302273 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002274 mutex_unlock(&hdata->hdmi_mutex);
2275
2276 if (ctx->drm_dev)
2277 drm_helper_hpd_irq_event(ctx->drm_dev);
2278
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002279 return IRQ_HANDLED;
2280}
2281
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002282static int hdmi_resources_init(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002283{
2284 struct device *dev = hdata->dev;
2285 struct hdmi_resources *res = &hdata->res;
2286 static char *supply[] = {
2287 "hdmi-en",
2288 "vdd",
2289 "vdd_osc",
2290 "vdd_pll",
2291 };
2292 int i, ret;
2293
2294 DRM_DEBUG_KMS("HDMI resource init\n");
2295
Sachin Kamatadc837a2012-08-31 15:50:47 +05302296 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002297
2298 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302299 res->hdmi = devm_clk_get(dev, "hdmi");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002300 if (IS_ERR_OR_NULL(res->hdmi)) {
2301 DRM_ERROR("failed to get clock 'hdmi'\n");
2302 goto fail;
2303 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302304 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002305 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
2306 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2307 goto fail;
2308 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302309 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002310 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
2311 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2312 goto fail;
2313 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302314 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002315 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
2316 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2317 goto fail;
2318 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302319 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002320 if (IS_ERR_OR_NULL(res->hdmiphy)) {
2321 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2322 goto fail;
2323 }
2324
2325 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
2326
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302327 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05302328 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002329 if (!res->regul_bulk) {
2330 DRM_ERROR("failed to get memory for regulators\n");
2331 goto fail;
2332 }
2333 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
2334 res->regul_bulk[i].supply = supply[i];
2335 res->regul_bulk[i].consumer = NULL;
2336 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302337 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002338 if (ret) {
2339 DRM_ERROR("failed to get regulators\n");
2340 goto fail;
2341 }
2342 res->regul_count = ARRAY_SIZE(supply);
2343
2344 return 0;
2345fail:
2346 DRM_ERROR("HDMI resource init - failed\n");
2347 return -ENODEV;
2348}
2349
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002350static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2351
2352void hdmi_attach_ddc_client(struct i2c_client *ddc)
2353{
2354 if (ddc)
2355 hdmi_ddc = ddc;
2356}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002357
2358void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2359{
2360 if (hdmiphy)
2361 hdmi_hdmiphy = hdmiphy;
2362}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002363
Rahul Sharma22c4f422012-10-04 20:48:55 +05302364#ifdef CONFIG_OF
2365static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2366 (struct device *dev)
2367{
2368 struct device_node *np = dev->of_node;
2369 struct s5p_hdmi_platform_data *pd;
2370 enum of_gpio_flags flags;
2371 u32 value;
2372
2373 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
2374 if (!pd) {
2375 DRM_ERROR("memory allocation for pdata failed\n");
2376 goto err_data;
2377 }
2378
2379 if (!of_find_property(np, "hpd-gpio", &value)) {
2380 DRM_ERROR("no hpd gpio property found\n");
2381 goto err_data;
2382 }
2383
2384 pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
2385
2386 return pd;
2387
2388err_data:
2389 return NULL;
2390}
2391#else
2392static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2393 (struct device *dev)
2394{
2395 return NULL;
2396}
2397#endif
2398
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302399static struct platform_device_id hdmi_driver_types[] = {
2400 {
2401 .name = "s5pv210-hdmi",
2402 .driver_data = HDMI_TYPE13,
2403 }, {
2404 .name = "exynos4-hdmi",
2405 .driver_data = HDMI_TYPE13,
2406 }, {
2407 .name = "exynos4-hdmi14",
Rahul Sharma22c4f422012-10-04 20:48:55 +05302408 .driver_data = HDMI_TYPE14,
2409 }, {
2410 .name = "exynos5-hdmi",
2411 .driver_data = HDMI_TYPE14,
2412 }, {
2413 /* end node */
2414 }
2415};
2416
Sachin Kamat65da0352012-12-12 14:24:07 +05302417#ifdef CONFIG_OF
Rahul Sharma22c4f422012-10-04 20:48:55 +05302418static struct of_device_id hdmi_match_types[] = {
2419 {
2420 .compatible = "samsung,exynos5-hdmi",
2421 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302422 }, {
2423 /* end node */
2424 }
2425};
Sachin Kamat65da0352012-12-12 14:24:07 +05302426#endif
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302427
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002428static int hdmi_probe(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002429{
2430 struct device *dev = &pdev->dev;
2431 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2432 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302433 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002434 struct resource *res;
2435 int ret;
2436
2437 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2438
Rahul Sharma22c4f422012-10-04 20:48:55 +05302439 if (pdev->dev.of_node) {
2440 pdata = drm_hdmi_dt_parse_pdata(dev);
2441 if (IS_ERR(pdata)) {
2442 DRM_ERROR("failed to parse dt\n");
2443 return PTR_ERR(pdata);
2444 }
2445 } else {
2446 pdata = pdev->dev.platform_data;
2447 }
2448
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002449 if (!pdata) {
2450 DRM_ERROR("no platform data specified\n");
2451 return -EINVAL;
2452 }
2453
Sachin Kamata6e65072012-06-19 11:47:40 +05302454 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
2455 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002456 if (!drm_hdmi_ctx) {
2457 DRM_ERROR("failed to allocate common hdmi context.\n");
2458 return -ENOMEM;
2459 }
2460
Sachin Kamata6e65072012-06-19 11:47:40 +05302461 hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context),
2462 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002463 if (!hdata) {
2464 DRM_ERROR("out of memory\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002465 return -ENOMEM;
2466 }
2467
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002468 mutex_init(&hdata->hdmi_mutex);
2469
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002470 drm_hdmi_ctx->ctx = (void *)hdata;
2471 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2472
2473 platform_set_drvdata(pdev, drm_hdmi_ctx);
2474
Rahul Sharma22c4f422012-10-04 20:48:55 +05302475 if (dev->of_node) {
2476 const struct of_device_id *match;
2477 match = of_match_node(of_match_ptr(hdmi_match_types),
2478 pdev->dev.of_node);
Sachin Kamat1a4513b2012-12-12 14:24:08 +05302479 if (match == NULL)
2480 return -ENODEV;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302481 hdata->type = (enum hdmi_type)match->data;
2482 } else {
2483 hdata->type = (enum hdmi_type)platform_get_device_id
Rahul Sharma5a325072012-10-04 20:48:54 +05302484 (pdev)->driver_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302485 }
2486
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302487 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002488 hdata->dev = dev;
2489
2490 ret = hdmi_resources_init(hdata);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302491
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002492 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302493 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302494 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002495 }
2496
2497 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302498 if (!res) {
2499 DRM_ERROR("failed to find registers\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302500 return -ENOENT;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302501 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002502
Sachin Kamata6e65072012-06-19 11:47:40 +05302503 hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002504 if (!hdata->regs) {
2505 DRM_ERROR("failed to map registers\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302506 return -ENXIO;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002507 }
2508
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302509 ret = devm_gpio_request(&pdev->dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302510 if (ret) {
2511 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302512 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302513 }
2514
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002515 /* DDC i2c driver */
2516 if (i2c_add_driver(&ddc_driver)) {
2517 DRM_ERROR("failed to register ddc i2c driver\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302518 return -ENOENT;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002519 }
2520
2521 hdata->ddc_port = hdmi_ddc;
2522
2523 /* hdmiphy i2c driver */
2524 if (i2c_add_driver(&hdmiphy_driver)) {
2525 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2526 ret = -ENOENT;
2527 goto err_ddc;
2528 }
2529
2530 hdata->hdmiphy_port = hdmi_hdmiphy;
2531
Sean Paul77006a72013-01-16 10:17:20 -05002532 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
2533 if (hdata->irq < 0) {
2534 DRM_ERROR("failed to get GPIO irq\n");
2535 ret = hdata->irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002536 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002537 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002538
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302539 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2540
Sean Paul77006a72013-01-16 10:17:20 -05002541 ret = request_threaded_irq(hdata->irq, NULL,
2542 hdmi_irq_thread, IRQF_TRIGGER_RISING |
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002543 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sean Paul77006a72013-01-16 10:17:20 -05002544 "hdmi", drm_hdmi_ctx);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002545 if (ret) {
Sean Paul77006a72013-01-16 10:17:20 -05002546 DRM_ERROR("failed to register hdmi interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002547 goto err_hdmiphy;
2548 }
2549
Rahul Sharma768c3052012-10-04 20:48:56 +05302550 /* Attach HDMI Driver to common hdmi. */
2551 exynos_hdmi_drv_attach(drm_hdmi_ctx);
2552
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002553 /* register specific callbacks to common hdmi. */
Joonyoung Shim578b6062012-04-05 20:49:26 +09002554 exynos_hdmi_ops_register(&hdmi_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002555
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002556 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002557
2558 return 0;
2559
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002560err_hdmiphy:
2561 i2c_del_driver(&hdmiphy_driver);
2562err_ddc:
2563 i2c_del_driver(&ddc_driver);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002564 return ret;
2565}
2566
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002567static int hdmi_remove(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002568{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002569 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002570 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002571 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002572
2573 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2574
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002575 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002576
Sean Paul77006a72013-01-16 10:17:20 -05002577 free_irq(hdata->irq, hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002578
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002579
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002580 /* hdmiphy i2c driver */
2581 i2c_del_driver(&hdmiphy_driver);
2582 /* DDC i2c driver */
2583 i2c_del_driver(&ddc_driver);
2584
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002585 return 0;
2586}
2587
Joonyoung Shimab27af82012-04-23 19:35:51 +09002588#ifdef CONFIG_PM_SLEEP
2589static int hdmi_suspend(struct device *dev)
2590{
2591 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2592 struct hdmi_context *hdata = ctx->ctx;
2593
Rahul Sharma64327cb2012-11-28 11:30:23 +05302594 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2595
Sean Paul77006a72013-01-16 10:17:20 -05002596 disable_irq(hdata->irq);
Joonyoung Shimab27af82012-04-23 19:35:51 +09002597
2598 hdata->hpd = false;
2599 if (ctx->drm_dev)
2600 drm_helper_hpd_irq_event(ctx->drm_dev);
2601
Rahul Sharma64327cb2012-11-28 11:30:23 +05302602 if (pm_runtime_suspended(dev)) {
2603 DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
2604 return 0;
2605 }
2606
Joonyoung Shimab27af82012-04-23 19:35:51 +09002607 hdmi_poweroff(hdata);
2608
2609 return 0;
2610}
2611
2612static int hdmi_resume(struct device *dev)
2613{
2614 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2615 struct hdmi_context *hdata = ctx->ctx;
2616
Rahul Sharma64327cb2012-11-28 11:30:23 +05302617 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2618
2619 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2620
Sean Paul77006a72013-01-16 10:17:20 -05002621 enable_irq(hdata->irq);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302622
2623 if (!pm_runtime_suspended(dev)) {
2624 DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
2625 return 0;
2626 }
2627
2628 hdmi_poweron(hdata);
2629
Joonyoung Shimab27af82012-04-23 19:35:51 +09002630 return 0;
2631}
2632#endif
2633
Rahul Sharma64327cb2012-11-28 11:30:23 +05302634#ifdef CONFIG_PM_RUNTIME
2635static int hdmi_runtime_suspend(struct device *dev)
2636{
2637 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2638 struct hdmi_context *hdata = ctx->ctx;
2639 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2640
2641 hdmi_poweroff(hdata);
2642
2643 return 0;
2644}
2645
2646static int hdmi_runtime_resume(struct device *dev)
2647{
2648 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2649 struct hdmi_context *hdata = ctx->ctx;
2650 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2651
2652 hdmi_poweron(hdata);
2653
2654 return 0;
2655}
2656#endif
2657
2658static const struct dev_pm_ops hdmi_pm_ops = {
2659 SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
2660 SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
2661};
Joonyoung Shimab27af82012-04-23 19:35:51 +09002662
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002663struct platform_driver hdmi_driver = {
2664 .probe = hdmi_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002665 .remove = hdmi_remove,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302666 .id_table = hdmi_driver_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002667 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302668 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002669 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002670 .pm = &hdmi_pm_ops,
Sachin Kamat65da0352012-12-12 14:24:07 +05302671 .of_match_table = of_match_ptr(hdmi_match_types),
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002672 },
2673};