blob: ce13a23a8274cc0ef6f3518d66529d9b908a7758 [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;
Rahul Sharma59956d32013-06-11 12:24:03 +053086 struct clk *mout_hdmi;
Joonyoung Shim590f4182012-03-16 18:47:14 +090087 struct regulator_bulk_data *regul_bulk;
88 int regul_count;
89};
90
Sean Paul2f7e2ed2013-01-15 08:11:08 -050091struct hdmi_tg_regs {
92 u8 cmd[1];
93 u8 h_fsz[2];
94 u8 hact_st[2];
95 u8 hact_sz[2];
96 u8 v_fsz[2];
97 u8 vsync[2];
98 u8 vsync2[2];
99 u8 vact_st[2];
100 u8 vact_sz[2];
101 u8 field_chg[2];
102 u8 vact_st2[2];
103 u8 vact_st3[2];
104 u8 vact_st4[2];
105 u8 vsync_top_hdmi[2];
106 u8 vsync_bot_hdmi[2];
107 u8 field_top_hdmi[2];
108 u8 field_bot_hdmi[2];
109 u8 tg_3d[1];
110};
111
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900112struct hdmi_v13_core_regs {
113 u8 h_blank[2];
114 u8 v_blank[3];
115 u8 h_v_line[3];
116 u8 vsync_pol[1];
117 u8 int_pro_mode[1];
118 u8 v_blank_f[3];
119 u8 h_sync_gen[3];
120 u8 v_sync_gen1[3];
121 u8 v_sync_gen2[3];
122 u8 v_sync_gen3[3];
123};
124
125struct hdmi_v14_core_regs {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500126 u8 h_blank[2];
127 u8 v2_blank[2];
128 u8 v1_blank[2];
129 u8 v_line[2];
130 u8 h_line[2];
131 u8 hsync_pol[1];
132 u8 vsync_pol[1];
133 u8 int_pro_mode[1];
134 u8 v_blank_f0[2];
135 u8 v_blank_f1[2];
136 u8 h_sync_start[2];
137 u8 h_sync_end[2];
138 u8 v_sync_line_bef_2[2];
139 u8 v_sync_line_bef_1[2];
140 u8 v_sync_line_aft_2[2];
141 u8 v_sync_line_aft_1[2];
142 u8 v_sync_line_aft_pxl_2[2];
143 u8 v_sync_line_aft_pxl_1[2];
144 u8 v_blank_f2[2]; /* for 3D mode */
145 u8 v_blank_f3[2]; /* for 3D mode */
146 u8 v_blank_f4[2]; /* for 3D mode */
147 u8 v_blank_f5[2]; /* for 3D mode */
148 u8 v_sync_line_aft_3[2];
149 u8 v_sync_line_aft_4[2];
150 u8 v_sync_line_aft_5[2];
151 u8 v_sync_line_aft_6[2];
152 u8 v_sync_line_aft_pxl_3[2];
153 u8 v_sync_line_aft_pxl_4[2];
154 u8 v_sync_line_aft_pxl_5[2];
155 u8 v_sync_line_aft_pxl_6[2];
156 u8 vact_space_1[2];
157 u8 vact_space_2[2];
158 u8 vact_space_3[2];
159 u8 vact_space_4[2];
160 u8 vact_space_5[2];
161 u8 vact_space_6[2];
162};
163
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900164struct hdmi_v13_conf {
165 struct hdmi_v13_core_regs core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500166 struct hdmi_tg_regs tg;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900167};
168
169struct hdmi_v14_conf {
170 struct hdmi_v14_core_regs core;
171 struct hdmi_tg_regs tg;
172};
173
174struct hdmi_conf_regs {
175 int pixel_clock;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500176 int cea_video_id;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900177 union {
178 struct hdmi_v13_conf v13_conf;
179 struct hdmi_v14_conf v14_conf;
180 } conf;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500181};
182
Joonyoung Shim590f4182012-03-16 18:47:14 +0900183struct hdmi_context {
184 struct device *dev;
185 struct drm_device *drm_dev;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900186 bool hpd;
187 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +0900188 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900189 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900190
Joonyoung Shim590f4182012-03-16 18:47:14 +0900191 void __iomem *regs;
Inki Dae1055b392012-10-19 17:37:35 +0900192 void *parent_ctx;
Sean Paul77006a72013-01-16 10:17:20 -0500193 int irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900194
195 struct i2c_client *ddc_port;
196 struct i2c_client *hdmiphy_port;
197
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900198 /* current hdmiphy conf regs */
199 struct hdmi_conf_regs mode_conf;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900200
201 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900202
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530203 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530204
205 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900206};
207
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500208struct hdmiphy_config {
209 int pixel_clock;
210 u8 conf[32];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900211};
212
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900213/* list of phy config settings */
214static const struct hdmiphy_config hdmiphy_v13_configs[] = {
215 {
216 .pixel_clock = 27000000,
217 .conf = {
218 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
219 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
220 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
221 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
222 },
223 },
224 {
225 .pixel_clock = 27027000,
226 .conf = {
227 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
228 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
229 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
230 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
231 },
232 },
233 {
234 .pixel_clock = 74176000,
235 .conf = {
236 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
237 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
238 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
239 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
240 },
241 },
242 {
243 .pixel_clock = 74250000,
244 .conf = {
245 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
246 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
247 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
248 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
249 },
250 },
251 {
252 .pixel_clock = 148500000,
253 .conf = {
254 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
255 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
256 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
257 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
258 },
259 },
260};
261
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500262static const struct hdmiphy_config hdmiphy_v14_configs[] = {
263 {
264 .pixel_clock = 25200000,
265 .conf = {
266 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
267 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
268 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
269 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
270 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900271 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500272 {
273 .pixel_clock = 27000000,
274 .conf = {
275 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
276 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
277 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
278 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
279 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900280 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500281 {
282 .pixel_clock = 27027000,
283 .conf = {
284 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
285 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
286 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
287 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
288 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900289 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500290 {
291 .pixel_clock = 36000000,
292 .conf = {
293 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
294 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
295 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
296 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
297 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900298 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500299 {
300 .pixel_clock = 40000000,
301 .conf = {
302 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
303 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
304 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
305 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
306 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900307 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500308 {
309 .pixel_clock = 65000000,
310 .conf = {
311 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
312 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
313 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
314 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
315 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900316 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500317 {
318 .pixel_clock = 74176000,
319 .conf = {
320 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
321 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
322 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
323 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
324 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900325 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500326 {
327 .pixel_clock = 74250000,
328 .conf = {
329 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
330 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
331 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
332 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
333 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900334 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500335 {
336 .pixel_clock = 83500000,
337 .conf = {
338 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
339 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
340 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
341 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
342 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900343 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500344 {
345 .pixel_clock = 106500000,
346 .conf = {
347 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
348 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
349 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
350 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
351 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900352 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500353 {
354 .pixel_clock = 108000000,
355 .conf = {
356 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
357 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
358 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
359 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
360 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900361 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500362 {
363 .pixel_clock = 146250000,
364 .conf = {
365 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
366 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
367 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
368 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
369 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900370 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500371 {
372 .pixel_clock = 148500000,
373 .conf = {
374 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
375 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
376 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
377 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
378 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900379 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900380};
381
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530382struct hdmi_infoframe {
383 enum HDMI_PACKET_TYPE type;
384 u8 ver;
385 u8 len;
386};
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900387
388static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
389{
390 return readl(hdata->regs + reg_id);
391}
392
393static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
394 u32 reg_id, u8 value)
395{
396 writeb(value, hdata->regs + reg_id);
397}
398
399static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
400 u32 reg_id, u32 value, u32 mask)
401{
402 u32 old = readl(hdata->regs + reg_id);
403 value = (value & mask) | (old & ~mask);
404 writel(value, hdata->regs + reg_id);
405}
406
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900407static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900408{
409#define DUMPREG(reg_id) \
410 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
411 readl(hdata->regs + reg_id))
412 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
413 DUMPREG(HDMI_INTC_FLAG);
414 DUMPREG(HDMI_INTC_CON);
415 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900416 DUMPREG(HDMI_V13_PHY_RSTOUT);
417 DUMPREG(HDMI_V13_PHY_VPLL);
418 DUMPREG(HDMI_V13_PHY_CMU);
419 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900420
421 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
422 DUMPREG(HDMI_CON_0);
423 DUMPREG(HDMI_CON_1);
424 DUMPREG(HDMI_CON_2);
425 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900426 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900427 DUMPREG(HDMI_STATUS_EN);
428 DUMPREG(HDMI_HPD);
429 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900430 DUMPREG(HDMI_V13_HPD_GEN);
431 DUMPREG(HDMI_V13_DC_CONTROL);
432 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900433
434 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
435 DUMPREG(HDMI_H_BLANK_0);
436 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900437 DUMPREG(HDMI_V13_V_BLANK_0);
438 DUMPREG(HDMI_V13_V_BLANK_1);
439 DUMPREG(HDMI_V13_V_BLANK_2);
440 DUMPREG(HDMI_V13_H_V_LINE_0);
441 DUMPREG(HDMI_V13_H_V_LINE_1);
442 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900443 DUMPREG(HDMI_VSYNC_POL);
444 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900445 DUMPREG(HDMI_V13_V_BLANK_F_0);
446 DUMPREG(HDMI_V13_V_BLANK_F_1);
447 DUMPREG(HDMI_V13_V_BLANK_F_2);
448 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
449 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
450 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
451 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
452 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
453 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
454 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
455 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
456 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
457 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
458 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
459 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900460
461 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
462 DUMPREG(HDMI_TG_CMD);
463 DUMPREG(HDMI_TG_H_FSZ_L);
464 DUMPREG(HDMI_TG_H_FSZ_H);
465 DUMPREG(HDMI_TG_HACT_ST_L);
466 DUMPREG(HDMI_TG_HACT_ST_H);
467 DUMPREG(HDMI_TG_HACT_SZ_L);
468 DUMPREG(HDMI_TG_HACT_SZ_H);
469 DUMPREG(HDMI_TG_V_FSZ_L);
470 DUMPREG(HDMI_TG_V_FSZ_H);
471 DUMPREG(HDMI_TG_VSYNC_L);
472 DUMPREG(HDMI_TG_VSYNC_H);
473 DUMPREG(HDMI_TG_VSYNC2_L);
474 DUMPREG(HDMI_TG_VSYNC2_H);
475 DUMPREG(HDMI_TG_VACT_ST_L);
476 DUMPREG(HDMI_TG_VACT_ST_H);
477 DUMPREG(HDMI_TG_VACT_SZ_L);
478 DUMPREG(HDMI_TG_VACT_SZ_H);
479 DUMPREG(HDMI_TG_FIELD_CHG_L);
480 DUMPREG(HDMI_TG_FIELD_CHG_H);
481 DUMPREG(HDMI_TG_VACT_ST2_L);
482 DUMPREG(HDMI_TG_VACT_ST2_H);
483 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
484 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
485 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
486 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
487 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
488 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
489 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
490 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
491#undef DUMPREG
492}
493
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900494static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
495{
496 int i;
497
498#define DUMPREG(reg_id) \
499 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
500 readl(hdata->regs + reg_id))
501
502 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
503 DUMPREG(HDMI_INTC_CON);
504 DUMPREG(HDMI_INTC_FLAG);
505 DUMPREG(HDMI_HPD_STATUS);
506 DUMPREG(HDMI_INTC_CON_1);
507 DUMPREG(HDMI_INTC_FLAG_1);
508 DUMPREG(HDMI_PHY_STATUS_0);
509 DUMPREG(HDMI_PHY_STATUS_PLL);
510 DUMPREG(HDMI_PHY_CON_0);
511 DUMPREG(HDMI_PHY_RSTOUT);
512 DUMPREG(HDMI_PHY_VPLL);
513 DUMPREG(HDMI_PHY_CMU);
514 DUMPREG(HDMI_CORE_RSTOUT);
515
516 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
517 DUMPREG(HDMI_CON_0);
518 DUMPREG(HDMI_CON_1);
519 DUMPREG(HDMI_CON_2);
520 DUMPREG(HDMI_SYS_STATUS);
521 DUMPREG(HDMI_PHY_STATUS_0);
522 DUMPREG(HDMI_STATUS_EN);
523 DUMPREG(HDMI_HPD);
524 DUMPREG(HDMI_MODE_SEL);
525 DUMPREG(HDMI_ENC_EN);
526 DUMPREG(HDMI_DC_CONTROL);
527 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
528
529 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
530 DUMPREG(HDMI_H_BLANK_0);
531 DUMPREG(HDMI_H_BLANK_1);
532 DUMPREG(HDMI_V2_BLANK_0);
533 DUMPREG(HDMI_V2_BLANK_1);
534 DUMPREG(HDMI_V1_BLANK_0);
535 DUMPREG(HDMI_V1_BLANK_1);
536 DUMPREG(HDMI_V_LINE_0);
537 DUMPREG(HDMI_V_LINE_1);
538 DUMPREG(HDMI_H_LINE_0);
539 DUMPREG(HDMI_H_LINE_1);
540 DUMPREG(HDMI_HSYNC_POL);
541
542 DUMPREG(HDMI_VSYNC_POL);
543 DUMPREG(HDMI_INT_PRO_MODE);
544 DUMPREG(HDMI_V_BLANK_F0_0);
545 DUMPREG(HDMI_V_BLANK_F0_1);
546 DUMPREG(HDMI_V_BLANK_F1_0);
547 DUMPREG(HDMI_V_BLANK_F1_1);
548
549 DUMPREG(HDMI_H_SYNC_START_0);
550 DUMPREG(HDMI_H_SYNC_START_1);
551 DUMPREG(HDMI_H_SYNC_END_0);
552 DUMPREG(HDMI_H_SYNC_END_1);
553
554 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
555 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
556 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
557 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
558
559 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
560 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
561 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
562 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
563
564 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
565 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
566 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
567 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
568
569 DUMPREG(HDMI_V_BLANK_F2_0);
570 DUMPREG(HDMI_V_BLANK_F2_1);
571 DUMPREG(HDMI_V_BLANK_F3_0);
572 DUMPREG(HDMI_V_BLANK_F3_1);
573 DUMPREG(HDMI_V_BLANK_F4_0);
574 DUMPREG(HDMI_V_BLANK_F4_1);
575 DUMPREG(HDMI_V_BLANK_F5_0);
576 DUMPREG(HDMI_V_BLANK_F5_1);
577
578 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
579 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
580 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
581 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
582 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
583 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
584 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
585 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
586
587 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
588 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
589 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
590 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
591 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
592 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
593 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
594 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
595
596 DUMPREG(HDMI_VACT_SPACE_1_0);
597 DUMPREG(HDMI_VACT_SPACE_1_1);
598 DUMPREG(HDMI_VACT_SPACE_2_0);
599 DUMPREG(HDMI_VACT_SPACE_2_1);
600 DUMPREG(HDMI_VACT_SPACE_3_0);
601 DUMPREG(HDMI_VACT_SPACE_3_1);
602 DUMPREG(HDMI_VACT_SPACE_4_0);
603 DUMPREG(HDMI_VACT_SPACE_4_1);
604 DUMPREG(HDMI_VACT_SPACE_5_0);
605 DUMPREG(HDMI_VACT_SPACE_5_1);
606 DUMPREG(HDMI_VACT_SPACE_6_0);
607 DUMPREG(HDMI_VACT_SPACE_6_1);
608
609 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
610 DUMPREG(HDMI_TG_CMD);
611 DUMPREG(HDMI_TG_H_FSZ_L);
612 DUMPREG(HDMI_TG_H_FSZ_H);
613 DUMPREG(HDMI_TG_HACT_ST_L);
614 DUMPREG(HDMI_TG_HACT_ST_H);
615 DUMPREG(HDMI_TG_HACT_SZ_L);
616 DUMPREG(HDMI_TG_HACT_SZ_H);
617 DUMPREG(HDMI_TG_V_FSZ_L);
618 DUMPREG(HDMI_TG_V_FSZ_H);
619 DUMPREG(HDMI_TG_VSYNC_L);
620 DUMPREG(HDMI_TG_VSYNC_H);
621 DUMPREG(HDMI_TG_VSYNC2_L);
622 DUMPREG(HDMI_TG_VSYNC2_H);
623 DUMPREG(HDMI_TG_VACT_ST_L);
624 DUMPREG(HDMI_TG_VACT_ST_H);
625 DUMPREG(HDMI_TG_VACT_SZ_L);
626 DUMPREG(HDMI_TG_VACT_SZ_H);
627 DUMPREG(HDMI_TG_FIELD_CHG_L);
628 DUMPREG(HDMI_TG_FIELD_CHG_H);
629 DUMPREG(HDMI_TG_VACT_ST2_L);
630 DUMPREG(HDMI_TG_VACT_ST2_H);
631 DUMPREG(HDMI_TG_VACT_ST3_L);
632 DUMPREG(HDMI_TG_VACT_ST3_H);
633 DUMPREG(HDMI_TG_VACT_ST4_L);
634 DUMPREG(HDMI_TG_VACT_ST4_H);
635 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
636 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
637 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
638 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
639 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
640 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
641 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
642 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
643 DUMPREG(HDMI_TG_3D);
644
645 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
646 DUMPREG(HDMI_AVI_CON);
647 DUMPREG(HDMI_AVI_HEADER0);
648 DUMPREG(HDMI_AVI_HEADER1);
649 DUMPREG(HDMI_AVI_HEADER2);
650 DUMPREG(HDMI_AVI_CHECK_SUM);
651 DUMPREG(HDMI_VSI_CON);
652 DUMPREG(HDMI_VSI_HEADER0);
653 DUMPREG(HDMI_VSI_HEADER1);
654 DUMPREG(HDMI_VSI_HEADER2);
655 for (i = 0; i < 7; ++i)
656 DUMPREG(HDMI_VSI_DATA(i));
657
658#undef DUMPREG
659}
660
661static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
662{
Rahul Sharma5a325072012-10-04 20:48:54 +0530663 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900664 hdmi_v13_regs_dump(hdata, prefix);
665 else
666 hdmi_v14_regs_dump(hdata, prefix);
667}
668
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530669static u8 hdmi_chksum(struct hdmi_context *hdata,
670 u32 start, u8 len, u32 hdr_sum)
671{
672 int i;
673
674 /* hdr_sum : header0 + header1 + header2
675 * start : start address of packet byte1
676 * len : packet bytes - 1 */
677 for (i = 0; i < len; ++i)
678 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
679
680 /* return 2's complement of 8 bit hdr_sum */
681 return (u8)(~(hdr_sum & 0xff) + 1);
682}
683
684static void hdmi_reg_infoframe(struct hdmi_context *hdata,
685 struct hdmi_infoframe *infoframe)
686{
687 u32 hdr_sum;
688 u8 chksum;
689 u32 aspect_ratio;
690 u32 mod;
691 u32 vic;
692
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530693 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
694 if (hdata->dvi_mode) {
695 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
696 HDMI_VSI_CON_DO_NOT_TRANSMIT);
697 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
698 HDMI_AVI_CON_DO_NOT_TRANSMIT);
699 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
700 return;
701 }
702
703 switch (infoframe->type) {
704 case HDMI_PACKET_TYPE_AVI:
705 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
706 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->type);
707 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1, infoframe->ver);
708 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->len);
709 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
710
711 /* Output format zero hardcoded ,RGB YBCR selection */
712 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
713 AVI_ACTIVE_FORMAT_VALID |
714 AVI_UNDERSCANNED_DISPLAY_VALID);
715
716 aspect_ratio = AVI_PIC_ASPECT_RATIO_16_9;
717
718 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), aspect_ratio |
719 AVI_SAME_AS_PIC_ASPECT_RATIO);
720
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900721 vic = hdata->mode_conf.cea_video_id;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530722 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
723
724 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
725 infoframe->len, hdr_sum);
726 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
727 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
728 break;
729 case HDMI_PACKET_TYPE_AUI:
730 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
731 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->type);
732 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1, infoframe->ver);
733 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->len);
734 hdr_sum = infoframe->type + infoframe->ver + infoframe->len;
735 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
736 infoframe->len, hdr_sum);
737 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
738 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
739 break;
740 default:
741 break;
742 }
743}
744
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900745static bool hdmi_is_connected(void *ctx)
746{
Joonyoung Shimf9309d12012-04-05 20:49:22 +0900747 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900748
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900749 return hdata->hpd;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900750}
751
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500752static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900753{
754 struct edid *raw_edid;
Joonyoung Shimf9309d12012-04-05 20:49:22 +0900755 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900756
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900757 if (!hdata->ddc_port)
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500758 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900759
760 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500761 if (!raw_edid)
762 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900763
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500764 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
765 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
766 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
767 raw_edid->width_cm, raw_edid->height_cm);
768
769 return raw_edid;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900770}
771
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900772static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900773{
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900774 const struct hdmiphy_config *confs;
775 int count, i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900776
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900777 if (hdata->type == HDMI_TYPE13) {
778 confs = hdmiphy_v13_configs;
779 count = ARRAY_SIZE(hdmiphy_v13_configs);
780 } else if (hdata->type == HDMI_TYPE14) {
781 confs = hdmiphy_v14_configs;
782 count = ARRAY_SIZE(hdmiphy_v14_configs);
783 } else
784 return -EINVAL;
Inki Dae1de425b2012-03-16 18:47:04 +0900785
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900786 for (i = 0; i < count; i++)
787 if (confs[i].pixel_clock == pixel_clock)
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500788 return i;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500789
790 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
791 return -EINVAL;
792}
793
Rahul Sharma16844fb2013-06-10 14:50:00 +0530794static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900795{
Joonyoung Shimf9309d12012-04-05 20:49:22 +0900796 struct hdmi_context *hdata = ctx;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900797 int ret;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900798
Rahul Sharma16844fb2013-06-10 14:50:00 +0530799 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
800 mode->hdisplay, mode->vdisplay, mode->vrefresh,
801 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
802 false, mode->clock * 1000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900803
Rahul Sharma16844fb2013-06-10 14:50:00 +0530804 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900805 if (ret < 0)
806 return ret;
807 return 0;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900808}
809
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900810static void hdmi_set_acr(u32 freq, u8 *acr)
811{
812 u32 n, cts;
813
814 switch (freq) {
815 case 32000:
816 n = 4096;
817 cts = 27000;
818 break;
819 case 44100:
820 n = 6272;
821 cts = 30000;
822 break;
823 case 88200:
824 n = 12544;
825 cts = 30000;
826 break;
827 case 176400:
828 n = 25088;
829 cts = 30000;
830 break;
831 case 48000:
832 n = 6144;
833 cts = 27000;
834 break;
835 case 96000:
836 n = 12288;
837 cts = 27000;
838 break;
839 case 192000:
840 n = 24576;
841 cts = 27000;
842 break;
843 default:
844 n = 0;
845 cts = 0;
846 break;
847 }
848
849 acr[1] = cts >> 16;
850 acr[2] = cts >> 8 & 0xff;
851 acr[3] = cts & 0xff;
852
853 acr[4] = n >> 16;
854 acr[5] = n >> 8 & 0xff;
855 acr[6] = n & 0xff;
856}
857
858static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
859{
860 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
861 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
862 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
863 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
864 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
865 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
866 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
867 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
868 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
869
Rahul Sharma5a325072012-10-04 20:48:54 +0530870 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900871 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
872 else
873 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
874}
875
876static void hdmi_audio_init(struct hdmi_context *hdata)
877{
878 u32 sample_rate, bits_per_sample, frame_size_code;
879 u32 data_num, bit_ch, sample_frq;
880 u32 val;
881 u8 acr[7];
882
883 sample_rate = 44100;
884 bits_per_sample = 16;
885 frame_size_code = 0;
886
887 switch (bits_per_sample) {
888 case 20:
889 data_num = 2;
890 bit_ch = 1;
891 break;
892 case 24:
893 data_num = 3;
894 bit_ch = 1;
895 break;
896 default:
897 data_num = 1;
898 bit_ch = 0;
899 break;
900 }
901
902 hdmi_set_acr(sample_rate, acr);
903 hdmi_reg_acr(hdata, acr);
904
905 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
906 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
907 | HDMI_I2S_MUX_ENABLE);
908
909 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
910 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
911
912 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
913
914 sample_frq = (sample_rate == 44100) ? 0 :
915 (sample_rate == 48000) ? 2 :
916 (sample_rate == 32000) ? 3 :
917 (sample_rate == 96000) ? 0xa : 0x0;
918
919 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
920 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
921
922 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
923 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
924
925 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
926 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
927 | HDMI_I2S_SEL_LRCK(6));
928 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
929 | HDMI_I2S_SEL_SDATA2(4));
930 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
931 | HDMI_I2S_SEL_SDATA2(2));
932 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
933
934 /* I2S_CON_1 & 2 */
935 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
936 | HDMI_I2S_L_CH_LOW_POL);
937 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
938 | HDMI_I2S_SET_BIT_CH(bit_ch)
939 | HDMI_I2S_SET_SDATA_BIT(data_num)
940 | HDMI_I2S_BASIC_FORMAT);
941
942 /* Configure register related to CUV information */
943 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
944 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
945 | HDMI_I2S_COPYRIGHT
946 | HDMI_I2S_LINEAR_PCM
947 | HDMI_I2S_CONSUMER_FORMAT);
948 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
949 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
950 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
951 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
952 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
953 HDMI_I2S_ORG_SMP_FREQ_44_1
954 | HDMI_I2S_WORD_LEN_MAX24_24BITS
955 | HDMI_I2S_WORD_LEN_MAX_24BITS);
956
957 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
958}
959
960static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
961{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +0900962 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900963 return;
964
965 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
966 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
967 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
968}
969
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900970static void hdmi_conf_reset(struct hdmi_context *hdata)
971{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900972 u32 reg;
973
Rahul Sharma5a325072012-10-04 20:48:54 +0530974 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900975 reg = HDMI_V13_CORE_RSTOUT;
976 else
977 reg = HDMI_CORE_RSTOUT;
978
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900979 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900980 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -0500981 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900982 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -0500983 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900984}
985
986static void hdmi_conf_init(struct hdmi_context *hdata)
987{
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530988 struct hdmi_infoframe infoframe;
989
Sean Paul77006a72013-01-16 10:17:20 -0500990 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900991 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
992 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900993
994 /* choose HDMI mode */
995 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
996 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
997 /* disable bluescreen */
998 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900999
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001000 if (hdata->dvi_mode) {
1001 /* choose DVI mode */
1002 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1003 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1004 hdmi_reg_writeb(hdata, HDMI_CON_2,
1005 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1006 }
1007
Rahul Sharma5a325072012-10-04 20:48:54 +05301008 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001009 /* choose bluescreen (fecal) color */
1010 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1011 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1012 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1013
1014 /* enable AVI packet every vsync, fixes purple line problem */
1015 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1016 /* force RGB, look to CEA-861-D, table 7 for more detail */
1017 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1018 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1019
1020 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1021 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1022 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1023 } else {
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301024 infoframe.type = HDMI_PACKET_TYPE_AVI;
1025 infoframe.ver = HDMI_AVI_VERSION;
1026 infoframe.len = HDMI_AVI_LENGTH;
1027 hdmi_reg_infoframe(hdata, &infoframe);
1028
1029 infoframe.type = HDMI_PACKET_TYPE_AUI;
1030 infoframe.ver = HDMI_AUI_VERSION;
1031 infoframe.len = HDMI_AUI_LENGTH;
1032 hdmi_reg_infoframe(hdata, &infoframe);
1033
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001034 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001035 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1036 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001037}
1038
Rahul Sharma16844fb2013-06-10 14:50:00 +05301039static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001040{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001041 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1042 const struct hdmi_v13_core_regs *core =
1043 &hdata->mode_conf.conf.v13_conf.core;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001044 int tries;
1045
1046 /* setting core registers */
1047 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1048 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001049 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1050 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1051 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1052 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1053 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1054 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001055 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1056 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001057 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1058 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1059 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1060 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1061 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1062 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1063 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1064 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1065 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1066 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1067 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1068 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1069 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1070 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1071 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001072 /* Timing generator registers */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001073 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1074 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1075 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1076 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1077 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1078 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1079 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1080 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1081 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1082 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1083 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1084 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1085 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1086 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1087 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1088 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1089 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1090 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1091 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1092 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1093 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1094 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1095 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1096 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1097 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1098 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1099 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1100 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001101
1102 /* waiting for HDMIPHY's PLL to get to steady state */
1103 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001104 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001105 if (val & HDMI_PHY_STATUS_READY)
1106 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001107 usleep_range(1000, 2000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001108 }
1109 /* steady state not achieved */
1110 if (tries == 0) {
1111 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1112 hdmi_regs_dump(hdata, "timing apply");
1113 }
1114
Sean Paul0bfb1f82013-06-11 12:24:02 +05301115 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301116 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301117 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001118
1119 /* enable HDMI and timing generator */
1120 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1121 if (core->int_pro_mode[0])
1122 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1123 HDMI_FIELD_EN);
1124 else
1125 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1126}
1127
Rahul Sharma16844fb2013-06-10 14:50:00 +05301128static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001129{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001130 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1131 const struct hdmi_v14_core_regs *core =
1132 &hdata->mode_conf.conf.v14_conf.core;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001133 int tries;
1134
1135 /* setting core registers */
1136 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1137 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1138 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1139 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1140 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1141 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1142 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1143 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1144 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1145 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1146 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1147 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1148 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1149 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1150 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1151 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1152 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1153 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1154 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1155 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1156 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1157 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1158 core->v_sync_line_bef_2[0]);
1159 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1160 core->v_sync_line_bef_2[1]);
1161 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1162 core->v_sync_line_bef_1[0]);
1163 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1164 core->v_sync_line_bef_1[1]);
1165 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1166 core->v_sync_line_aft_2[0]);
1167 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1168 core->v_sync_line_aft_2[1]);
1169 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1170 core->v_sync_line_aft_1[0]);
1171 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1172 core->v_sync_line_aft_1[1]);
1173 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1174 core->v_sync_line_aft_pxl_2[0]);
1175 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1176 core->v_sync_line_aft_pxl_2[1]);
1177 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1178 core->v_sync_line_aft_pxl_1[0]);
1179 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1180 core->v_sync_line_aft_pxl_1[1]);
1181 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1182 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1183 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1184 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1185 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1186 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1187 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1188 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1189 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1190 core->v_sync_line_aft_3[0]);
1191 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1192 core->v_sync_line_aft_3[1]);
1193 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1194 core->v_sync_line_aft_4[0]);
1195 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1196 core->v_sync_line_aft_4[1]);
1197 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1198 core->v_sync_line_aft_5[0]);
1199 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1200 core->v_sync_line_aft_5[1]);
1201 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1202 core->v_sync_line_aft_6[0]);
1203 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1204 core->v_sync_line_aft_6[1]);
1205 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1206 core->v_sync_line_aft_pxl_3[0]);
1207 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1208 core->v_sync_line_aft_pxl_3[1]);
1209 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1210 core->v_sync_line_aft_pxl_4[0]);
1211 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1212 core->v_sync_line_aft_pxl_4[1]);
1213 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1214 core->v_sync_line_aft_pxl_5[0]);
1215 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1216 core->v_sync_line_aft_pxl_5[1]);
1217 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1218 core->v_sync_line_aft_pxl_6[0]);
1219 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1220 core->v_sync_line_aft_pxl_6[1]);
1221 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1222 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1223 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1224 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1225 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1226 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1227 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1228 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1229 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1230 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1231 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1232 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1233
1234 /* Timing generator registers */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001235 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1236 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1237 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1238 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1239 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1240 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1241 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1242 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1243 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1244 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1245 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1246 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1247 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1248 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1249 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1250 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1251 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1252 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1253 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1254 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1255 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
1256 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
1257 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
1258 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
1259 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1260 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1261 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1262 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1263 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1264 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1265 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1266 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1267 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001268
1269 /* waiting for HDMIPHY's PLL to get to steady state */
1270 for (tries = 100; tries; --tries) {
1271 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1272 if (val & HDMI_PHY_STATUS_READY)
1273 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001274 usleep_range(1000, 2000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001275 }
1276 /* steady state not achieved */
1277 if (tries == 0) {
1278 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1279 hdmi_regs_dump(hdata, "timing apply");
1280 }
1281
Sean Paul0bfb1f82013-06-11 12:24:02 +05301282 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301283 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301284 clk_prepare_enable(hdata->res.sclk_hdmi);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001285
1286 /* enable HDMI and timing generator */
1287 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1288 if (core->int_pro_mode[0])
1289 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1290 HDMI_FIELD_EN);
1291 else
1292 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1293}
1294
Rahul Sharma16844fb2013-06-10 14:50:00 +05301295static void hdmi_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001296{
Rahul Sharma5a325072012-10-04 20:48:54 +05301297 if (hdata->type == HDMI_TYPE13)
Rahul Sharma16844fb2013-06-10 14:50:00 +05301298 hdmi_v13_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001299 else
Rahul Sharma16844fb2013-06-10 14:50:00 +05301300 hdmi_v14_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001301}
1302
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001303static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1304{
1305 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001306 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001307
Sean Paul0bfb1f82013-06-11 12:24:02 +05301308 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301309 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301310 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001311
1312 /* operation mode */
1313 buffer[0] = 0x1f;
1314 buffer[1] = 0x00;
1315
1316 if (hdata->hdmiphy_port)
1317 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1318
Rahul Sharma5a325072012-10-04 20:48:54 +05301319 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001320 reg = HDMI_V13_PHY_RSTOUT;
1321 else
1322 reg = HDMI_PHY_RSTOUT;
1323
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001324 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001325 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001326 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001327 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001328 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001329}
1330
Rahul Sharmaa5562252012-11-28 11:30:25 +05301331static void hdmiphy_poweron(struct hdmi_context *hdata)
1332{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301333 if (hdata->type == HDMI_TYPE14)
1334 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
1335 HDMI_PHY_POWER_OFF_EN);
1336}
1337
1338static void hdmiphy_poweroff(struct hdmi_context *hdata)
1339{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301340 if (hdata->type == HDMI_TYPE14)
1341 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
1342 HDMI_PHY_POWER_OFF_EN);
1343}
1344
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001345static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1346{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001347 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001348 u8 buffer[32];
1349 u8 operation[2];
1350 u8 read_buffer[32] = {0, };
1351 int ret;
1352 int i;
1353
1354 if (!hdata->hdmiphy_port) {
1355 DRM_ERROR("hdmiphy is not attached\n");
1356 return;
1357 }
1358
1359 /* pixel clock */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001360 i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);
1361 if (i < 0) {
1362 DRM_ERROR("failed to find hdmiphy conf\n");
1363 return;
1364 }
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001365
Sachin Kamat5f46c332013-04-26 11:29:00 +05301366 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001367 hdmiphy_data = hdmiphy_v13_configs[i].conf;
Sachin Kamat5f46c332013-04-26 11:29:00 +05301368 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001369 hdmiphy_data = hdmiphy_v14_configs[i].conf;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001370
1371 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001372 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1373 if (ret != 32) {
1374 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1375 return;
1376 }
1377
Sean Paul09760ea2013-01-14 17:03:20 -05001378 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001379
1380 /* operation mode */
1381 operation[0] = 0x1f;
1382 operation[1] = 0x80;
1383
1384 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1385 if (ret != 2) {
1386 DRM_ERROR("failed to enable hdmiphy\n");
1387 return;
1388 }
1389
1390 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1391 if (ret < 0) {
1392 DRM_ERROR("failed to read hdmiphy config\n");
1393 return;
1394 }
1395
1396 for (i = 0; i < ret; i++)
1397 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1398 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1399}
1400
1401static void hdmi_conf_apply(struct hdmi_context *hdata)
1402{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001403 hdmiphy_conf_reset(hdata);
1404 hdmiphy_conf_apply(hdata);
1405
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001406 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001407 hdmi_conf_reset(hdata);
1408 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001409 mutex_unlock(&hdata->hdmi_mutex);
1410
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001411 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001412
1413 /* setting core registers */
Rahul Sharma16844fb2013-06-10 14:50:00 +05301414 hdmi_mode_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001415 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001416
1417 hdmi_regs_dump(hdata, "start");
1418}
1419
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001420static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1421{
1422 int i;
1423 BUG_ON(num_bytes > 4);
1424 for (i = 0; i < num_bytes; i++)
1425 reg_pair[i] = (value >> (8 * i)) & 0xff;
1426}
1427
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001428static void hdmi_v13_mode_set(struct hdmi_context *hdata,
1429 struct drm_display_mode *m)
1430{
1431 struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core;
1432 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1433 unsigned int val;
1434
1435 hdata->mode_conf.cea_video_id =
1436 drm_match_cea_mode((struct drm_display_mode *)m);
1437 hdata->mode_conf.pixel_clock = m->clock * 1000;
1438
1439 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1440 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
1441
1442 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1443 hdmi_set_reg(core->vsync_pol, 1, val);
1444
1445 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1446 hdmi_set_reg(core->int_pro_mode, 1, val);
1447
1448 val = (m->hsync_start - m->hdisplay - 2);
1449 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1450 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1451 hdmi_set_reg(core->h_sync_gen, 3, val);
1452
1453 /*
1454 * Quirk requirement for exynos HDMI IP design,
1455 * 2 pixels less than the actual calculation for hsync_start
1456 * and end.
1457 */
1458
1459 /* Following values & calculations differ for different type of modes */
1460 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1461 /* Interlaced Mode */
1462 val = ((m->vsync_end - m->vdisplay) / 2);
1463 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1464 hdmi_set_reg(core->v_sync_gen1, 3, val);
1465
1466 val = m->vtotal / 2;
1467 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1468 hdmi_set_reg(core->v_blank, 3, val);
1469
1470 val = (m->vtotal +
1471 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1472 val |= m->vtotal << 11;
1473 hdmi_set_reg(core->v_blank_f, 3, val);
1474
1475 val = ((m->vtotal / 2) + 7);
1476 val |= ((m->vtotal / 2) + 2) << 12;
1477 hdmi_set_reg(core->v_sync_gen2, 3, val);
1478
1479 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1480 val |= ((m->htotal / 2) +
1481 (m->hsync_start - m->hdisplay)) << 12;
1482 hdmi_set_reg(core->v_sync_gen3, 3, val);
1483
1484 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1485 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1486
1487 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1488 } else {
1489 /* Progressive Mode */
1490
1491 val = m->vtotal;
1492 val |= (m->vtotal - m->vdisplay) << 11;
1493 hdmi_set_reg(core->v_blank, 3, val);
1494
1495 hdmi_set_reg(core->v_blank_f, 3, 0);
1496
1497 val = (m->vsync_end - m->vdisplay);
1498 val |= ((m->vsync_start - m->vdisplay) << 12);
1499 hdmi_set_reg(core->v_sync_gen1, 3, val);
1500
1501 hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value */
1502 hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value */
1503 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1504 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1505 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1506 }
1507
1508 /* Timing generator registers */
1509 hdmi_set_reg(tg->cmd, 1, 0x0);
1510 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1511 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1512 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1513 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1514 hdmi_set_reg(tg->vsync, 2, 0x1);
1515 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1516 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1517 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1518 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1519 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1520 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1521 hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */
1522}
1523
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001524static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1525 struct drm_display_mode *m)
1526{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001527 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1528 struct hdmi_v14_core_regs *core =
1529 &hdata->mode_conf.conf.v14_conf.core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001530
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001531 hdata->mode_conf.cea_video_id =
1532 drm_match_cea_mode((struct drm_display_mode *)m);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001533 hdata->mode_conf.pixel_clock = m->clock * 1000;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001534
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001535 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1536 hdmi_set_reg(core->v_line, 2, m->vtotal);
1537 hdmi_set_reg(core->h_line, 2, m->htotal);
1538 hdmi_set_reg(core->hsync_pol, 1,
1539 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1540 hdmi_set_reg(core->vsync_pol, 1,
1541 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1542 hdmi_set_reg(core->int_pro_mode, 1,
1543 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1544
1545 /*
1546 * Quirk requirement for exynos 5 HDMI IP design,
1547 * 2 pixels less than the actual calculation for hsync_start
1548 * and end.
1549 */
1550
1551 /* Following values & calculations differ for different type of modes */
1552 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1553 /* Interlaced Mode */
1554 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1555 (m->vsync_end - m->vdisplay) / 2);
1556 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1557 (m->vsync_start - m->vdisplay) / 2);
1558 hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
1559 hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
1560 hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal +
1561 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2);
1562 hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
1563 hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
1564 hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
1565 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
1566 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1567 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
1568 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1569 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1570 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1571 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1572 hdmi_set_reg(tg->vact_st3, 2, 0x0);
1573 hdmi_set_reg(tg->vact_st4, 2, 0x0);
1574 } else {
1575 /* Progressive Mode */
1576 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1577 m->vsync_end - m->vdisplay);
1578 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1579 m->vsync_start - m->vdisplay);
1580 hdmi_set_reg(core->v2_blank, 2, m->vtotal);
1581 hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
1582 hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
1583 hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
1584 hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
1585 hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
1586 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
1587 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
1588 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1589 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1590 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1591 hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
1592 hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
1593 }
1594
1595 /* Following values & calculations are same irrespective of mode type */
1596 hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
1597 hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
1598 hdmi_set_reg(core->vact_space_1, 2, 0xffff);
1599 hdmi_set_reg(core->vact_space_2, 2, 0xffff);
1600 hdmi_set_reg(core->vact_space_3, 2, 0xffff);
1601 hdmi_set_reg(core->vact_space_4, 2, 0xffff);
1602 hdmi_set_reg(core->vact_space_5, 2, 0xffff);
1603 hdmi_set_reg(core->vact_space_6, 2, 0xffff);
1604 hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
1605 hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
1606 hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
1607 hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
1608 hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
1609 hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
1610 hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
1611 hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
1612 hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
1613 hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
1614 hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
1615 hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
1616
1617 /* Timing generator registers */
1618 hdmi_set_reg(tg->cmd, 1, 0x0);
1619 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1620 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1621 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1622 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1623 hdmi_set_reg(tg->vsync, 2, 0x1);
1624 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1625 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1626 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1627 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1628 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1629 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1630 hdmi_set_reg(tg->tg_3d, 1, 0x0);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001631}
1632
Rahul Sharma16844fb2013-06-10 14:50:00 +05301633static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001634{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001635 struct hdmi_context *hdata = ctx;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001636 struct drm_display_mode *m = mode;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001637
YoungJun Chocbc4c332013-06-12 10:44:40 +09001638 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1639 m->hdisplay, m->vdisplay,
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001640 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1641 "INTERLACED" : "PROGERESSIVE");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001642
Sachin Kamat5f46c332013-04-26 11:29:00 +05301643 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001644 hdmi_v13_mode_set(hdata, mode);
Sachin Kamat5f46c332013-04-26 11:29:00 +05301645 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001646 hdmi_v14_mode_set(hdata, mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001647}
1648
Inki Dae1de425b2012-03-16 18:47:04 +09001649static void hdmi_get_max_resol(void *ctx, unsigned int *width,
1650 unsigned int *height)
1651{
Inki Dae1de425b2012-03-16 18:47:04 +09001652 *width = MAX_WIDTH;
1653 *height = MAX_HEIGHT;
1654}
1655
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001656static void hdmi_commit(void *ctx)
1657{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001658 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001659
Shirish Sdda90122013-01-23 22:03:18 -05001660 mutex_lock(&hdata->hdmi_mutex);
1661 if (!hdata->powered) {
1662 mutex_unlock(&hdata->hdmi_mutex);
1663 return;
1664 }
1665 mutex_unlock(&hdata->hdmi_mutex);
1666
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001667 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001668}
1669
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001670static void hdmi_poweron(struct hdmi_context *hdata)
1671{
1672 struct hdmi_resources *res = &hdata->res;
1673
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001674 mutex_lock(&hdata->hdmi_mutex);
1675 if (hdata->powered) {
1676 mutex_unlock(&hdata->hdmi_mutex);
1677 return;
1678 }
1679
1680 hdata->powered = true;
1681
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001682 mutex_unlock(&hdata->hdmi_mutex);
1683
Seung-Woo Kimad079452013-06-05 14:34:38 +09001684 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1685 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1686
Sean Paul0bfb1f82013-06-11 12:24:02 +05301687 clk_prepare_enable(res->hdmiphy);
1688 clk_prepare_enable(res->hdmi);
1689 clk_prepare_enable(res->sclk_hdmi);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301690
1691 hdmiphy_poweron(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001692}
1693
1694static void hdmi_poweroff(struct hdmi_context *hdata)
1695{
1696 struct hdmi_resources *res = &hdata->res;
1697
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001698 mutex_lock(&hdata->hdmi_mutex);
1699 if (!hdata->powered)
1700 goto out;
1701 mutex_unlock(&hdata->hdmi_mutex);
1702
1703 /*
1704 * The TV power domain needs any condition of hdmiphy to turn off and
1705 * its reset state seems to meet the condition.
1706 */
1707 hdmiphy_conf_reset(hdata);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301708 hdmiphy_poweroff(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001709
Sean Paul0bfb1f82013-06-11 12:24:02 +05301710 clk_disable_unprepare(res->sclk_hdmi);
1711 clk_disable_unprepare(res->hdmi);
1712 clk_disable_unprepare(res->hdmiphy);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001713 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1714
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001715 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001716
1717 hdata->powered = false;
1718
1719out:
1720 mutex_unlock(&hdata->hdmi_mutex);
1721}
1722
1723static void hdmi_dpms(void *ctx, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001724{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001725 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001726
YoungJun Chocbc4c332013-06-12 10:44:40 +09001727 DRM_DEBUG_KMS("mode %d\n", mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001728
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001729 switch (mode) {
1730 case DRM_MODE_DPMS_ON:
Rahul Sharma64327cb2012-11-28 11:30:23 +05301731 if (pm_runtime_suspended(hdata->dev))
1732 pm_runtime_get_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001733 break;
1734 case DRM_MODE_DPMS_STANDBY:
1735 case DRM_MODE_DPMS_SUSPEND:
1736 case DRM_MODE_DPMS_OFF:
Rahul Sharma64327cb2012-11-28 11:30:23 +05301737 if (!pm_runtime_suspended(hdata->dev))
1738 pm_runtime_put_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001739 break;
1740 default:
1741 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1742 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001743 }
1744}
1745
Joonyoung Shim578b6062012-04-05 20:49:26 +09001746static struct exynos_hdmi_ops hdmi_ops = {
1747 /* display */
1748 .is_connected = hdmi_is_connected,
1749 .get_edid = hdmi_get_edid,
Rahul Sharma16844fb2013-06-10 14:50:00 +05301750 .check_mode = hdmi_check_mode,
Joonyoung Shim578b6062012-04-05 20:49:26 +09001751
1752 /* manager */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001753 .mode_set = hdmi_mode_set,
Inki Dae1de425b2012-03-16 18:47:04 +09001754 .get_max_resol = hdmi_get_max_resol,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001755 .commit = hdmi_commit,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001756 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001757};
1758
Sean Paul77006a72013-01-16 10:17:20 -05001759static irqreturn_t hdmi_irq_thread(int irq, void *arg)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001760{
1761 struct exynos_drm_hdmi_context *ctx = arg;
1762 struct hdmi_context *hdata = ctx->ctx;
1763
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001764 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301765 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001766 mutex_unlock(&hdata->hdmi_mutex);
1767
1768 if (ctx->drm_dev)
1769 drm_helper_hpd_irq_event(ctx->drm_dev);
1770
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001771 return IRQ_HANDLED;
1772}
1773
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001774static int hdmi_resources_init(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001775{
1776 struct device *dev = hdata->dev;
1777 struct hdmi_resources *res = &hdata->res;
1778 static char *supply[] = {
1779 "hdmi-en",
1780 "vdd",
1781 "vdd_osc",
1782 "vdd_pll",
1783 };
1784 int i, ret;
1785
1786 DRM_DEBUG_KMS("HDMI resource init\n");
1787
Sachin Kamatadc837a2012-08-31 15:50:47 +05301788 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001789
1790 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301791 res->hdmi = devm_clk_get(dev, "hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301792 if (IS_ERR(res->hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001793 DRM_ERROR("failed to get clock 'hdmi'\n");
1794 goto fail;
1795 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301796 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301797 if (IS_ERR(res->sclk_hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001798 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
1799 goto fail;
1800 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301801 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301802 if (IS_ERR(res->sclk_pixel)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001803 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1804 goto fail;
1805 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301806 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301807 if (IS_ERR(res->sclk_hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001808 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
1809 goto fail;
1810 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301811 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301812 if (IS_ERR(res->hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001813 DRM_ERROR("failed to get clock 'hdmiphy'\n");
1814 goto fail;
1815 }
Rahul Sharma59956d32013-06-11 12:24:03 +05301816 res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
1817 if (IS_ERR(res->mout_hdmi)) {
1818 DRM_ERROR("failed to get clock 'mout_hdmi'\n");
1819 goto fail;
1820 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001821
Rahul Sharma59956d32013-06-11 12:24:03 +05301822 clk_set_parent(res->mout_hdmi, res->sclk_pixel);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001823
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301824 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05301825 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001826 if (!res->regul_bulk) {
1827 DRM_ERROR("failed to get memory for regulators\n");
1828 goto fail;
1829 }
1830 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
1831 res->regul_bulk[i].supply = supply[i];
1832 res->regul_bulk[i].consumer = NULL;
1833 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301834 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001835 if (ret) {
1836 DRM_ERROR("failed to get regulators\n");
1837 goto fail;
1838 }
1839 res->regul_count = ARRAY_SIZE(supply);
1840
1841 return 0;
1842fail:
1843 DRM_ERROR("HDMI resource init - failed\n");
1844 return -ENODEV;
1845}
1846
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001847static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
1848
1849void hdmi_attach_ddc_client(struct i2c_client *ddc)
1850{
1851 if (ddc)
1852 hdmi_ddc = ddc;
1853}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001854
1855void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
1856{
1857 if (hdmiphy)
1858 hdmi_hdmiphy = hdmiphy;
1859}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001860
Rahul Sharma22c4f422012-10-04 20:48:55 +05301861#ifdef CONFIG_OF
1862static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
1863 (struct device *dev)
1864{
1865 struct device_node *np = dev->of_node;
1866 struct s5p_hdmi_platform_data *pd;
1867 enum of_gpio_flags flags;
1868 u32 value;
1869
1870 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
1871 if (!pd) {
1872 DRM_ERROR("memory allocation for pdata failed\n");
1873 goto err_data;
1874 }
1875
1876 if (!of_find_property(np, "hpd-gpio", &value)) {
1877 DRM_ERROR("no hpd gpio property found\n");
1878 goto err_data;
1879 }
1880
1881 pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
1882
1883 return pd;
1884
1885err_data:
1886 return NULL;
1887}
1888#else
1889static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
1890 (struct device *dev)
1891{
1892 return NULL;
1893}
1894#endif
1895
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05301896static struct platform_device_id hdmi_driver_types[] = {
1897 {
1898 .name = "s5pv210-hdmi",
1899 .driver_data = HDMI_TYPE13,
1900 }, {
1901 .name = "exynos4-hdmi",
1902 .driver_data = HDMI_TYPE13,
1903 }, {
1904 .name = "exynos4-hdmi14",
Rahul Sharma22c4f422012-10-04 20:48:55 +05301905 .driver_data = HDMI_TYPE14,
1906 }, {
1907 .name = "exynos5-hdmi",
1908 .driver_data = HDMI_TYPE14,
1909 }, {
1910 /* end node */
1911 }
1912};
1913
Sachin Kamat65da0352012-12-12 14:24:07 +05301914#ifdef CONFIG_OF
Rahul Sharma22c4f422012-10-04 20:48:55 +05301915static struct of_device_id hdmi_match_types[] = {
1916 {
1917 .compatible = "samsung,exynos5-hdmi",
1918 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05301919 }, {
1920 /* end node */
1921 }
1922};
Sachin Kamat65da0352012-12-12 14:24:07 +05301923#endif
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05301924
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001925static int hdmi_probe(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001926{
1927 struct device *dev = &pdev->dev;
1928 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
1929 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301930 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001931 struct resource *res;
1932 int ret;
1933
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001934 if (dev->of_node) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05301935 pdata = drm_hdmi_dt_parse_pdata(dev);
1936 if (IS_ERR(pdata)) {
1937 DRM_ERROR("failed to parse dt\n");
1938 return PTR_ERR(pdata);
1939 }
1940 } else {
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001941 pdata = dev->platform_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05301942 }
1943
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001944 if (!pdata) {
1945 DRM_ERROR("no platform data specified\n");
1946 return -EINVAL;
1947 }
1948
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001949 drm_hdmi_ctx = devm_kzalloc(dev, sizeof(*drm_hdmi_ctx),
Sachin Kamata6e65072012-06-19 11:47:40 +05301950 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001951 if (!drm_hdmi_ctx) {
1952 DRM_ERROR("failed to allocate common hdmi context.\n");
1953 return -ENOMEM;
1954 }
1955
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001956 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context),
Sachin Kamata6e65072012-06-19 11:47:40 +05301957 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001958 if (!hdata) {
1959 DRM_ERROR("out of memory\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001960 return -ENOMEM;
1961 }
1962
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001963 mutex_init(&hdata->hdmi_mutex);
1964
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001965 drm_hdmi_ctx->ctx = (void *)hdata;
1966 hdata->parent_ctx = (void *)drm_hdmi_ctx;
1967
1968 platform_set_drvdata(pdev, drm_hdmi_ctx);
1969
Rahul Sharma22c4f422012-10-04 20:48:55 +05301970 if (dev->of_node) {
1971 const struct of_device_id *match;
1972 match = of_match_node(of_match_ptr(hdmi_match_types),
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001973 dev->of_node);
Sachin Kamat1a4513b2012-12-12 14:24:08 +05301974 if (match == NULL)
1975 return -ENODEV;
Rahul Sharma22c4f422012-10-04 20:48:55 +05301976 hdata->type = (enum hdmi_type)match->data;
1977 } else {
1978 hdata->type = (enum hdmi_type)platform_get_device_id
Rahul Sharma5a325072012-10-04 20:48:54 +05301979 (pdev)->driver_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05301980 }
1981
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301982 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001983 hdata->dev = dev;
1984
1985 ret = hdmi_resources_init(hdata);
Rahul Sharma22c4f422012-10-04 20:48:55 +05301986
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001987 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05301988 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301989 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001990 }
1991
1992 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001993 hdata->regs = devm_ioremap_resource(dev, res);
Thierry Redingd4ed6022013-01-21 11:09:02 +01001994 if (IS_ERR(hdata->regs))
1995 return PTR_ERR(hdata->regs);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001996
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09001997 ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301998 if (ret) {
1999 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302000 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302001 }
2002
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002003 /* DDC i2c driver */
2004 if (i2c_add_driver(&ddc_driver)) {
2005 DRM_ERROR("failed to register ddc i2c driver\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302006 return -ENOENT;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002007 }
2008
2009 hdata->ddc_port = hdmi_ddc;
2010
2011 /* hdmiphy i2c driver */
2012 if (i2c_add_driver(&hdmiphy_driver)) {
2013 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2014 ret = -ENOENT;
2015 goto err_ddc;
2016 }
2017
2018 hdata->hdmiphy_port = hdmi_hdmiphy;
2019
Sean Paul77006a72013-01-16 10:17:20 -05002020 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
2021 if (hdata->irq < 0) {
2022 DRM_ERROR("failed to get GPIO irq\n");
2023 ret = hdata->irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002024 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002025 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002026
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302027 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2028
Seung-Woo Kimdcb9a7c2013-05-22 21:14:17 +09002029 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
Sean Paul77006a72013-01-16 10:17:20 -05002030 hdmi_irq_thread, IRQF_TRIGGER_RISING |
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002031 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sean Paul77006a72013-01-16 10:17:20 -05002032 "hdmi", drm_hdmi_ctx);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002033 if (ret) {
Sean Paul77006a72013-01-16 10:17:20 -05002034 DRM_ERROR("failed to register hdmi interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002035 goto err_hdmiphy;
2036 }
2037
Rahul Sharma768c3052012-10-04 20:48:56 +05302038 /* Attach HDMI Driver to common hdmi. */
2039 exynos_hdmi_drv_attach(drm_hdmi_ctx);
2040
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002041 /* register specific callbacks to common hdmi. */
Joonyoung Shim578b6062012-04-05 20:49:26 +09002042 exynos_hdmi_ops_register(&hdmi_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002043
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002044 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002045
2046 return 0;
2047
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002048err_hdmiphy:
2049 i2c_del_driver(&hdmiphy_driver);
2050err_ddc:
2051 i2c_del_driver(&ddc_driver);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002052 return ret;
2053}
2054
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002055static int hdmi_remove(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002056{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002057 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002058
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002059 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002060
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002061 /* hdmiphy i2c driver */
2062 i2c_del_driver(&hdmiphy_driver);
2063 /* DDC i2c driver */
2064 i2c_del_driver(&ddc_driver);
2065
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002066 return 0;
2067}
2068
Joonyoung Shimab27af82012-04-23 19:35:51 +09002069#ifdef CONFIG_PM_SLEEP
2070static int hdmi_suspend(struct device *dev)
2071{
2072 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2073 struct hdmi_context *hdata = ctx->ctx;
2074
Sean Paul77006a72013-01-16 10:17:20 -05002075 disable_irq(hdata->irq);
Joonyoung Shimab27af82012-04-23 19:35:51 +09002076
2077 hdata->hpd = false;
2078 if (ctx->drm_dev)
2079 drm_helper_hpd_irq_event(ctx->drm_dev);
2080
Rahul Sharma64327cb2012-11-28 11:30:23 +05302081 if (pm_runtime_suspended(dev)) {
YoungJun Chocbc4c332013-06-12 10:44:40 +09002082 DRM_DEBUG_KMS("Already suspended\n");
Rahul Sharma64327cb2012-11-28 11:30:23 +05302083 return 0;
2084 }
2085
Joonyoung Shimab27af82012-04-23 19:35:51 +09002086 hdmi_poweroff(hdata);
2087
2088 return 0;
2089}
2090
2091static int hdmi_resume(struct device *dev)
2092{
2093 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2094 struct hdmi_context *hdata = ctx->ctx;
2095
Rahul Sharma64327cb2012-11-28 11:30:23 +05302096 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2097
Sean Paul77006a72013-01-16 10:17:20 -05002098 enable_irq(hdata->irq);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302099
2100 if (!pm_runtime_suspended(dev)) {
YoungJun Chocbc4c332013-06-12 10:44:40 +09002101 DRM_DEBUG_KMS("Already resumed\n");
Rahul Sharma64327cb2012-11-28 11:30:23 +05302102 return 0;
2103 }
2104
2105 hdmi_poweron(hdata);
2106
Joonyoung Shimab27af82012-04-23 19:35:51 +09002107 return 0;
2108}
2109#endif
2110
Rahul Sharma64327cb2012-11-28 11:30:23 +05302111#ifdef CONFIG_PM_RUNTIME
2112static int hdmi_runtime_suspend(struct device *dev)
2113{
2114 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2115 struct hdmi_context *hdata = ctx->ctx;
Rahul Sharma64327cb2012-11-28 11:30:23 +05302116
2117 hdmi_poweroff(hdata);
2118
2119 return 0;
2120}
2121
2122static int hdmi_runtime_resume(struct device *dev)
2123{
2124 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2125 struct hdmi_context *hdata = ctx->ctx;
Rahul Sharma64327cb2012-11-28 11:30:23 +05302126
2127 hdmi_poweron(hdata);
2128
2129 return 0;
2130}
2131#endif
2132
2133static const struct dev_pm_ops hdmi_pm_ops = {
2134 SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
2135 SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
2136};
Joonyoung Shimab27af82012-04-23 19:35:51 +09002137
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002138struct platform_driver hdmi_driver = {
2139 .probe = hdmi_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002140 .remove = hdmi_remove,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302141 .id_table = hdmi_driver_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002142 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302143 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002144 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002145 .pm = &hdmi_pm_ops,
Sachin Kamat65da0352012-12-12 14:24:07 +05302146 .of_match_table = of_match_ptr(hdmi_match_types),
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002147 },
2148};