]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/gpu/drm/exynos/exynos_hdmi.c
drm: exynos: Rely on the default ->best_encoder() behavior
[mirror_ubuntu-zesty-kernel.git] / drivers / gpu / drm / exynos / exynos_hdmi.c
CommitLineData
d8408326
SWK
1/*
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 *
5eefadb5
AH
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
d8408326
SWK
13 * option) any later version.
14 *
15 */
16
760285e7
DH
17#include <drm/drmP.h>
18#include <drm/drm_edid.h>
19#include <drm/drm_crtc_helper.h>
4ea9526b 20#include <drm/drm_atomic_helper.h>
d8408326
SWK
21
22#include "regs-hdmi.h"
23
24#include <linux/kernel.h>
d8408326
SWK
25#include <linux/wait.h>
26#include <linux/i2c.h>
d8408326
SWK
27#include <linux/platform_device.h>
28#include <linux/interrupt.h>
29#include <linux/irq.h>
30#include <linux/delay.h>
31#include <linux/pm_runtime.h>
32#include <linux/clk.h>
2228b7cd 33#include <linux/gpio/consumer.h>
d8408326 34#include <linux/regulator/consumer.h>
22c4f428 35#include <linux/io.h>
d5e9ca4c 36#include <linux/of_address.h>
cd240cde 37#include <linux/of_device.h>
d34d59bd 38#include <linux/hdmi.h>
f37cd5e8 39#include <linux/component.h>
049d34e9
RS
40#include <linux/mfd/syscon.h>
41#include <linux/regmap.h>
d8408326
SWK
42
43#include <drm/exynos_drm.h>
44
45#include "exynos_drm_drv.h"
f37cd5e8 46#include "exynos_drm_crtc.h"
d8408326 47
724fd140
SP
48#define HOTPLUG_DEBOUNCE_MS 1100
49
a144c2e9
RS
50/* AVI header and aspect ratio */
51#define HDMI_AVI_VERSION 0x02
5eefadb5 52#define HDMI_AVI_LENGTH 0x0d
a144c2e9
RS
53
54/* AUI header info */
5eefadb5
AH
55#define HDMI_AUI_VERSION 0x01
56#define HDMI_AUI_LENGTH 0x0a
57
58/* AVI active format aspect ratio */
59#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x08
60#define AVI_4_3_CENTER_RATIO 0x09
61#define AVI_16_9_CENTER_RATIO 0x0a
a144c2e9 62
5a325071
RS
63enum hdmi_type {
64 HDMI_TYPE13,
65 HDMI_TYPE14,
633d00b3
AH
66 HDMI_TYPE_COUNT
67};
68
69#define HDMI_MAPPED_BASE 0xffff0000
70
71enum hdmi_mapped_regs {
72 HDMI_PHY_STATUS = HDMI_MAPPED_BASE,
73 HDMI_PHY_RSTOUT,
74 HDMI_ACR_CON,
d24bb3e5
AH
75 HDMI_ACR_MCTS0,
76 HDMI_ACR_CTS0,
77 HDMI_ACR_N0
633d00b3
AH
78};
79
80static const u32 hdmi_reg_map[][HDMI_TYPE_COUNT] = {
81 { HDMI_V13_PHY_STATUS, HDMI_PHY_STATUS_0 },
82 { HDMI_V13_PHY_RSTOUT, HDMI_V14_PHY_RSTOUT },
83 { HDMI_V13_ACR_CON, HDMI_V14_ACR_CON },
d24bb3e5
AH
84 { HDMI_V13_ACR_MCTS0, HDMI_V14_ACR_MCTS0 },
85 { HDMI_V13_ACR_CTS0, HDMI_V14_ACR_CTS0 },
86 { HDMI_V13_ACR_N0, HDMI_V14_ACR_N0 },
5a325071
RS
87};
88
1ab739db
AH
89static const char * const supply[] = {
90 "vdd",
91 "vdd_osc",
92 "vdd_pll",
93};
94
65e98030
AH
95struct hdmiphy_config {
96 int pixel_clock;
97 u8 conf[32];
98};
99
100struct hdmiphy_configs {
101 int count;
102 const struct hdmiphy_config *data;
103};
104
9be7e989
AH
105struct string_array_spec {
106 int count;
107 const char * const *data;
108};
109
110#define INIT_ARRAY_SPEC(a) { .count = ARRAY_SIZE(a), .data = a }
111
bfe4e84c
ID
112struct hdmi_driver_data {
113 unsigned int type;
114 unsigned int is_apb_phy:1;
68cd004e 115 unsigned int has_sysreg:1;
65e98030 116 struct hdmiphy_configs phy_confs;
9be7e989
AH
117 struct string_array_spec clk_gates;
118 /*
119 * Array of triplets (p_off, p_on, clock), where p_off and p_on are
120 * required parents of clock when HDMI-PHY is respectively off or on.
121 */
122 struct string_array_spec clk_muxes;
bfe4e84c
ID
123};
124
590f418a 125struct hdmi_context {
2b8376c8 126 struct drm_encoder encoder;
590f418a
JS
127 struct device *dev;
128 struct drm_device *drm_dev;
d9716ee3 129 struct drm_connector connector;
cf8fc4f1 130 bool powered;
872d20d6 131 bool dvi_mode;
724fd140 132 struct delayed_work hotplug_work;
bfa48423 133 struct drm_display_mode current_mode;
c93aaebf 134 u8 cea_video_id;
cd240cde 135 const struct hdmi_driver_data *drv_data;
7ecd34e8 136
af1f7c24 137 void __iomem *regs;
d5e9ca4c 138 void __iomem *regs_hdmiphy;
af1f7c24
AH
139 struct i2c_client *hdmiphy_port;
140 struct i2c_adapter *ddc_adpt;
f28464c3 141 struct gpio_desc *hpd_gpio;
af1f7c24 142 int irq;
049d34e9 143 struct regmap *pmureg;
68cd004e 144 struct regmap *sysreg;
9be7e989
AH
145 struct clk **clk_gates;
146 struct clk **clk_muxes;
af1f7c24
AH
147 struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)];
148 struct regulator *reg_hdmi_en;
59b62d3c 149 struct exynos_drm_clk phy_clk;
590f418a
JS
150};
151
2b8376c8 152static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
0d8424f8 153{
cf67cc9a 154 return container_of(e, struct hdmi_context, encoder);
0d8424f8
AH
155}
156
185f22d2
AH
157static inline struct hdmi_context *connector_to_hdmi(struct drm_connector *c)
158{
159 return container_of(c, struct hdmi_context, connector);
160}
161
6b986edf
RS
162static const struct hdmiphy_config hdmiphy_v13_configs[] = {
163 {
164 .pixel_clock = 27000000,
165 .conf = {
166 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
167 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
168 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
74a74ff4 169 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
6b986edf 170 },
d8408326 171 },
6b986edf
RS
172 {
173 .pixel_clock = 27027000,
174 .conf = {
175 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
176 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
177 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
74a74ff4 178 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
6b986edf 179 },
d8408326 180 },
6b986edf
RS
181 {
182 .pixel_clock = 74176000,
183 .conf = {
184 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
185 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
186 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
74a74ff4 187 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x80,
6b986edf 188 },
d8408326 189 },
6b986edf
RS
190 {
191 .pixel_clock = 74250000,
192 .conf = {
193 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
194 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
195 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
74a74ff4 196 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x80,
6b986edf 197 },
d8408326 198 },
6b986edf
RS
199 {
200 .pixel_clock = 148500000,
201 .conf = {
202 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
203 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
204 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
74a74ff4 205 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x80,
6b986edf 206 },
d8408326
SWK
207 },
208};
209
2f7e2ed0
SP
210static const struct hdmiphy_config hdmiphy_v14_configs[] = {
211 {
212 .pixel_clock = 25200000,
213 .conf = {
214 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
215 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
216 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
217 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
218 },
3ecd70b1 219 },
2f7e2ed0
SP
220 {
221 .pixel_clock = 27000000,
222 .conf = {
223 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
224 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
225 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
226 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
227 },
3ecd70b1 228 },
2f7e2ed0
SP
229 {
230 .pixel_clock = 27027000,
231 .conf = {
232 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
233 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
234 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
74a74ff4 235 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
2f7e2ed0 236 },
3ecd70b1 237 },
2f7e2ed0
SP
238 {
239 .pixel_clock = 36000000,
240 .conf = {
241 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
242 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
243 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
244 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
245 },
3ecd70b1 246 },
2f7e2ed0
SP
247 {
248 .pixel_clock = 40000000,
249 .conf = {
250 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
251 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
252 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
253 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
254 },
3ecd70b1 255 },
2f7e2ed0
SP
256 {
257 .pixel_clock = 65000000,
258 .conf = {
259 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
260 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
261 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
262 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
263 },
3ecd70b1 264 },
e1d883c0
S
265 {
266 .pixel_clock = 71000000,
267 .conf = {
96d2653a
S
268 0x01, 0xd1, 0x3b, 0x35, 0x40, 0x0c, 0x04, 0x08,
269 0x85, 0xa0, 0x63, 0xd9, 0x45, 0xa0, 0xac, 0x80,
270 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
e1d883c0
S
271 0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
272 },
273 },
274 {
275 .pixel_clock = 73250000,
276 .conf = {
96d2653a
S
277 0x01, 0xd1, 0x3d, 0x35, 0x40, 0x18, 0x02, 0x08,
278 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
279 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
e1d883c0
S
280 0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
281 },
282 },
2f7e2ed0
SP
283 {
284 .pixel_clock = 74176000,
285 .conf = {
286 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
287 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
288 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
289 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
290 },
3ecd70b1 291 },
2f7e2ed0
SP
292 {
293 .pixel_clock = 74250000,
294 .conf = {
295 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
296 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
297 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
74a74ff4 298 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
2f7e2ed0 299 },
e540adf3 300 },
2f7e2ed0
SP
301 {
302 .pixel_clock = 83500000,
303 .conf = {
304 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
305 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
306 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
307 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
308 },
e540adf3 309 },
2f7e2ed0
SP
310 {
311 .pixel_clock = 106500000,
312 .conf = {
313 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
314 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
315 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
316 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
317 },
3ecd70b1 318 },
2f7e2ed0
SP
319 {
320 .pixel_clock = 108000000,
321 .conf = {
322 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
323 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
324 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
325 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
326 },
3ecd70b1 327 },
e1d883c0
S
328 {
329 .pixel_clock = 115500000,
330 .conf = {
96d2653a
S
331 0x01, 0xd1, 0x30, 0x12, 0x40, 0x40, 0x10, 0x08,
332 0x80, 0x80, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
333 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
e1d883c0
S
334 0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
335 },
336 },
337 {
338 .pixel_clock = 119000000,
339 .conf = {
96d2653a
S
340 0x01, 0xd1, 0x32, 0x1a, 0x40, 0x30, 0xd8, 0x08,
341 0x04, 0xa0, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
342 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
e1d883c0
S
343 0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
344 },
345 },
2f7e2ed0
SP
346 {
347 .pixel_clock = 146250000,
348 .conf = {
349 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
350 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
351 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
352 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
353 },
3ecd70b1 354 },
2f7e2ed0
SP
355 {
356 .pixel_clock = 148500000,
357 .conf = {
358 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
359 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
360 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
74a74ff4 361 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
2f7e2ed0 362 },
3ecd70b1
JS
363 },
364};
365
a18a2dda
RS
366static const struct hdmiphy_config hdmiphy_5420_configs[] = {
367 {
368 .pixel_clock = 25200000,
369 .conf = {
370 0x01, 0x52, 0x3F, 0x55, 0x40, 0x01, 0x00, 0xC8,
371 0x82, 0xC8, 0xBD, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
372 0x06, 0x80, 0x01, 0x84, 0x05, 0x02, 0x24, 0x66,
373 0x54, 0xF4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
374 },
375 },
376 {
377 .pixel_clock = 27000000,
378 .conf = {
379 0x01, 0xD1, 0x22, 0x51, 0x40, 0x08, 0xFC, 0xE0,
380 0x98, 0xE8, 0xCB, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
381 0x06, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
382 0x54, 0xE4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
383 },
384 },
385 {
386 .pixel_clock = 27027000,
387 .conf = {
388 0x01, 0xD1, 0x2D, 0x72, 0x40, 0x64, 0x12, 0xC8,
389 0x43, 0xE8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
390 0x26, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
391 0x54, 0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
392 },
393 },
394 {
395 .pixel_clock = 36000000,
396 .conf = {
397 0x01, 0x51, 0x2D, 0x55, 0x40, 0x40, 0x00, 0xC8,
398 0x02, 0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
399 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
400 0x54, 0xAB, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
401 },
402 },
403 {
404 .pixel_clock = 40000000,
405 .conf = {
406 0x01, 0xD1, 0x21, 0x31, 0x40, 0x3C, 0x28, 0xC8,
407 0x87, 0xE8, 0xC8, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
408 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
409 0x54, 0x9A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
410 },
411 },
412 {
413 .pixel_clock = 65000000,
414 .conf = {
415 0x01, 0xD1, 0x36, 0x34, 0x40, 0x0C, 0x04, 0xC8,
416 0x82, 0xE8, 0x45, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
417 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
418 0x54, 0xBD, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
419 },
420 },
421 {
422 .pixel_clock = 71000000,
423 .conf = {
424 0x01, 0xD1, 0x3B, 0x35, 0x40, 0x0C, 0x04, 0xC8,
425 0x85, 0xE8, 0x63, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
426 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
427 0x54, 0x57, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
428 },
429 },
430 {
431 .pixel_clock = 73250000,
432 .conf = {
433 0x01, 0xD1, 0x1F, 0x10, 0x40, 0x78, 0x8D, 0xC8,
434 0x81, 0xE8, 0xB7, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
435 0x56, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
436 0x54, 0xA8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
437 },
438 },
439 {
440 .pixel_clock = 74176000,
441 .conf = {
442 0x01, 0xD1, 0x1F, 0x10, 0x40, 0x5B, 0xEF, 0xC8,
443 0x81, 0xE8, 0xB9, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
444 0x56, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
445 0x54, 0xA6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
446 },
447 },
448 {
449 .pixel_clock = 74250000,
450 .conf = {
451 0x01, 0xD1, 0x1F, 0x10, 0x40, 0x40, 0xF8, 0x08,
452 0x81, 0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
453 0x26, 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x66,
454 0x54, 0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
455 },
456 },
457 {
458 .pixel_clock = 83500000,
459 .conf = {
460 0x01, 0xD1, 0x23, 0x11, 0x40, 0x0C, 0xFB, 0xC8,
461 0x85, 0xE8, 0xD1, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
462 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
463 0x54, 0x4A, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
464 },
465 },
466 {
467 .pixel_clock = 88750000,
468 .conf = {
469 0x01, 0xD1, 0x25, 0x11, 0x40, 0x18, 0xFF, 0xC8,
470 0x83, 0xE8, 0xDE, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
471 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
472 0x54, 0x45, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
473 },
474 },
475 {
476 .pixel_clock = 106500000,
477 .conf = {
478 0x01, 0xD1, 0x2C, 0x12, 0x40, 0x0C, 0x09, 0xC8,
479 0x84, 0xE8, 0x0A, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
480 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
481 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
482 },
483 },
484 {
485 .pixel_clock = 108000000,
486 .conf = {
487 0x01, 0x51, 0x2D, 0x15, 0x40, 0x01, 0x00, 0xC8,
488 0x82, 0xC8, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
489 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
490 0x54, 0xC7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
491 },
492 },
493 {
494 .pixel_clock = 115500000,
495 .conf = {
496 0x01, 0xD1, 0x30, 0x14, 0x40, 0x0C, 0x03, 0xC8,
497 0x88, 0xE8, 0x21, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
498 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
499 0x54, 0x6A, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
500 },
501 },
502 {
503 .pixel_clock = 146250000,
504 .conf = {
505 0x01, 0xD1, 0x3D, 0x15, 0x40, 0x18, 0xFD, 0xC8,
506 0x83, 0xE8, 0x6E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
507 0x08, 0x80, 0x09, 0x84, 0x05, 0x02, 0x24, 0x66,
508 0x54, 0x54, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
509 },
510 },
511 {
512 .pixel_clock = 148500000,
513 .conf = {
514 0x01, 0xD1, 0x1F, 0x00, 0x40, 0x40, 0xF8, 0x08,
515 0x81, 0xE8, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
516 0x26, 0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x66,
517 0x54, 0x4B, 0x25, 0x03, 0x00, 0x80, 0x01, 0x80,
518 },
519 },
520};
521
68cd004e
AH
522static const struct hdmiphy_config hdmiphy_5433_configs[] = {
523 {
524 .pixel_clock = 27000000,
525 .conf = {
526 0x01, 0x51, 0x22, 0x51, 0x08, 0xfc, 0x88, 0x46,
527 0x72, 0x50, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5,
528 0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
529 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
530 },
531 },
532 {
533 .pixel_clock = 27027000,
534 .conf = {
535 0x01, 0x51, 0x2d, 0x72, 0x64, 0x09, 0x88, 0xc3,
536 0x71, 0x50, 0x24, 0x14, 0x24, 0x0f, 0x7c, 0xa5,
537 0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
538 0x28, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
539 },
540 },
541 {
542 .pixel_clock = 40000000,
543 .conf = {
544 0x01, 0x51, 0x32, 0x55, 0x01, 0x00, 0x88, 0x02,
545 0x4d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
546 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
547 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
548 },
549 },
550 {
551 .pixel_clock = 50000000,
552 .conf = {
553 0x01, 0x51, 0x34, 0x40, 0x64, 0x09, 0x88, 0xc3,
554 0x3d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
555 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
556 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
557 },
558 },
559 {
560 .pixel_clock = 65000000,
561 .conf = {
562 0x01, 0x51, 0x36, 0x31, 0x40, 0x10, 0x04, 0xc6,
563 0x2e, 0xe8, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
564 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
565 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
566 },
567 },
568 {
569 .pixel_clock = 74176000,
570 .conf = {
571 0x01, 0x51, 0x3E, 0x35, 0x5B, 0xDE, 0x88, 0x42,
572 0x53, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
573 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
574 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
575 },
576 },
577 {
578 .pixel_clock = 74250000,
579 .conf = {
580 0x01, 0x51, 0x3E, 0x35, 0x40, 0xF0, 0x88, 0xC2,
581 0x52, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
582 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
583 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
584 },
585 },
586 {
587 .pixel_clock = 108000000,
588 .conf = {
589 0x01, 0x51, 0x2d, 0x15, 0x01, 0x00, 0x88, 0x02,
590 0x72, 0x52, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
591 0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
592 0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
593 },
594 },
595 {
596 .pixel_clock = 148500000,
597 .conf = {
598 0x01, 0x51, 0x1f, 0x00, 0x40, 0xf8, 0x88, 0xc1,
599 0x52, 0x52, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5,
600 0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
601 0x08, 0x10, 0x01, 0x01, 0x48, 0x4a, 0x00, 0x40,
602 },
603 },
604};
605
190a3c61 606static const char * const hdmi_clk_gates4[] = {
9be7e989
AH
607 "hdmi", "sclk_hdmi"
608};
609
190a3c61 610static const char * const hdmi_clk_muxes4[] = {
9be7e989
AH
611 "sclk_pixel", "sclk_hdmiphy", "mout_hdmi"
612};
613
68cd004e
AH
614static const char * const hdmi_clk_gates5433[] = {
615 "hdmi_pclk", "hdmi_i_pclk", "i_tmds_clk", "i_pixel_clk", "i_spdif_clk"
616};
617
618static const char * const hdmi_clk_muxes5433[] = {
619 "oscclk", "tmds_clko", "tmds_clko_user",
620 "oscclk", "pixel_clko", "pixel_clko_user"
621};
622
5eefadb5
AH
623static const struct hdmi_driver_data exynos4210_hdmi_driver_data = {
624 .type = HDMI_TYPE13,
625 .phy_confs = INIT_ARRAY_SPEC(hdmiphy_v13_configs),
9be7e989
AH
626 .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates4),
627 .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
a18a2dda 628};
d5e9ca4c 629
190a3c61 630static const struct hdmi_driver_data exynos4212_hdmi_driver_data = {
d5e9ca4c 631 .type = HDMI_TYPE14,
65e98030 632 .phy_confs = INIT_ARRAY_SPEC(hdmiphy_v14_configs),
9be7e989
AH
633 .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates4),
634 .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
d5e9ca4c
RS
635};
636
5eefadb5
AH
637static const struct hdmi_driver_data exynos5420_hdmi_driver_data = {
638 .type = HDMI_TYPE14,
639 .is_apb_phy = 1,
640 .phy_confs = INIT_ARRAY_SPEC(hdmiphy_5420_configs),
9be7e989
AH
641 .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates4),
642 .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
ff830c96
MS
643};
644
68cd004e
AH
645static const struct hdmi_driver_data exynos5433_hdmi_driver_data = {
646 .type = HDMI_TYPE14,
647 .is_apb_phy = 1,
648 .has_sysreg = 1,
649 .phy_confs = INIT_ARRAY_SPEC(hdmiphy_5433_configs),
650 .clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates5433),
651 .clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes5433),
652};
653
633d00b3
AH
654static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
655{
656 if ((reg_id & 0xffff0000) == HDMI_MAPPED_BASE)
657 return hdmi_reg_map[reg_id & 0xffff][hdata->drv_data->type];
658 return reg_id;
659}
660
d8408326
SWK
661static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
662{
633d00b3 663 return readl(hdata->regs + hdmi_map_reg(hdata, reg_id));
d8408326
SWK
664}
665
666static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
667 u32 reg_id, u8 value)
668{
1993c339 669 writel(value, hdata->regs + hdmi_map_reg(hdata, reg_id));
d8408326
SWK
670}
671
edb6e412
AH
672static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
673 int bytes, u32 val)
674{
633d00b3
AH
675 reg_id = hdmi_map_reg(hdata, reg_id);
676
edb6e412 677 while (--bytes >= 0) {
1993c339 678 writel(val & 0xff, hdata->regs + reg_id);
edb6e412
AH
679 val >>= 8;
680 reg_id += 4;
681 }
682}
683
d8408326
SWK
684static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
685 u32 reg_id, u32 value, u32 mask)
686{
633d00b3
AH
687 u32 old;
688
689 reg_id = hdmi_map_reg(hdata, reg_id);
690 old = readl(hdata->regs + reg_id);
d8408326
SWK
691 value = (value & mask) | (old & ~mask);
692 writel(value, hdata->regs + reg_id);
693}
694
d5e9ca4c
RS
695static int hdmiphy_reg_write_buf(struct hdmi_context *hdata,
696 u32 reg_offset, const u8 *buf, u32 len)
697{
698 if ((reg_offset + len) > 32)
699 return -EINVAL;
700
701 if (hdata->hdmiphy_port) {
702 int ret;
703
704 ret = i2c_master_send(hdata->hdmiphy_port, buf, len);
705 if (ret == len)
706 return 0;
707 return ret;
708 } else {
709 int i;
710 for (i = 0; i < len; i++)
1993c339 711 writel(buf[i], hdata->regs_hdmiphy +
d5e9ca4c
RS
712 ((reg_offset + i)<<2));
713 return 0;
714 }
715}
716
9be7e989
AH
717static int hdmi_clk_enable_gates(struct hdmi_context *hdata)
718{
719 int i, ret;
720
721 for (i = 0; i < hdata->drv_data->clk_gates.count; ++i) {
722 ret = clk_prepare_enable(hdata->clk_gates[i]);
723 if (!ret)
724 continue;
725
726 dev_err(hdata->dev, "Cannot enable clock '%s', %d\n",
727 hdata->drv_data->clk_gates.data[i], ret);
728 while (i--)
729 clk_disable_unprepare(hdata->clk_gates[i]);
730 return ret;
731 }
732
733 return 0;
734}
735
736static void hdmi_clk_disable_gates(struct hdmi_context *hdata)
737{
738 int i = hdata->drv_data->clk_gates.count;
739
740 while (i--)
741 clk_disable_unprepare(hdata->clk_gates[i]);
742}
743
744static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy)
745{
746 struct device *dev = hdata->dev;
747 int ret = 0;
748 int i;
749
750 for (i = 0; i < hdata->drv_data->clk_muxes.count; i += 3) {
751 struct clk **c = &hdata->clk_muxes[i];
752
753 ret = clk_set_parent(c[2], c[to_phy]);
754 if (!ret)
755 continue;
756
757 dev_err(dev, "Cannot set clock parent of '%s' to '%s', %d\n",
758 hdata->drv_data->clk_muxes.data[i + 2],
759 hdata->drv_data->clk_muxes.data[i + to_phy], ret);
760 }
761
762 return ret;
763}
764
a144c2e9
RS
765static u8 hdmi_chksum(struct hdmi_context *hdata,
766 u32 start, u8 len, u32 hdr_sum)
767{
768 int i;
769
770 /* hdr_sum : header0 + header1 + header2
771 * start : start address of packet byte1
772 * len : packet bytes - 1 */
773 for (i = 0; i < len; ++i)
774 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
775
776 /* return 2's complement of 8 bit hdr_sum */
777 return (u8)(~(hdr_sum & 0xff) + 1);
778}
779
780static void hdmi_reg_infoframe(struct hdmi_context *hdata,
d34d59bd 781 union hdmi_infoframe *infoframe)
a144c2e9
RS
782{
783 u32 hdr_sum;
784 u8 chksum;
c93aaebf 785 u8 ar;
a144c2e9 786
a144c2e9
RS
787 if (hdata->dvi_mode) {
788 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
789 HDMI_VSI_CON_DO_NOT_TRANSMIT);
790 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
791 HDMI_AVI_CON_DO_NOT_TRANSMIT);
792 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
793 return;
794 }
795
d34d59bd
SK
796 switch (infoframe->any.type) {
797 case HDMI_INFOFRAME_TYPE_AVI:
a144c2e9 798 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
d34d59bd
SK
799 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
800 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
801 infoframe->any.version);
802 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
803 hdr_sum = infoframe->any.type + infoframe->any.version +
804 infoframe->any.length;
a144c2e9
RS
805
806 /* Output format zero hardcoded ,RGB YBCR selection */
807 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
808 AVI_ACTIVE_FORMAT_VALID |
809 AVI_UNDERSCANNED_DISPLAY_VALID);
810
46154152
S
811 /*
812 * Set the aspect ratio as per the mode, mentioned in
813 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
814 */
c93aaebf
AH
815 ar = hdata->current_mode.picture_aspect_ratio;
816 switch (ar) {
46154152 817 case HDMI_PICTURE_ASPECT_4_3:
c93aaebf 818 ar |= AVI_4_3_CENTER_RATIO;
46154152
S
819 break;
820 case HDMI_PICTURE_ASPECT_16_9:
c93aaebf 821 ar |= AVI_16_9_CENTER_RATIO;
46154152
S
822 break;
823 case HDMI_PICTURE_ASPECT_NONE:
824 default:
c93aaebf 825 ar |= AVI_SAME_AS_PIC_ASPECT_RATIO;
46154152
S
826 break;
827 }
c93aaebf 828 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), ar);
a144c2e9 829
c93aaebf 830 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), hdata->cea_video_id);
a144c2e9
RS
831
832 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
d34d59bd 833 infoframe->any.length, hdr_sum);
a144c2e9
RS
834 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
835 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
836 break;
d34d59bd 837 case HDMI_INFOFRAME_TYPE_AUDIO:
a144c2e9 838 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
d34d59bd
SK
839 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
840 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
841 infoframe->any.version);
842 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
843 hdr_sum = infoframe->any.type + infoframe->any.version +
844 infoframe->any.length;
a144c2e9 845 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
d34d59bd 846 infoframe->any.length, hdr_sum);
a144c2e9
RS
847 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
848 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
849 break;
850 default:
851 break;
852 }
853}
854
d9716ee3
SP
855static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
856 bool force)
4551789f 857{
185f22d2 858 struct hdmi_context *hdata = connector_to_hdmi(connector);
4551789f 859
2228b7cd 860 if (gpiod_get_value(hdata->hpd_gpio))
ef6ce28b 861 return connector_status_connected;
5137c8ca 862
ef6ce28b 863 return connector_status_disconnected;
4551789f
SP
864}
865
d9716ee3 866static void hdmi_connector_destroy(struct drm_connector *connector)
d8408326 867{
ad279310
AH
868 drm_connector_unregister(connector);
869 drm_connector_cleanup(connector);
d8408326
SWK
870}
871
800ba2b5 872static const struct drm_connector_funcs hdmi_connector_funcs = {
63498e30 873 .dpms = drm_atomic_helper_connector_dpms,
d9716ee3
SP
874 .fill_modes = drm_helper_probe_single_connector_modes,
875 .detect = hdmi_detect,
876 .destroy = hdmi_connector_destroy,
4ea9526b
GP
877 .reset = drm_atomic_helper_connector_reset,
878 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
879 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
d9716ee3
SP
880};
881
882static int hdmi_get_modes(struct drm_connector *connector)
d8408326 883{
185f22d2 884 struct hdmi_context *hdata = connector_to_hdmi(connector);
d9716ee3 885 struct edid *edid;
64ebd890 886 int ret;
d8408326 887
8fa04aae 888 if (!hdata->ddc_adpt)
d9716ee3 889 return -ENODEV;
d8408326 890
8fa04aae 891 edid = drm_get_edid(connector, hdata->ddc_adpt);
d9716ee3
SP
892 if (!edid)
893 return -ENODEV;
9c08e4ba 894
d9716ee3 895 hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
9c08e4ba
RS
896 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
897 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
d9716ee3 898 edid->width_cm, edid->height_cm);
d8408326 899
d9716ee3
SP
900 drm_mode_connector_update_edid_property(connector, edid);
901
64ebd890
AH
902 ret = drm_add_edid_modes(connector, edid);
903
904 kfree(edid);
905
906 return ret;
d8408326
SWK
907}
908
6b986edf 909static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
d8408326 910{
65e98030 911 const struct hdmiphy_configs *confs = &hdata->drv_data->phy_confs;
d5e9ca4c 912 int i;
6b986edf 913
65e98030
AH
914 for (i = 0; i < confs->count; i++)
915 if (confs->data[i].pixel_clock == pixel_clock)
2f7e2ed0 916 return i;
2f7e2ed0
SP
917
918 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
919 return -EINVAL;
920}
921
d9716ee3 922static int hdmi_mode_valid(struct drm_connector *connector,
f041b257 923 struct drm_display_mode *mode)
3ecd70b1 924{
185f22d2 925 struct hdmi_context *hdata = connector_to_hdmi(connector);
6b986edf 926 int ret;
3ecd70b1 927
16844fb1
RS
928 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
929 mode->hdisplay, mode->vdisplay, mode->vrefresh,
930 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
931 false, mode->clock * 1000);
3ecd70b1 932
16844fb1 933 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
6b986edf 934 if (ret < 0)
d9716ee3
SP
935 return MODE_BAD;
936
937 return MODE_OK;
938}
939
800ba2b5 940static const struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
d9716ee3
SP
941 .get_modes = hdmi_get_modes,
942 .mode_valid = hdmi_mode_valid,
d9716ee3
SP
943};
944
2b8376c8 945static int hdmi_create_connector(struct drm_encoder *encoder)
d9716ee3 946{
2b8376c8 947 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
d9716ee3
SP
948 struct drm_connector *connector = &hdata->connector;
949 int ret;
950
d9716ee3
SP
951 connector->interlace_allowed = true;
952 connector->polled = DRM_CONNECTOR_POLL_HPD;
953
954 ret = drm_connector_init(hdata->drm_dev, connector,
955 &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
956 if (ret) {
957 DRM_ERROR("Failed to initialize connector with drm\n");
6b986edf 958 return ret;
d9716ee3
SP
959 }
960
961 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
34ea3d38 962 drm_connector_register(connector);
2b8376c8 963 drm_mode_connector_attach_encoder(connector, encoder);
d9716ee3
SP
964
965 return 0;
966}
967
2b8376c8
GP
968static bool hdmi_mode_fixup(struct drm_encoder *encoder,
969 const struct drm_display_mode *mode,
970 struct drm_display_mode *adjusted_mode)
f041b257 971{
2b8376c8
GP
972 struct drm_device *dev = encoder->dev;
973 struct drm_connector *connector;
f041b257
SP
974 struct drm_display_mode *m;
975 int mode_ok;
976
f041b257
SP
977 drm_mode_set_crtcinfo(adjusted_mode, 0);
978
2b8376c8
GP
979 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
980 if (connector->encoder == encoder)
981 break;
982 }
983
984 if (connector->encoder != encoder)
985 return true;
986
d9716ee3 987 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
f041b257 988
d9716ee3 989 if (mode_ok == MODE_OK)
2b8376c8 990 return true;
f041b257
SP
991
992 /*
5eefadb5 993 * Find the most suitable mode and copy it to adjusted_mode.
f041b257
SP
994 */
995 list_for_each_entry(m, &connector->modes, head) {
d9716ee3 996 mode_ok = hdmi_mode_valid(connector, m);
f041b257 997
d9716ee3 998 if (mode_ok == MODE_OK) {
f041b257
SP
999 DRM_INFO("desired mode doesn't exist so\n");
1000 DRM_INFO("use the most suitable mode among modes.\n");
1001
1002 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
1003 m->hdisplay, m->vdisplay, m->vrefresh);
1004
75626853 1005 drm_mode_copy(adjusted_mode, m);
f041b257
SP
1006 break;
1007 }
1008 }
2b8376c8
GP
1009
1010 return true;
f041b257
SP
1011}
1012
d24bb3e5 1013static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq)
3e148baf
SWK
1014{
1015 u32 n, cts;
1016
d24bb3e5
AH
1017 cts = (freq % 9) ? 27000 : 30000;
1018 n = 128 * freq / (27000000 / cts);
3e148baf 1019
d24bb3e5
AH
1020 hdmi_reg_writev(hdata, HDMI_ACR_N0, 3, n);
1021 hdmi_reg_writev(hdata, HDMI_ACR_MCTS0, 3, cts);
1022 hdmi_reg_writev(hdata, HDMI_ACR_CTS0, 3, cts);
633d00b3 1023 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
3e148baf
SWK
1024}
1025
1026static void hdmi_audio_init(struct hdmi_context *hdata)
1027{
7a9bf6e5 1028 u32 sample_rate, bits_per_sample;
3e148baf
SWK
1029 u32 data_num, bit_ch, sample_frq;
1030 u32 val;
3e148baf
SWK
1031
1032 sample_rate = 44100;
1033 bits_per_sample = 16;
3e148baf
SWK
1034
1035 switch (bits_per_sample) {
1036 case 20:
1037 data_num = 2;
5eefadb5 1038 bit_ch = 1;
3e148baf
SWK
1039 break;
1040 case 24:
1041 data_num = 3;
5eefadb5 1042 bit_ch = 1;
3e148baf
SWK
1043 break;
1044 default:
1045 data_num = 1;
5eefadb5 1046 bit_ch = 0;
3e148baf
SWK
1047 break;
1048 }
1049
d24bb3e5 1050 hdmi_reg_acr(hdata, sample_rate);
3e148baf
SWK
1051
1052 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1053 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1054 | HDMI_I2S_MUX_ENABLE);
1055
1056 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1057 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1058
1059 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1060
1061 sample_frq = (sample_rate == 44100) ? 0 :
1062 (sample_rate == 48000) ? 2 :
1063 (sample_rate == 32000) ? 3 :
1064 (sample_rate == 96000) ? 0xa : 0x0;
1065
1066 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1067 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1068
1069 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1070 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1071
1072 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1073 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1074 | HDMI_I2S_SEL_LRCK(6));
1075 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1076 | HDMI_I2S_SEL_SDATA2(4));
1077 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1078 | HDMI_I2S_SEL_SDATA2(2));
1079 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1080
1081 /* I2S_CON_1 & 2 */
1082 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1083 | HDMI_I2S_L_CH_LOW_POL);
1084 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1085 | HDMI_I2S_SET_BIT_CH(bit_ch)
1086 | HDMI_I2S_SET_SDATA_BIT(data_num)
1087 | HDMI_I2S_BASIC_FORMAT);
1088
1089 /* Configure register related to CUV information */
1090 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1091 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1092 | HDMI_I2S_COPYRIGHT
1093 | HDMI_I2S_LINEAR_PCM
1094 | HDMI_I2S_CONSUMER_FORMAT);
1095 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1096 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1097 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1098 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1099 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1100 HDMI_I2S_ORG_SMP_FREQ_44_1
1101 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1102 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1103
1104 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1105}
1106
1107static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1108{
872d20d6 1109 if (hdata->dvi_mode)
3e148baf
SWK
1110 return;
1111
1112 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1113 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1114 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1115}
1116
bfa48423 1117static void hdmi_start(struct hdmi_context *hdata, bool start)
d8408326 1118{
bfa48423 1119 u32 val = start ? HDMI_TG_EN : 0;
3ecd70b1 1120
bfa48423
RS
1121 if (hdata->current_mode.flags & DRM_MODE_FLAG_INTERLACE)
1122 val |= HDMI_FIELD_EN;
3ecd70b1 1123
bfa48423
RS
1124 hdmi_reg_writemask(hdata, HDMI_CON_0, val, HDMI_EN);
1125 hdmi_reg_writemask(hdata, HDMI_TG_CMD, val, HDMI_TG_EN | HDMI_FIELD_EN);
d8408326
SWK
1126}
1127
1128static void hdmi_conf_init(struct hdmi_context *hdata)
1129{
d34d59bd 1130 union hdmi_infoframe infoframe;
a144c2e9 1131
77006a7a 1132 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
d8408326
SWK
1133 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1134 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
d8408326
SWK
1135
1136 /* choose HDMI mode */
1137 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1138 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
5eefadb5 1139 /* apply video pre-amble and guard band in HDMI mode only */
9a8e1cb0 1140 hdmi_reg_writeb(hdata, HDMI_CON_2, 0);
d8408326
SWK
1141 /* disable bluescreen */
1142 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
3ecd70b1 1143
872d20d6 1144 if (hdata->dvi_mode) {
872d20d6
SWK
1145 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1146 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1147 hdmi_reg_writeb(hdata, HDMI_CON_2,
1148 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1149 }
1150
cd240cde 1151 if (hdata->drv_data->type == HDMI_TYPE13) {
3ecd70b1
JS
1152 /* choose bluescreen (fecal) color */
1153 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1154 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1155 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1156
1157 /* enable AVI packet every vsync, fixes purple line problem */
1158 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1159 /* force RGB, look to CEA-861-D, table 7 for more detail */
1160 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1161 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1162
1163 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1164 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1165 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1166 } else {
d34d59bd
SK
1167 infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
1168 infoframe.any.version = HDMI_AVI_VERSION;
1169 infoframe.any.length = HDMI_AVI_LENGTH;
a144c2e9
RS
1170 hdmi_reg_infoframe(hdata, &infoframe);
1171
d34d59bd
SK
1172 infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
1173 infoframe.any.version = HDMI_AUI_VERSION;
1174 infoframe.any.length = HDMI_AUI_LENGTH;
a144c2e9
RS
1175 hdmi_reg_infoframe(hdata, &infoframe);
1176
3ecd70b1 1177 /* enable AVI packet every vsync, fixes purple line problem */
3ecd70b1
JS
1178 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1179 }
d8408326
SWK
1180}
1181
8eb6d4ec
AH
1182static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
1183{
1184 int tries;
1185
1186 for (tries = 0; tries < 10; ++tries) {
1187 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
1188
1189 if (val & HDMI_PHY_STATUS_READY) {
1190 DRM_DEBUG_KMS("PLL stabilized after %d tries\n", tries);
1191 return;
1192 }
1193 usleep_range(10, 20);
1194 }
1195
1196 DRM_ERROR("PLL could not reach steady state\n");
1197}
1198
16844fb1 1199static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
d8408326 1200{
edb6e412
AH
1201 struct drm_display_mode *m = &hdata->current_mode;
1202 unsigned int val;
3ecd70b1 1203
edb6e412
AH
1204 hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1205 hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
1206 (m->htotal << 12) | m->vtotal);
1207
1208 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1209 hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, val);
1210
1211 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1212 hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, val);
1213
1214 val = (m->hsync_start - m->hdisplay - 2);
1215 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
5eefadb5 1216 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
edb6e412
AH
1217 hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val);
1218
1219 /*
1220 * Quirk requirement for exynos HDMI IP design,
1221 * 2 pixels less than the actual calculation for hsync_start
1222 * and end.
1223 */
1224
1225 /* Following values & calculations differ for different type of modes */
1226 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
edb6e412
AH
1227 val = ((m->vsync_end - m->vdisplay) / 2);
1228 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1229 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1230
1231 val = m->vtotal / 2;
1232 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1233 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1234
1235 val = (m->vtotal +
1236 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1237 val |= m->vtotal << 11;
1238 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, val);
1239
1240 val = ((m->vtotal / 2) + 7);
1241 val |= ((m->vtotal / 2) + 2) << 12;
1242 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, val);
1243
1244 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1245 val |= ((m->htotal / 2) +
1246 (m->hsync_start - m->hdisplay)) << 12;
1247 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, val);
1248
1249 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1250 (m->vtotal - m->vdisplay) / 2);
1251 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1252
1253 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249);
1254 } else {
edb6e412
AH
1255 val = m->vtotal;
1256 val |= (m->vtotal - m->vdisplay) << 11;
1257 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1258
1259 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, 0);
1260
1261 val = (m->vsync_end - m->vdisplay);
1262 val |= ((m->vsync_start - m->vdisplay) << 12);
1263 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1264
1265 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, 0x1001);
1266 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, 0x1001);
1267 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1268 m->vtotal - m->vdisplay);
1269 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
edb6e412
AH
1270 }
1271
edb6e412
AH
1272 hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1273 hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1274 hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1275 hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
3ecd70b1
JS
1276}
1277
16844fb1 1278static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
3ecd70b1 1279{
7b5102da 1280 struct drm_display_mode *m = &hdata->current_mode;
d8408326 1281
7b5102da
AH
1282 hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1283 hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
1284 hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal);
1285 hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1,
5eefadb5 1286 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
7b5102da
AH
1287 hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1,
1288 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1289 hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1,
1290 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1291
1292 /*
1293 * Quirk requirement for exynos 5 HDMI IP design,
1294 * 2 pixels less than the actual calculation for hsync_start
1295 * and end.
1296 */
1297
1298 /* Following values & calculations differ for different type of modes */
1299 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
7b5102da
AH
1300 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1301 (m->vsync_end - m->vdisplay) / 2);
1302 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1303 (m->vsync_start - m->vdisplay) / 2);
1304 hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal / 2);
1305 hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1306 (m->vtotal - m->vdisplay) / 2);
1307 hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2,
1308 m->vtotal - m->vdisplay / 2);
1309 hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, m->vtotal);
1310 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2,
1311 (m->vtotal / 2) + 7);
1312 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2,
1313 (m->vtotal / 2) + 2);
1314 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2,
1315 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1316 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2,
1317 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1318 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1319 (m->vtotal - m->vdisplay) / 2);
1320 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1321 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2,
1322 m->vtotal - m->vdisplay / 2);
1323 hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2,
1324 (m->vtotal / 2) + 1);
1325 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2,
1326 (m->vtotal / 2) + 1);
1327 hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2,
1328 (m->vtotal / 2) + 1);
1329 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0);
1330 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0);
1331 } else {
7b5102da
AH
1332 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1333 m->vsync_end - m->vdisplay);
1334 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1335 m->vsync_start - m->vdisplay);
1336 hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal);
1337 hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1338 m->vtotal - m->vdisplay);
1339 hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2, 0xffff);
1340 hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, 0xffff);
1341 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2, 0xffff);
1342 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2, 0xffff);
1343 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2, 0xffff);
1344 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2, 0xffff);
1345 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1346 m->vtotal - m->vdisplay);
1347 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
7b5102da
AH
1348 }
1349
7b5102da
AH
1350 hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2,
1351 m->hsync_start - m->hdisplay - 2);
1352 hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2,
1353 m->hsync_end - m->hdisplay - 2);
1354 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_1_0, 2, 0xffff);
1355 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_2_0, 2, 0xffff);
1356 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_3_0, 2, 0xffff);
1357 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_4_0, 2, 0xffff);
1358 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_5_0, 2, 0xffff);
1359 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_6_0, 2, 0xffff);
1360 hdmi_reg_writev(hdata, HDMI_V_BLANK_F2_0, 2, 0xffff);
1361 hdmi_reg_writev(hdata, HDMI_V_BLANK_F3_0, 2, 0xffff);
1362 hdmi_reg_writev(hdata, HDMI_V_BLANK_F4_0, 2, 0xffff);
1363 hdmi_reg_writev(hdata, HDMI_V_BLANK_F5_0, 2, 0xffff);
1364 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_3_0, 2, 0xffff);
1365 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_4_0, 2, 0xffff);
1366 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_5_0, 2, 0xffff);
1367 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_6_0, 2, 0xffff);
1368 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, 2, 0xffff);
1369 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, 2, 0xffff);
1370 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff);
1371 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff);
3ecd70b1 1372
7b5102da
AH
1373 hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1374 hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1375 hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1376 hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
68cd004e
AH
1377 if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1378 hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1);
d8408326
SWK
1379}
1380
16844fb1 1381static void hdmi_mode_apply(struct hdmi_context *hdata)
3ecd70b1 1382{
cd240cde 1383 if (hdata->drv_data->type == HDMI_TYPE13)
16844fb1 1384 hdmi_v13_mode_apply(hdata);
3ecd70b1 1385 else
16844fb1 1386 hdmi_v14_mode_apply(hdata);
8eb6d4ec 1387
8eb6d4ec 1388 hdmi_start(hdata, true);
3ecd70b1
JS
1389}
1390
d8408326
SWK
1391static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1392{
69f88877
AH
1393 hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, 0, 1);
1394 usleep_range(10000, 12000);
1395 hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, ~0, 1);
1396 usleep_range(10000, 12000);
633d00b3 1397 hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
09760ea3 1398 usleep_range(10000, 12000);
5eefadb5 1399 hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
09760ea3 1400 usleep_range(10000, 12000);
d8408326
SWK
1401}
1402
68cd004e
AH
1403static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable)
1404{
1405 u8 v = enable ? HDMI_PHY_ENABLE_MODE_SET : HDMI_PHY_DISABLE_MODE_SET;
1406
1407 if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1408 writel(v, hdata->regs_hdmiphy + HDMIPHY5433_MODE_SET_DONE);
1409}
1410
d8408326
SWK
1411static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1412{
d8408326 1413 int ret;
4677f51a 1414 const u8 *phy_conf;
d8408326 1415
4677f51a
AH
1416 ret = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000);
1417 if (ret < 0) {
6b986edf
RS
1418 DRM_ERROR("failed to find hdmiphy conf\n");
1419 return;
1420 }
4677f51a
AH
1421 phy_conf = hdata->drv_data->phy_confs.data[ret].conf;
1422
1423 hdmi_clk_set_parents(hdata, false);
1424
1425 hdmiphy_conf_reset(hdata);
6b986edf 1426
68cd004e 1427 hdmiphy_enable_mode_set(hdata, true);
4677f51a 1428 ret = hdmiphy_reg_write_buf(hdata, 0, phy_conf, 32);
d5e9ca4c
RS
1429 if (ret) {
1430 DRM_ERROR("failed to configure hdmiphy\n");
d8408326
SWK
1431 return;
1432 }
68cd004e 1433 hdmiphy_enable_mode_set(hdata, false);
4677f51a 1434 hdmi_clk_set_parents(hdata, true);
09760ea3 1435 usleep_range(10000, 12000);
4677f51a 1436 hdmiphy_wait_for_pll(hdata);
d8408326
SWK
1437}
1438
1439static void hdmi_conf_apply(struct hdmi_context *hdata)
1440{
bfa48423 1441 hdmi_start(hdata, false);
d8408326 1442 hdmi_conf_init(hdata);
3e148baf 1443 hdmi_audio_init(hdata);
16844fb1 1444 hdmi_mode_apply(hdata);
3e148baf 1445 hdmi_audio_control(hdata, true);
d8408326
SWK
1446}
1447
2b8376c8
GP
1448static void hdmi_mode_set(struct drm_encoder *encoder,
1449 struct drm_display_mode *mode,
1450 struct drm_display_mode *adjusted_mode)
d8408326 1451{
cf67cc9a 1452 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
2b8376c8 1453 struct drm_display_mode *m = adjusted_mode;
d8408326 1454
cbc4c33d
YC
1455 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1456 m->hdisplay, m->vdisplay,
6b986edf 1457 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1e6d459d 1458 "INTERLACED" : "PROGRESSIVE");
d8408326 1459
2b8376c8 1460 drm_mode_copy(&hdata->current_mode, m);
c93aaebf 1461 hdata->cea_video_id = drm_match_cea_mode(mode);
d8408326
SWK
1462}
1463
68cd004e
AH
1464static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
1465{
1466 if (!hdata->sysreg)
1467 return;
1468
1469 regmap_update_bits(hdata->sysreg, EXYNOS5433_SYSREG_DISP_HDMI_PHY,
1470 SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0);
1471}
1472
59b62d3c 1473static void hdmiphy_enable(struct hdmi_context *hdata)
cf8fc4f1 1474{
882a0644 1475 if (hdata->powered)
cf8fc4f1 1476 return;
d8408326 1477
af65c804
SP
1478 pm_runtime_get_sync(hdata->dev);
1479
af1f7c24 1480 if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
ad07945a
SWK
1481 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1482
049d34e9
RS
1483 regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1484 PMU_HDMI_PHY_ENABLE_BIT, 1);
1485
68cd004e
AH
1486 hdmi_set_refclk(hdata, true);
1487
5dd45e2c
AH
1488 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN);
1489
59b62d3c 1490 hdmiphy_conf_apply(hdata);
f28464c3
GP
1491
1492 hdata->powered = true;
cf8fc4f1
JS
1493}
1494
59b62d3c
AH
1495static void hdmiphy_disable(struct hdmi_context *hdata)
1496{
1497 if (!hdata->powered)
1498 return;
1499
1500 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
1501
1502 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN);
1503
1504 hdmi_set_refclk(hdata, false);
1505
1506 regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1507 PMU_HDMI_PHY_ENABLE_BIT, 0);
1508
1509 regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk);
1510
1511 pm_runtime_put_sync(hdata->dev);
1512
1513 hdata->powered = false;
1514}
1515
1516static void hdmi_enable(struct drm_encoder *encoder)
1517{
1518 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
1519
1520 hdmiphy_enable(hdata);
1521 hdmi_conf_apply(hdata);
1522}
1523
2b8376c8 1524static void hdmi_disable(struct drm_encoder *encoder)
cf8fc4f1 1525{
cf67cc9a 1526 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
2b8376c8 1527 struct drm_crtc *crtc = encoder->crtc;
b6595dc7 1528 const struct drm_crtc_helper_funcs *funcs = NULL;
cf8fc4f1 1529
cf8fc4f1 1530 if (!hdata->powered)
882a0644 1531 return;
cf8fc4f1 1532
b6595dc7
GP
1533 /*
1534 * The SFRs of VP and Mixer are updated by Vertical Sync of
1535 * Timing generator which is a part of HDMI so the sequence
1536 * to disable TV Subsystem should be as following,
1537 * VP -> Mixer -> HDMI
1538 *
1539 * Below codes will try to disable Mixer and VP(if used)
1540 * prior to disabling HDMI.
1541 */
1542 if (crtc)
1543 funcs = crtc->helper_private;
1544 if (funcs && funcs->disable)
1545 (*funcs->disable)(crtc);
1546
724fd140
SP
1547 cancel_delayed_work(&hdata->hotplug_work);
1548
59b62d3c 1549 hdmiphy_disable(hdata);
d8408326
SWK
1550}
1551
800ba2b5 1552static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
f041b257 1553 .mode_fixup = hdmi_mode_fixup,
d8408326 1554 .mode_set = hdmi_mode_set,
b6595dc7
GP
1555 .enable = hdmi_enable,
1556 .disable = hdmi_disable,
d8408326
SWK
1557};
1558
800ba2b5 1559static const struct drm_encoder_funcs exynos_hdmi_encoder_funcs = {
2b8376c8
GP
1560 .destroy = drm_encoder_cleanup,
1561};
1562
724fd140 1563static void hdmi_hotplug_work_func(struct work_struct *work)
cf8fc4f1 1564{
724fd140
SP
1565 struct hdmi_context *hdata;
1566
1567 hdata = container_of(work, struct hdmi_context, hotplug_work.work);
cf8fc4f1 1568
4551789f
SP
1569 if (hdata->drm_dev)
1570 drm_helper_hpd_irq_event(hdata->drm_dev);
724fd140
SP
1571}
1572
1573static irqreturn_t hdmi_irq_thread(int irq, void *arg)
1574{
1575 struct hdmi_context *hdata = arg;
1576
1577 mod_delayed_work(system_wq, &hdata->hotplug_work,
1578 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
cf8fc4f1 1579
cf8fc4f1
JS
1580 return IRQ_HANDLED;
1581}
1582
9be7e989
AH
1583static int hdmi_clks_get(struct hdmi_context *hdata,
1584 const struct string_array_spec *names,
1585 struct clk **clks)
1586{
1587 struct device *dev = hdata->dev;
1588 int i;
1589
1590 for (i = 0; i < names->count; ++i) {
1591 struct clk *clk = devm_clk_get(dev, names->data[i]);
1592
1593 if (IS_ERR(clk)) {
1594 int ret = PTR_ERR(clk);
1595
1596 dev_err(dev, "Cannot get clock %s, %d\n",
1597 names->data[i], ret);
1598
1599 return ret;
1600 }
1601
1602 clks[i] = clk;
1603 }
1604
1605 return 0;
1606}
1607
1608static int hdmi_clk_init(struct hdmi_context *hdata)
1609{
1610 const struct hdmi_driver_data *drv_data = hdata->drv_data;
1611 int count = drv_data->clk_gates.count + drv_data->clk_muxes.count;
1612 struct device *dev = hdata->dev;
1613 struct clk **clks;
1614 int ret;
1615
1616 if (!count)
1617 return 0;
1618
1619 clks = devm_kzalloc(dev, sizeof(*clks) * count, GFP_KERNEL);
1620 if (!clks)
f9628c2a 1621 return -ENOMEM;
9be7e989
AH
1622
1623 hdata->clk_gates = clks;
1624 hdata->clk_muxes = clks + drv_data->clk_gates.count;
1625
1626 ret = hdmi_clks_get(hdata, &drv_data->clk_gates, hdata->clk_gates);
1627 if (ret)
1628 return ret;
1629
1630 return hdmi_clks_get(hdata, &drv_data->clk_muxes, hdata->clk_muxes);
1631}
1632
1633
59b62d3c
AH
1634static void hdmiphy_clk_enable(struct exynos_drm_clk *clk, bool enable)
1635{
1636 struct hdmi_context *hdata = container_of(clk, struct hdmi_context,
1637 phy_clk);
1638
1639 if (enable)
1640 hdmiphy_enable(hdata);
1641 else
1642 hdmiphy_disable(hdata);
1643}
1644
56550d94 1645static int hdmi_resources_init(struct hdmi_context *hdata)
d8408326
SWK
1646{
1647 struct device *dev = hdata->dev;
d8408326
SWK
1648 int i, ret;
1649
1650 DRM_DEBUG_KMS("HDMI resource init\n");
1651
2228b7cd
AH
1652 hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
1653 if (IS_ERR(hdata->hpd_gpio)) {
1654 DRM_ERROR("cannot get hpd gpio property\n");
1655 return PTR_ERR(hdata->hpd_gpio);
1656 }
1657
1658 hdata->irq = gpiod_to_irq(hdata->hpd_gpio);
1659 if (hdata->irq < 0) {
1660 DRM_ERROR("failed to get GPIO irq\n");
1661 return hdata->irq;
1662 }
d8408326 1663
9be7e989
AH
1664 ret = hdmi_clk_init(hdata);
1665 if (ret)
1666 return ret;
1667
1668 ret = hdmi_clk_set_parents(hdata, false);
1669 if (ret)
1670 return ret;
d8408326 1671
d8408326 1672 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
af1f7c24
AH
1673 hdata->regul_bulk[i].supply = supply[i];
1674 hdata->regul_bulk[i].consumer = NULL;
d8408326 1675 }
af1f7c24 1676 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk);
d8408326 1677 if (ret) {
b85881dd
JMC
1678 if (ret != -EPROBE_DEFER)
1679 DRM_ERROR("failed to get regulators\n");
df5225bc 1680 return ret;
d8408326 1681 }
d8408326 1682
af1f7c24 1683 hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
498d5a37 1684
af1f7c24 1685 if (PTR_ERR(hdata->reg_hdmi_en) == -ENODEV)
498d5a37
AH
1686 return 0;
1687
af1f7c24
AH
1688 if (IS_ERR(hdata->reg_hdmi_en))
1689 return PTR_ERR(hdata->reg_hdmi_en);
498d5a37 1690
af1f7c24 1691 ret = regulator_enable(hdata->reg_hdmi_en);
498d5a37
AH
1692 if (ret)
1693 DRM_ERROR("failed to enable hdmi-en regulator\n");
05fdf987 1694
df5225bc 1695 return ret;
d8408326
SWK
1696}
1697
22c4f428
RS
1698static struct of_device_id hdmi_match_types[] = {
1699 {
ff830c96
MS
1700 .compatible = "samsung,exynos4210-hdmi",
1701 .data = &exynos4210_hdmi_driver_data,
cc57caf0
RS
1702 }, {
1703 .compatible = "samsung,exynos4212-hdmi",
bfe4e84c 1704 .data = &exynos4212_hdmi_driver_data,
a18a2dda
RS
1705 }, {
1706 .compatible = "samsung,exynos5420-hdmi",
1707 .data = &exynos5420_hdmi_driver_data,
68cd004e
AH
1708 }, {
1709 .compatible = "samsung,exynos5433-hdmi",
1710 .data = &exynos5433_hdmi_driver_data,
c119ed05
TS
1711 }, {
1712 /* end node */
1713 }
1714};
39b58a39 1715MODULE_DEVICE_TABLE (of, hdmi_match_types);
c119ed05 1716
f37cd5e8
ID
1717static int hdmi_bind(struct device *dev, struct device *master, void *data)
1718{
1719 struct drm_device *drm_dev = data;
930865fb 1720 struct hdmi_context *hdata = dev_get_drvdata(dev);
2b8376c8
GP
1721 struct drm_encoder *encoder = &hdata->encoder;
1722 int ret, pipe;
f37cd5e8 1723
f37cd5e8
ID
1724 hdata->drm_dev = drm_dev;
1725
2b8376c8
GP
1726 pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
1727 EXYNOS_DISPLAY_TYPE_HDMI);
1728 if (pipe < 0)
1729 return pipe;
1730
59b62d3c
AH
1731 hdata->phy_clk.enable = hdmiphy_clk_enable;
1732
1733 exynos_drm_crtc_from_pipe(drm_dev, pipe)->pipe_clk = &hdata->phy_clk;
1734
2b8376c8
GP
1735 encoder->possible_crtcs = 1 << pipe;
1736
1737 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
1738
1739 drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
13a3d91f 1740 DRM_MODE_ENCODER_TMDS, NULL);
2b8376c8
GP
1741
1742 drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
a2986e80 1743
2b8376c8 1744 ret = hdmi_create_connector(encoder);
a2986e80
GP
1745 if (ret) {
1746 DRM_ERROR("failed to create connector ret = %d\n", ret);
2b8376c8 1747 drm_encoder_cleanup(encoder);
a2986e80
GP
1748 return ret;
1749 }
1750
1751 return 0;
f37cd5e8
ID
1752}
1753
1754static void hdmi_unbind(struct device *dev, struct device *master, void *data)
1755{
f37cd5e8
ID
1756}
1757
1758static const struct component_ops hdmi_component_ops = {
1759 .bind = hdmi_bind,
1760 .unbind = hdmi_unbind,
1761};
1762
e2a562dc
ID
1763static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev)
1764{
1765 const char *compatible_str = "samsung,exynos4210-hdmiddc";
1766 struct device_node *np;
1767
1768 np = of_find_compatible_node(NULL, NULL, compatible_str);
1769 if (np)
1770 return of_get_next_parent(np);
1771
1772 return NULL;
1773}
1774
1775static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
1776{
1777 const char *compatible_str = "samsung,exynos4212-hdmiphy";
1778
1779 return of_find_compatible_node(NULL, NULL, compatible_str);
1780}
1781
56550d94 1782static int hdmi_probe(struct platform_device *pdev)
d8408326 1783{
f37cd5e8 1784 struct device_node *ddc_node, *phy_node;
d8408326 1785 struct device *dev = &pdev->dev;
d8408326 1786 struct hdmi_context *hdata;
d8408326
SWK
1787 struct resource *res;
1788 int ret;
1789
88c49815 1790 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
930865fb
AH
1791 if (!hdata)
1792 return -ENOMEM;
1793
57a64122 1794 hdata->drv_data = of_device_get_match_data(dev);
930865fb 1795
930865fb 1796 platform_set_drvdata(pdev, hdata);
d8408326 1797
d8408326
SWK
1798 hdata->dev = dev;
1799
1800 ret = hdmi_resources_init(hdata);
1801 if (ret) {
b85881dd
JMC
1802 if (ret != -EPROBE_DEFER)
1803 DRM_ERROR("hdmi_resources_init failed\n");
df5225bc 1804 return ret;
d8408326
SWK
1805 }
1806
1807 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
d873ab99 1808 hdata->regs = devm_ioremap_resource(dev, res);
df5225bc
ID
1809 if (IS_ERR(hdata->regs)) {
1810 ret = PTR_ERR(hdata->regs);
86650408 1811 return ret;
df5225bc 1812 }
d8408326 1813
e2a562dc
ID
1814 ddc_node = hdmi_legacy_ddc_dt_binding(dev);
1815 if (ddc_node)
1816 goto out_get_ddc_adpt;
1817
2b768132
DK
1818 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
1819 if (!ddc_node) {
1820 DRM_ERROR("Failed to find ddc node in device tree\n");
86650408 1821 return -ENODEV;
2b768132 1822 }
e2a562dc
ID
1823
1824out_get_ddc_adpt:
8fa04aae
ID
1825 hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
1826 if (!hdata->ddc_adpt) {
1827 DRM_ERROR("Failed to get ddc i2c adapter by node\n");
df5225bc 1828 return -EPROBE_DEFER;
d8408326 1829 }
d8408326 1830
e2a562dc
ID
1831 phy_node = hdmi_legacy_phy_dt_binding(dev);
1832 if (phy_node)
1833 goto out_get_phy_port;
1834
2b768132
DK
1835 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
1836 if (!phy_node) {
1837 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
1838 ret = -ENODEV;
1839 goto err_ddc;
1840 }
d5e9ca4c 1841
e2a562dc 1842out_get_phy_port:
cd240cde 1843 if (hdata->drv_data->is_apb_phy) {
d5e9ca4c
RS
1844 hdata->regs_hdmiphy = of_iomap(phy_node, 0);
1845 if (!hdata->regs_hdmiphy) {
1846 DRM_ERROR("failed to ioremap hdmi phy\n");
1847 ret = -ENOMEM;
1848 goto err_ddc;
1849 }
1850 } else {
1851 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
1852 if (!hdata->hdmiphy_port) {
1853 DRM_ERROR("Failed to get hdmi phy i2c client\n");
df5225bc 1854 ret = -EPROBE_DEFER;
d5e9ca4c
RS
1855 goto err_ddc;
1856 }
d8408326 1857 }
d8408326 1858
724fd140
SP
1859 INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
1860
dcb9a7c7 1861 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
77006a7a 1862 hdmi_irq_thread, IRQF_TRIGGER_RISING |
cf8fc4f1 1863 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
f041b257 1864 "hdmi", hdata);
d8408326 1865 if (ret) {
77006a7a 1866 DRM_ERROR("failed to register hdmi interrupt\n");
66265a2e 1867 goto err_hdmiphy;
d8408326 1868 }
d8408326 1869
049d34e9
RS
1870 hdata->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
1871 "samsung,syscon-phandle");
1872 if (IS_ERR(hdata->pmureg)) {
1873 DRM_ERROR("syscon regmap lookup failed.\n");
df5225bc 1874 ret = -EPROBE_DEFER;
049d34e9
RS
1875 goto err_hdmiphy;
1876 }
1877
68cd004e
AH
1878 if (hdata->drv_data->has_sysreg) {
1879 hdata->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1880 "samsung,sysreg-phandle");
1881 if (IS_ERR(hdata->sysreg)) {
1882 DRM_ERROR("sysreg regmap lookup failed.\n");
1883 ret = -EPROBE_DEFER;
1884 goto err_hdmiphy;
1885 }
1886 }
1887
af65c804 1888 pm_runtime_enable(dev);
d8408326 1889
df5225bc
ID
1890 ret = component_add(&pdev->dev, &hdmi_component_ops);
1891 if (ret)
1892 goto err_disable_pm_runtime;
1893
1894 return ret;
1895
1896err_disable_pm_runtime:
1897 pm_runtime_disable(dev);
d8408326 1898
d8408326 1899err_hdmiphy:
b21a3bf4
PT
1900 if (hdata->hdmiphy_port)
1901 put_device(&hdata->hdmiphy_port->dev);
d8408326 1902err_ddc:
8fa04aae 1903 put_device(&hdata->ddc_adpt->dev);
df5225bc 1904
d8408326
SWK
1905 return ret;
1906}
1907
56550d94 1908static int hdmi_remove(struct platform_device *pdev)
d8408326 1909{
930865fb 1910 struct hdmi_context *hdata = platform_get_drvdata(pdev);
d8408326 1911
724fd140
SP
1912 cancel_delayed_work_sync(&hdata->hotplug_work);
1913
2445c4a4
AH
1914 component_del(&pdev->dev, &hdmi_component_ops);
1915
1916 pm_runtime_disable(&pdev->dev);
1917
af1f7c24
AH
1918 if (!IS_ERR(hdata->reg_hdmi_en))
1919 regulator_disable(hdata->reg_hdmi_en);
05fdf987 1920
9d1e25c9
SWK
1921 if (hdata->hdmiphy_port)
1922 put_device(&hdata->hdmiphy_port->dev);
f37cd5e8 1923
2445c4a4 1924 put_device(&hdata->ddc_adpt->dev);
d8408326 1925
d8408326
SWK
1926 return 0;
1927}
1928
f28464c3
GP
1929#ifdef CONFIG_PM
1930static int exynos_hdmi_suspend(struct device *dev)
1931{
1932 struct hdmi_context *hdata = dev_get_drvdata(dev);
1933
9be7e989 1934 hdmi_clk_disable_gates(hdata);
f28464c3
GP
1935
1936 return 0;
1937}
1938
1939static int exynos_hdmi_resume(struct device *dev)
1940{
1941 struct hdmi_context *hdata = dev_get_drvdata(dev);
1942 int ret;
1943
9be7e989
AH
1944 ret = hdmi_clk_enable_gates(hdata);
1945 if (ret < 0)
f28464c3 1946 return ret;
f28464c3
GP
1947
1948 return 0;
1949}
1950#endif
1951
1952static const struct dev_pm_ops exynos_hdmi_pm_ops = {
1953 SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL)
1954};
1955
d8408326
SWK
1956struct platform_driver hdmi_driver = {
1957 .probe = hdmi_probe,
56550d94 1958 .remove = hdmi_remove,
d8408326 1959 .driver = {
22c4f428 1960 .name = "exynos-hdmi",
d8408326 1961 .owner = THIS_MODULE,
f28464c3 1962 .pm = &exynos_hdmi_pm_ops,
88c49815 1963 .of_match_table = hdmi_match_types,
d8408326
SWK
1964 },
1965};