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