Merge tag 'pwm/for-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
[deliverable/linux.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
940static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
941{
185f22d2 942 struct hdmi_context *hdata = connector_to_hdmi(connector);
d9716ee3 943
2b8376c8 944 return &hdata->encoder;
d9716ee3
SP
945}
946
800ba2b5 947static const struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
d9716ee3
SP
948 .get_modes = hdmi_get_modes,
949 .mode_valid = hdmi_mode_valid,
950 .best_encoder = hdmi_best_encoder,
951};
952
2b8376c8 953static int hdmi_create_connector(struct drm_encoder *encoder)
d9716ee3 954{
2b8376c8 955 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
d9716ee3
SP
956 struct drm_connector *connector = &hdata->connector;
957 int ret;
958
d9716ee3
SP
959 connector->interlace_allowed = true;
960 connector->polled = DRM_CONNECTOR_POLL_HPD;
961
962 ret = drm_connector_init(hdata->drm_dev, connector,
963 &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
964 if (ret) {
965 DRM_ERROR("Failed to initialize connector with drm\n");
6b986edf 966 return ret;
d9716ee3
SP
967 }
968
969 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
34ea3d38 970 drm_connector_register(connector);
2b8376c8 971 drm_mode_connector_attach_encoder(connector, encoder);
d9716ee3
SP
972
973 return 0;
974}
975
2b8376c8
GP
976static bool hdmi_mode_fixup(struct drm_encoder *encoder,
977 const struct drm_display_mode *mode,
978 struct drm_display_mode *adjusted_mode)
f041b257 979{
2b8376c8
GP
980 struct drm_device *dev = encoder->dev;
981 struct drm_connector *connector;
f041b257
SP
982 struct drm_display_mode *m;
983 int mode_ok;
984
f041b257
SP
985 drm_mode_set_crtcinfo(adjusted_mode, 0);
986
2b8376c8
GP
987 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
988 if (connector->encoder == encoder)
989 break;
990 }
991
992 if (connector->encoder != encoder)
993 return true;
994
d9716ee3 995 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
f041b257 996
d9716ee3 997 if (mode_ok == MODE_OK)
2b8376c8 998 return true;
f041b257
SP
999
1000 /*
5eefadb5 1001 * Find the most suitable mode and copy it to adjusted_mode.
f041b257
SP
1002 */
1003 list_for_each_entry(m, &connector->modes, head) {
d9716ee3 1004 mode_ok = hdmi_mode_valid(connector, m);
f041b257 1005
d9716ee3 1006 if (mode_ok == MODE_OK) {
f041b257
SP
1007 DRM_INFO("desired mode doesn't exist so\n");
1008 DRM_INFO("use the most suitable mode among modes.\n");
1009
1010 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
1011 m->hdisplay, m->vdisplay, m->vrefresh);
1012
75626853 1013 drm_mode_copy(adjusted_mode, m);
f041b257
SP
1014 break;
1015 }
1016 }
2b8376c8
GP
1017
1018 return true;
f041b257
SP
1019}
1020
d24bb3e5 1021static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq)
3e148baf
SWK
1022{
1023 u32 n, cts;
1024
d24bb3e5
AH
1025 cts = (freq % 9) ? 27000 : 30000;
1026 n = 128 * freq / (27000000 / cts);
3e148baf 1027
d24bb3e5
AH
1028 hdmi_reg_writev(hdata, HDMI_ACR_N0, 3, n);
1029 hdmi_reg_writev(hdata, HDMI_ACR_MCTS0, 3, cts);
1030 hdmi_reg_writev(hdata, HDMI_ACR_CTS0, 3, cts);
633d00b3 1031 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
3e148baf
SWK
1032}
1033
1034static void hdmi_audio_init(struct hdmi_context *hdata)
1035{
7a9bf6e5 1036 u32 sample_rate, bits_per_sample;
3e148baf
SWK
1037 u32 data_num, bit_ch, sample_frq;
1038 u32 val;
3e148baf
SWK
1039
1040 sample_rate = 44100;
1041 bits_per_sample = 16;
3e148baf
SWK
1042
1043 switch (bits_per_sample) {
1044 case 20:
1045 data_num = 2;
5eefadb5 1046 bit_ch = 1;
3e148baf
SWK
1047 break;
1048 case 24:
1049 data_num = 3;
5eefadb5 1050 bit_ch = 1;
3e148baf
SWK
1051 break;
1052 default:
1053 data_num = 1;
5eefadb5 1054 bit_ch = 0;
3e148baf
SWK
1055 break;
1056 }
1057
d24bb3e5 1058 hdmi_reg_acr(hdata, sample_rate);
3e148baf
SWK
1059
1060 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1061 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1062 | HDMI_I2S_MUX_ENABLE);
1063
1064 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1065 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1066
1067 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1068
1069 sample_frq = (sample_rate == 44100) ? 0 :
1070 (sample_rate == 48000) ? 2 :
1071 (sample_rate == 32000) ? 3 :
1072 (sample_rate == 96000) ? 0xa : 0x0;
1073
1074 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1075 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1076
1077 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1078 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1079
1080 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1081 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1082 | HDMI_I2S_SEL_LRCK(6));
1083 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1084 | HDMI_I2S_SEL_SDATA2(4));
1085 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1086 | HDMI_I2S_SEL_SDATA2(2));
1087 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1088
1089 /* I2S_CON_1 & 2 */
1090 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1091 | HDMI_I2S_L_CH_LOW_POL);
1092 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1093 | HDMI_I2S_SET_BIT_CH(bit_ch)
1094 | HDMI_I2S_SET_SDATA_BIT(data_num)
1095 | HDMI_I2S_BASIC_FORMAT);
1096
1097 /* Configure register related to CUV information */
1098 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1099 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1100 | HDMI_I2S_COPYRIGHT
1101 | HDMI_I2S_LINEAR_PCM
1102 | HDMI_I2S_CONSUMER_FORMAT);
1103 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1104 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1105 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1106 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1107 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1108 HDMI_I2S_ORG_SMP_FREQ_44_1
1109 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1110 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1111
1112 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1113}
1114
1115static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1116{
872d20d6 1117 if (hdata->dvi_mode)
3e148baf
SWK
1118 return;
1119
1120 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1121 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1122 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1123}
1124
bfa48423 1125static void hdmi_start(struct hdmi_context *hdata, bool start)
d8408326 1126{
bfa48423 1127 u32 val = start ? HDMI_TG_EN : 0;
3ecd70b1 1128
bfa48423
RS
1129 if (hdata->current_mode.flags & DRM_MODE_FLAG_INTERLACE)
1130 val |= HDMI_FIELD_EN;
3ecd70b1 1131
bfa48423
RS
1132 hdmi_reg_writemask(hdata, HDMI_CON_0, val, HDMI_EN);
1133 hdmi_reg_writemask(hdata, HDMI_TG_CMD, val, HDMI_TG_EN | HDMI_FIELD_EN);
d8408326
SWK
1134}
1135
1136static void hdmi_conf_init(struct hdmi_context *hdata)
1137{
d34d59bd 1138 union hdmi_infoframe infoframe;
a144c2e9 1139
77006a7a 1140 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
d8408326
SWK
1141 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1142 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
d8408326
SWK
1143
1144 /* choose HDMI mode */
1145 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1146 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
5eefadb5 1147 /* apply video pre-amble and guard band in HDMI mode only */
9a8e1cb0 1148 hdmi_reg_writeb(hdata, HDMI_CON_2, 0);
d8408326
SWK
1149 /* disable bluescreen */
1150 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
3ecd70b1 1151
872d20d6 1152 if (hdata->dvi_mode) {
872d20d6
SWK
1153 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1154 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1155 hdmi_reg_writeb(hdata, HDMI_CON_2,
1156 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1157 }
1158
cd240cde 1159 if (hdata->drv_data->type == HDMI_TYPE13) {
3ecd70b1
JS
1160 /* choose bluescreen (fecal) color */
1161 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1162 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1163 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1164
1165 /* enable AVI packet every vsync, fixes purple line problem */
1166 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1167 /* force RGB, look to CEA-861-D, table 7 for more detail */
1168 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1169 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1170
1171 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1172 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1173 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1174 } else {
d34d59bd
SK
1175 infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
1176 infoframe.any.version = HDMI_AVI_VERSION;
1177 infoframe.any.length = HDMI_AVI_LENGTH;
a144c2e9
RS
1178 hdmi_reg_infoframe(hdata, &infoframe);
1179
d34d59bd
SK
1180 infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
1181 infoframe.any.version = HDMI_AUI_VERSION;
1182 infoframe.any.length = HDMI_AUI_LENGTH;
a144c2e9
RS
1183 hdmi_reg_infoframe(hdata, &infoframe);
1184
3ecd70b1 1185 /* enable AVI packet every vsync, fixes purple line problem */
3ecd70b1
JS
1186 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1187 }
d8408326
SWK
1188}
1189
8eb6d4ec
AH
1190static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
1191{
1192 int tries;
1193
1194 for (tries = 0; tries < 10; ++tries) {
1195 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
1196
1197 if (val & HDMI_PHY_STATUS_READY) {
1198 DRM_DEBUG_KMS("PLL stabilized after %d tries\n", tries);
1199 return;
1200 }
1201 usleep_range(10, 20);
1202 }
1203
1204 DRM_ERROR("PLL could not reach steady state\n");
1205}
1206
16844fb1 1207static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
d8408326 1208{
edb6e412
AH
1209 struct drm_display_mode *m = &hdata->current_mode;
1210 unsigned int val;
3ecd70b1 1211
edb6e412
AH
1212 hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1213 hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
1214 (m->htotal << 12) | m->vtotal);
1215
1216 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1217 hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, val);
1218
1219 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1220 hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, val);
1221
1222 val = (m->hsync_start - m->hdisplay - 2);
1223 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
5eefadb5 1224 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
edb6e412
AH
1225 hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val);
1226
1227 /*
1228 * Quirk requirement for exynos HDMI IP design,
1229 * 2 pixels less than the actual calculation for hsync_start
1230 * and end.
1231 */
1232
1233 /* Following values & calculations differ for different type of modes */
1234 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
edb6e412
AH
1235 val = ((m->vsync_end - m->vdisplay) / 2);
1236 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1237 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1238
1239 val = m->vtotal / 2;
1240 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1241 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1242
1243 val = (m->vtotal +
1244 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1245 val |= m->vtotal << 11;
1246 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, val);
1247
1248 val = ((m->vtotal / 2) + 7);
1249 val |= ((m->vtotal / 2) + 2) << 12;
1250 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, val);
1251
1252 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1253 val |= ((m->htotal / 2) +
1254 (m->hsync_start - m->hdisplay)) << 12;
1255 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, val);
1256
1257 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1258 (m->vtotal - m->vdisplay) / 2);
1259 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1260
1261 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249);
1262 } else {
edb6e412
AH
1263 val = m->vtotal;
1264 val |= (m->vtotal - m->vdisplay) << 11;
1265 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1266
1267 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, 0);
1268
1269 val = (m->vsync_end - m->vdisplay);
1270 val |= ((m->vsync_start - m->vdisplay) << 12);
1271 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1272
1273 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, 0x1001);
1274 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, 0x1001);
1275 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1276 m->vtotal - m->vdisplay);
1277 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
edb6e412
AH
1278 }
1279
edb6e412
AH
1280 hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1281 hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1282 hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1283 hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
3ecd70b1
JS
1284}
1285
16844fb1 1286static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
3ecd70b1 1287{
7b5102da 1288 struct drm_display_mode *m = &hdata->current_mode;
d8408326 1289
7b5102da
AH
1290 hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1291 hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
1292 hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal);
1293 hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1,
5eefadb5 1294 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
7b5102da
AH
1295 hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1,
1296 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1297 hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1,
1298 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1299
1300 /*
1301 * Quirk requirement for exynos 5 HDMI IP design,
1302 * 2 pixels less than the actual calculation for hsync_start
1303 * and end.
1304 */
1305
1306 /* Following values & calculations differ for different type of modes */
1307 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
7b5102da
AH
1308 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1309 (m->vsync_end - m->vdisplay) / 2);
1310 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1311 (m->vsync_start - m->vdisplay) / 2);
1312 hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal / 2);
1313 hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1314 (m->vtotal - m->vdisplay) / 2);
1315 hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2,
1316 m->vtotal - m->vdisplay / 2);
1317 hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, m->vtotal);
1318 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2,
1319 (m->vtotal / 2) + 7);
1320 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2,
1321 (m->vtotal / 2) + 2);
1322 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2,
1323 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1324 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2,
1325 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1326 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1327 (m->vtotal - m->vdisplay) / 2);
1328 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1329 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2,
1330 m->vtotal - m->vdisplay / 2);
1331 hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2,
1332 (m->vtotal / 2) + 1);
1333 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2,
1334 (m->vtotal / 2) + 1);
1335 hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2,
1336 (m->vtotal / 2) + 1);
1337 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0);
1338 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0);
1339 } else {
7b5102da
AH
1340 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1341 m->vsync_end - m->vdisplay);
1342 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1343 m->vsync_start - m->vdisplay);
1344 hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal);
1345 hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1346 m->vtotal - m->vdisplay);
1347 hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2, 0xffff);
1348 hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, 0xffff);
1349 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2, 0xffff);
1350 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2, 0xffff);
1351 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2, 0xffff);
1352 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2, 0xffff);
1353 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1354 m->vtotal - m->vdisplay);
1355 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
7b5102da
AH
1356 }
1357
7b5102da
AH
1358 hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2,
1359 m->hsync_start - m->hdisplay - 2);
1360 hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2,
1361 m->hsync_end - m->hdisplay - 2);
1362 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_1_0, 2, 0xffff);
1363 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_2_0, 2, 0xffff);
1364 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_3_0, 2, 0xffff);
1365 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_4_0, 2, 0xffff);
1366 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_5_0, 2, 0xffff);
1367 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_6_0, 2, 0xffff);
1368 hdmi_reg_writev(hdata, HDMI_V_BLANK_F2_0, 2, 0xffff);
1369 hdmi_reg_writev(hdata, HDMI_V_BLANK_F3_0, 2, 0xffff);
1370 hdmi_reg_writev(hdata, HDMI_V_BLANK_F4_0, 2, 0xffff);
1371 hdmi_reg_writev(hdata, HDMI_V_BLANK_F5_0, 2, 0xffff);
1372 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_3_0, 2, 0xffff);
1373 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_4_0, 2, 0xffff);
1374 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_5_0, 2, 0xffff);
1375 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_6_0, 2, 0xffff);
1376 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, 2, 0xffff);
1377 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, 2, 0xffff);
1378 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff);
1379 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff);
3ecd70b1 1380
7b5102da
AH
1381 hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1382 hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1383 hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1384 hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
68cd004e
AH
1385 if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1386 hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1);
d8408326
SWK
1387}
1388
16844fb1 1389static void hdmi_mode_apply(struct hdmi_context *hdata)
3ecd70b1 1390{
cd240cde 1391 if (hdata->drv_data->type == HDMI_TYPE13)
16844fb1 1392 hdmi_v13_mode_apply(hdata);
3ecd70b1 1393 else
16844fb1 1394 hdmi_v14_mode_apply(hdata);
8eb6d4ec 1395
8eb6d4ec 1396 hdmi_start(hdata, true);
3ecd70b1
JS
1397}
1398
d8408326
SWK
1399static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1400{
69f88877
AH
1401 hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, 0, 1);
1402 usleep_range(10000, 12000);
1403 hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, ~0, 1);
1404 usleep_range(10000, 12000);
633d00b3 1405 hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
09760ea3 1406 usleep_range(10000, 12000);
5eefadb5 1407 hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
09760ea3 1408 usleep_range(10000, 12000);
d8408326
SWK
1409}
1410
68cd004e
AH
1411static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable)
1412{
1413 u8 v = enable ? HDMI_PHY_ENABLE_MODE_SET : HDMI_PHY_DISABLE_MODE_SET;
1414
1415 if (hdata->drv_data == &exynos5433_hdmi_driver_data)
1416 writel(v, hdata->regs_hdmiphy + HDMIPHY5433_MODE_SET_DONE);
1417}
1418
d8408326
SWK
1419static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1420{
d8408326 1421 int ret;
4677f51a 1422 const u8 *phy_conf;
d8408326 1423
4677f51a
AH
1424 ret = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000);
1425 if (ret < 0) {
6b986edf
RS
1426 DRM_ERROR("failed to find hdmiphy conf\n");
1427 return;
1428 }
4677f51a
AH
1429 phy_conf = hdata->drv_data->phy_confs.data[ret].conf;
1430
1431 hdmi_clk_set_parents(hdata, false);
1432
1433 hdmiphy_conf_reset(hdata);
6b986edf 1434
68cd004e 1435 hdmiphy_enable_mode_set(hdata, true);
4677f51a 1436 ret = hdmiphy_reg_write_buf(hdata, 0, phy_conf, 32);
d5e9ca4c
RS
1437 if (ret) {
1438 DRM_ERROR("failed to configure hdmiphy\n");
d8408326
SWK
1439 return;
1440 }
68cd004e 1441 hdmiphy_enable_mode_set(hdata, false);
4677f51a 1442 hdmi_clk_set_parents(hdata, true);
09760ea3 1443 usleep_range(10000, 12000);
4677f51a 1444 hdmiphy_wait_for_pll(hdata);
d8408326
SWK
1445}
1446
1447static void hdmi_conf_apply(struct hdmi_context *hdata)
1448{
bfa48423 1449 hdmi_start(hdata, false);
d8408326 1450 hdmi_conf_init(hdata);
3e148baf 1451 hdmi_audio_init(hdata);
16844fb1 1452 hdmi_mode_apply(hdata);
3e148baf 1453 hdmi_audio_control(hdata, true);
d8408326
SWK
1454}
1455
2b8376c8
GP
1456static void hdmi_mode_set(struct drm_encoder *encoder,
1457 struct drm_display_mode *mode,
1458 struct drm_display_mode *adjusted_mode)
d8408326 1459{
cf67cc9a 1460 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
2b8376c8 1461 struct drm_display_mode *m = adjusted_mode;
d8408326 1462
cbc4c33d
YC
1463 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1464 m->hdisplay, m->vdisplay,
6b986edf 1465 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1e6d459d 1466 "INTERLACED" : "PROGRESSIVE");
d8408326 1467
2b8376c8 1468 drm_mode_copy(&hdata->current_mode, m);
c93aaebf 1469 hdata->cea_video_id = drm_match_cea_mode(mode);
d8408326
SWK
1470}
1471
68cd004e
AH
1472static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
1473{
1474 if (!hdata->sysreg)
1475 return;
1476
1477 regmap_update_bits(hdata->sysreg, EXYNOS5433_SYSREG_DISP_HDMI_PHY,
1478 SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0);
1479}
1480
59b62d3c 1481static void hdmiphy_enable(struct hdmi_context *hdata)
cf8fc4f1 1482{
882a0644 1483 if (hdata->powered)
cf8fc4f1 1484 return;
d8408326 1485
af65c804
SP
1486 pm_runtime_get_sync(hdata->dev);
1487
af1f7c24 1488 if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
ad07945a
SWK
1489 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1490
049d34e9
RS
1491 regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1492 PMU_HDMI_PHY_ENABLE_BIT, 1);
1493
68cd004e
AH
1494 hdmi_set_refclk(hdata, true);
1495
5dd45e2c
AH
1496 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN);
1497
59b62d3c 1498 hdmiphy_conf_apply(hdata);
f28464c3
GP
1499
1500 hdata->powered = true;
cf8fc4f1
JS
1501}
1502
59b62d3c
AH
1503static void hdmiphy_disable(struct hdmi_context *hdata)
1504{
1505 if (!hdata->powered)
1506 return;
1507
1508 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
1509
1510 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN);
1511
1512 hdmi_set_refclk(hdata, false);
1513
1514 regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1515 PMU_HDMI_PHY_ENABLE_BIT, 0);
1516
1517 regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk);
1518
1519 pm_runtime_put_sync(hdata->dev);
1520
1521 hdata->powered = false;
1522}
1523
1524static void hdmi_enable(struct drm_encoder *encoder)
1525{
1526 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
1527
1528 hdmiphy_enable(hdata);
1529 hdmi_conf_apply(hdata);
1530}
1531
2b8376c8 1532static void hdmi_disable(struct drm_encoder *encoder)
cf8fc4f1 1533{
cf67cc9a 1534 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
2b8376c8 1535 struct drm_crtc *crtc = encoder->crtc;
b6595dc7 1536 const struct drm_crtc_helper_funcs *funcs = NULL;
cf8fc4f1 1537
cf8fc4f1 1538 if (!hdata->powered)
882a0644 1539 return;
cf8fc4f1 1540
b6595dc7
GP
1541 /*
1542 * The SFRs of VP and Mixer are updated by Vertical Sync of
1543 * Timing generator which is a part of HDMI so the sequence
1544 * to disable TV Subsystem should be as following,
1545 * VP -> Mixer -> HDMI
1546 *
1547 * Below codes will try to disable Mixer and VP(if used)
1548 * prior to disabling HDMI.
1549 */
1550 if (crtc)
1551 funcs = crtc->helper_private;
1552 if (funcs && funcs->disable)
1553 (*funcs->disable)(crtc);
1554
724fd140
SP
1555 cancel_delayed_work(&hdata->hotplug_work);
1556
59b62d3c 1557 hdmiphy_disable(hdata);
d8408326
SWK
1558}
1559
800ba2b5 1560static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
f041b257 1561 .mode_fixup = hdmi_mode_fixup,
d8408326 1562 .mode_set = hdmi_mode_set,
b6595dc7
GP
1563 .enable = hdmi_enable,
1564 .disable = hdmi_disable,
d8408326
SWK
1565};
1566
800ba2b5 1567static const struct drm_encoder_funcs exynos_hdmi_encoder_funcs = {
2b8376c8
GP
1568 .destroy = drm_encoder_cleanup,
1569};
1570
724fd140 1571static void hdmi_hotplug_work_func(struct work_struct *work)
cf8fc4f1 1572{
724fd140
SP
1573 struct hdmi_context *hdata;
1574
1575 hdata = container_of(work, struct hdmi_context, hotplug_work.work);
cf8fc4f1 1576
4551789f
SP
1577 if (hdata->drm_dev)
1578 drm_helper_hpd_irq_event(hdata->drm_dev);
724fd140
SP
1579}
1580
1581static irqreturn_t hdmi_irq_thread(int irq, void *arg)
1582{
1583 struct hdmi_context *hdata = arg;
1584
1585 mod_delayed_work(system_wq, &hdata->hotplug_work,
1586 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
cf8fc4f1 1587
cf8fc4f1
JS
1588 return IRQ_HANDLED;
1589}
1590
9be7e989
AH
1591static int hdmi_clks_get(struct hdmi_context *hdata,
1592 const struct string_array_spec *names,
1593 struct clk **clks)
1594{
1595 struct device *dev = hdata->dev;
1596 int i;
1597
1598 for (i = 0; i < names->count; ++i) {
1599 struct clk *clk = devm_clk_get(dev, names->data[i]);
1600
1601 if (IS_ERR(clk)) {
1602 int ret = PTR_ERR(clk);
1603
1604 dev_err(dev, "Cannot get clock %s, %d\n",
1605 names->data[i], ret);
1606
1607 return ret;
1608 }
1609
1610 clks[i] = clk;
1611 }
1612
1613 return 0;
1614}
1615
1616static int hdmi_clk_init(struct hdmi_context *hdata)
1617{
1618 const struct hdmi_driver_data *drv_data = hdata->drv_data;
1619 int count = drv_data->clk_gates.count + drv_data->clk_muxes.count;
1620 struct device *dev = hdata->dev;
1621 struct clk **clks;
1622 int ret;
1623
1624 if (!count)
1625 return 0;
1626
1627 clks = devm_kzalloc(dev, sizeof(*clks) * count, GFP_KERNEL);
1628 if (!clks)
f9628c2a 1629 return -ENOMEM;
9be7e989
AH
1630
1631 hdata->clk_gates = clks;
1632 hdata->clk_muxes = clks + drv_data->clk_gates.count;
1633
1634 ret = hdmi_clks_get(hdata, &drv_data->clk_gates, hdata->clk_gates);
1635 if (ret)
1636 return ret;
1637
1638 return hdmi_clks_get(hdata, &drv_data->clk_muxes, hdata->clk_muxes);
1639}
1640
1641
59b62d3c
AH
1642static void hdmiphy_clk_enable(struct exynos_drm_clk *clk, bool enable)
1643{
1644 struct hdmi_context *hdata = container_of(clk, struct hdmi_context,
1645 phy_clk);
1646
1647 if (enable)
1648 hdmiphy_enable(hdata);
1649 else
1650 hdmiphy_disable(hdata);
1651}
1652
56550d94 1653static int hdmi_resources_init(struct hdmi_context *hdata)
d8408326
SWK
1654{
1655 struct device *dev = hdata->dev;
d8408326
SWK
1656 int i, ret;
1657
1658 DRM_DEBUG_KMS("HDMI resource init\n");
1659
2228b7cd
AH
1660 hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
1661 if (IS_ERR(hdata->hpd_gpio)) {
1662 DRM_ERROR("cannot get hpd gpio property\n");
1663 return PTR_ERR(hdata->hpd_gpio);
1664 }
1665
1666 hdata->irq = gpiod_to_irq(hdata->hpd_gpio);
1667 if (hdata->irq < 0) {
1668 DRM_ERROR("failed to get GPIO irq\n");
1669 return hdata->irq;
1670 }
d8408326 1671
9be7e989
AH
1672 ret = hdmi_clk_init(hdata);
1673 if (ret)
1674 return ret;
1675
1676 ret = hdmi_clk_set_parents(hdata, false);
1677 if (ret)
1678 return ret;
d8408326 1679
d8408326 1680 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
af1f7c24
AH
1681 hdata->regul_bulk[i].supply = supply[i];
1682 hdata->regul_bulk[i].consumer = NULL;
d8408326 1683 }
af1f7c24 1684 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk);
d8408326 1685 if (ret) {
b85881dd
JMC
1686 if (ret != -EPROBE_DEFER)
1687 DRM_ERROR("failed to get regulators\n");
df5225bc 1688 return ret;
d8408326 1689 }
d8408326 1690
af1f7c24 1691 hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
498d5a37 1692
af1f7c24 1693 if (PTR_ERR(hdata->reg_hdmi_en) == -ENODEV)
498d5a37
AH
1694 return 0;
1695
af1f7c24
AH
1696 if (IS_ERR(hdata->reg_hdmi_en))
1697 return PTR_ERR(hdata->reg_hdmi_en);
498d5a37 1698
af1f7c24 1699 ret = regulator_enable(hdata->reg_hdmi_en);
498d5a37
AH
1700 if (ret)
1701 DRM_ERROR("failed to enable hdmi-en regulator\n");
05fdf987 1702
df5225bc 1703 return ret;
d8408326
SWK
1704}
1705
22c4f428
RS
1706static struct of_device_id hdmi_match_types[] = {
1707 {
ff830c96
MS
1708 .compatible = "samsung,exynos4210-hdmi",
1709 .data = &exynos4210_hdmi_driver_data,
cc57caf0
RS
1710 }, {
1711 .compatible = "samsung,exynos4212-hdmi",
bfe4e84c 1712 .data = &exynos4212_hdmi_driver_data,
a18a2dda
RS
1713 }, {
1714 .compatible = "samsung,exynos5420-hdmi",
1715 .data = &exynos5420_hdmi_driver_data,
68cd004e
AH
1716 }, {
1717 .compatible = "samsung,exynos5433-hdmi",
1718 .data = &exynos5433_hdmi_driver_data,
c119ed05
TS
1719 }, {
1720 /* end node */
1721 }
1722};
39b58a39 1723MODULE_DEVICE_TABLE (of, hdmi_match_types);
c119ed05 1724
f37cd5e8
ID
1725static int hdmi_bind(struct device *dev, struct device *master, void *data)
1726{
1727 struct drm_device *drm_dev = data;
930865fb 1728 struct hdmi_context *hdata = dev_get_drvdata(dev);
2b8376c8
GP
1729 struct drm_encoder *encoder = &hdata->encoder;
1730 int ret, pipe;
f37cd5e8 1731
f37cd5e8
ID
1732 hdata->drm_dev = drm_dev;
1733
2b8376c8
GP
1734 pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
1735 EXYNOS_DISPLAY_TYPE_HDMI);
1736 if (pipe < 0)
1737 return pipe;
1738
59b62d3c
AH
1739 hdata->phy_clk.enable = hdmiphy_clk_enable;
1740
1741 exynos_drm_crtc_from_pipe(drm_dev, pipe)->pipe_clk = &hdata->phy_clk;
1742
2b8376c8
GP
1743 encoder->possible_crtcs = 1 << pipe;
1744
1745 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
1746
1747 drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
13a3d91f 1748 DRM_MODE_ENCODER_TMDS, NULL);
2b8376c8
GP
1749
1750 drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
a2986e80 1751
2b8376c8 1752 ret = hdmi_create_connector(encoder);
a2986e80
GP
1753 if (ret) {
1754 DRM_ERROR("failed to create connector ret = %d\n", ret);
2b8376c8 1755 drm_encoder_cleanup(encoder);
a2986e80
GP
1756 return ret;
1757 }
1758
1759 return 0;
f37cd5e8
ID
1760}
1761
1762static void hdmi_unbind(struct device *dev, struct device *master, void *data)
1763{
f37cd5e8
ID
1764}
1765
1766static const struct component_ops hdmi_component_ops = {
1767 .bind = hdmi_bind,
1768 .unbind = hdmi_unbind,
1769};
1770
e2a562dc
ID
1771static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev)
1772{
1773 const char *compatible_str = "samsung,exynos4210-hdmiddc";
1774 struct device_node *np;
1775
1776 np = of_find_compatible_node(NULL, NULL, compatible_str);
1777 if (np)
1778 return of_get_next_parent(np);
1779
1780 return NULL;
1781}
1782
1783static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
1784{
1785 const char *compatible_str = "samsung,exynos4212-hdmiphy";
1786
1787 return of_find_compatible_node(NULL, NULL, compatible_str);
1788}
1789
56550d94 1790static int hdmi_probe(struct platform_device *pdev)
d8408326 1791{
f37cd5e8 1792 struct device_node *ddc_node, *phy_node;
d8408326 1793 struct device *dev = &pdev->dev;
d8408326 1794 struct hdmi_context *hdata;
d8408326
SWK
1795 struct resource *res;
1796 int ret;
1797
88c49815 1798 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
930865fb
AH
1799 if (!hdata)
1800 return -ENOMEM;
1801
57a64122 1802 hdata->drv_data = of_device_get_match_data(dev);
930865fb 1803
930865fb 1804 platform_set_drvdata(pdev, hdata);
d8408326 1805
d8408326
SWK
1806 hdata->dev = dev;
1807
1808 ret = hdmi_resources_init(hdata);
1809 if (ret) {
b85881dd
JMC
1810 if (ret != -EPROBE_DEFER)
1811 DRM_ERROR("hdmi_resources_init failed\n");
df5225bc 1812 return ret;
d8408326
SWK
1813 }
1814
1815 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
d873ab99 1816 hdata->regs = devm_ioremap_resource(dev, res);
df5225bc
ID
1817 if (IS_ERR(hdata->regs)) {
1818 ret = PTR_ERR(hdata->regs);
86650408 1819 return ret;
df5225bc 1820 }
d8408326 1821
e2a562dc
ID
1822 ddc_node = hdmi_legacy_ddc_dt_binding(dev);
1823 if (ddc_node)
1824 goto out_get_ddc_adpt;
1825
2b768132
DK
1826 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
1827 if (!ddc_node) {
1828 DRM_ERROR("Failed to find ddc node in device tree\n");
86650408 1829 return -ENODEV;
2b768132 1830 }
e2a562dc
ID
1831
1832out_get_ddc_adpt:
8fa04aae
ID
1833 hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
1834 if (!hdata->ddc_adpt) {
1835 DRM_ERROR("Failed to get ddc i2c adapter by node\n");
df5225bc 1836 return -EPROBE_DEFER;
d8408326 1837 }
d8408326 1838
e2a562dc
ID
1839 phy_node = hdmi_legacy_phy_dt_binding(dev);
1840 if (phy_node)
1841 goto out_get_phy_port;
1842
2b768132
DK
1843 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
1844 if (!phy_node) {
1845 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
1846 ret = -ENODEV;
1847 goto err_ddc;
1848 }
d5e9ca4c 1849
e2a562dc 1850out_get_phy_port:
cd240cde 1851 if (hdata->drv_data->is_apb_phy) {
d5e9ca4c
RS
1852 hdata->regs_hdmiphy = of_iomap(phy_node, 0);
1853 if (!hdata->regs_hdmiphy) {
1854 DRM_ERROR("failed to ioremap hdmi phy\n");
1855 ret = -ENOMEM;
1856 goto err_ddc;
1857 }
1858 } else {
1859 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
1860 if (!hdata->hdmiphy_port) {
1861 DRM_ERROR("Failed to get hdmi phy i2c client\n");
df5225bc 1862 ret = -EPROBE_DEFER;
d5e9ca4c
RS
1863 goto err_ddc;
1864 }
d8408326 1865 }
d8408326 1866
724fd140
SP
1867 INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
1868
dcb9a7c7 1869 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
77006a7a 1870 hdmi_irq_thread, IRQF_TRIGGER_RISING |
cf8fc4f1 1871 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
f041b257 1872 "hdmi", hdata);
d8408326 1873 if (ret) {
77006a7a 1874 DRM_ERROR("failed to register hdmi interrupt\n");
66265a2e 1875 goto err_hdmiphy;
d8408326 1876 }
d8408326 1877
049d34e9
RS
1878 hdata->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
1879 "samsung,syscon-phandle");
1880 if (IS_ERR(hdata->pmureg)) {
1881 DRM_ERROR("syscon regmap lookup failed.\n");
df5225bc 1882 ret = -EPROBE_DEFER;
049d34e9
RS
1883 goto err_hdmiphy;
1884 }
1885
68cd004e
AH
1886 if (hdata->drv_data->has_sysreg) {
1887 hdata->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1888 "samsung,sysreg-phandle");
1889 if (IS_ERR(hdata->sysreg)) {
1890 DRM_ERROR("sysreg regmap lookup failed.\n");
1891 ret = -EPROBE_DEFER;
1892 goto err_hdmiphy;
1893 }
1894 }
1895
af65c804 1896 pm_runtime_enable(dev);
d8408326 1897
df5225bc
ID
1898 ret = component_add(&pdev->dev, &hdmi_component_ops);
1899 if (ret)
1900 goto err_disable_pm_runtime;
1901
1902 return ret;
1903
1904err_disable_pm_runtime:
1905 pm_runtime_disable(dev);
d8408326 1906
d8408326 1907err_hdmiphy:
b21a3bf4
PT
1908 if (hdata->hdmiphy_port)
1909 put_device(&hdata->hdmiphy_port->dev);
d8408326 1910err_ddc:
8fa04aae 1911 put_device(&hdata->ddc_adpt->dev);
df5225bc 1912
d8408326
SWK
1913 return ret;
1914}
1915
56550d94 1916static int hdmi_remove(struct platform_device *pdev)
d8408326 1917{
930865fb 1918 struct hdmi_context *hdata = platform_get_drvdata(pdev);
d8408326 1919
724fd140
SP
1920 cancel_delayed_work_sync(&hdata->hotplug_work);
1921
2445c4a4
AH
1922 component_del(&pdev->dev, &hdmi_component_ops);
1923
1924 pm_runtime_disable(&pdev->dev);
1925
af1f7c24
AH
1926 if (!IS_ERR(hdata->reg_hdmi_en))
1927 regulator_disable(hdata->reg_hdmi_en);
05fdf987 1928
9d1e25c9
SWK
1929 if (hdata->hdmiphy_port)
1930 put_device(&hdata->hdmiphy_port->dev);
f37cd5e8 1931
2445c4a4 1932 put_device(&hdata->ddc_adpt->dev);
d8408326 1933
d8408326
SWK
1934 return 0;
1935}
1936
f28464c3
GP
1937#ifdef CONFIG_PM
1938static int exynos_hdmi_suspend(struct device *dev)
1939{
1940 struct hdmi_context *hdata = dev_get_drvdata(dev);
1941
9be7e989 1942 hdmi_clk_disable_gates(hdata);
f28464c3
GP
1943
1944 return 0;
1945}
1946
1947static int exynos_hdmi_resume(struct device *dev)
1948{
1949 struct hdmi_context *hdata = dev_get_drvdata(dev);
1950 int ret;
1951
9be7e989
AH
1952 ret = hdmi_clk_enable_gates(hdata);
1953 if (ret < 0)
f28464c3 1954 return ret;
f28464c3
GP
1955
1956 return 0;
1957}
1958#endif
1959
1960static const struct dev_pm_ops exynos_hdmi_pm_ops = {
1961 SET_RUNTIME_PM_OPS(exynos_hdmi_suspend, exynos_hdmi_resume, NULL)
1962};
1963
d8408326
SWK
1964struct platform_driver hdmi_driver = {
1965 .probe = hdmi_probe,
56550d94 1966 .remove = hdmi_remove,
d8408326 1967 .driver = {
22c4f428 1968 .name = "exynos-hdmi",
d8408326 1969 .owner = THIS_MODULE,
f28464c3 1970 .pm = &exynos_hdmi_pm_ops,
88c49815 1971 .of_match_table = hdmi_match_types,
d8408326
SWK
1972 },
1973};
This page took 0.505672 seconds and 5 git commands to generate.