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