drm/exynos/hdmi: replace all writeb with writel
[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>
33#include <linux/regulator/consumer.h>
22c4f428 34#include <linux/io.h>
d5e9ca4c 35#include <linux/of_address.h>
cd240cde 36#include <linux/of_device.h>
22c4f428 37#include <linux/of_gpio.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"
f041b257 47#include "exynos_mixer.h"
d8408326 48
fca57122 49#include <linux/gpio.h>
fca57122 50
d9716ee3 51#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
d8408326 52
724fd140
SP
53#define HOTPLUG_DEBOUNCE_MS 1100
54
a144c2e9
RS
55/* AVI header and aspect ratio */
56#define HDMI_AVI_VERSION 0x02
57#define HDMI_AVI_LENGTH 0x0D
a144c2e9
RS
58
59/* AUI header info */
60#define HDMI_AUI_VERSION 0x01
61#define HDMI_AUI_LENGTH 0x0A
46154152
S
62#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
63#define AVI_4_3_CENTER_RATIO 0x9
64#define AVI_16_9_CENTER_RATIO 0xa
a144c2e9 65
5a325071
RS
66enum hdmi_type {
67 HDMI_TYPE13,
68 HDMI_TYPE14,
633d00b3
AH
69 HDMI_TYPE_COUNT
70};
71
72#define HDMI_MAPPED_BASE 0xffff0000
73
74enum hdmi_mapped_regs {
75 HDMI_PHY_STATUS = HDMI_MAPPED_BASE,
76 HDMI_PHY_RSTOUT,
77 HDMI_ACR_CON,
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 },
5a325071
RS
84};
85
bfe4e84c
ID
86struct hdmi_driver_data {
87 unsigned int type;
d5e9ca4c
RS
88 const struct hdmiphy_config *phy_confs;
89 unsigned int phy_conf_count;
bfe4e84c
ID
90 unsigned int is_apb_phy:1;
91};
92
590f418a
JS
93struct hdmi_resources {
94 struct clk *hdmi;
95 struct clk *sclk_hdmi;
96 struct clk *sclk_pixel;
97 struct clk *sclk_hdmiphy;
59956d35 98 struct clk *mout_hdmi;
590f418a 99 struct regulator_bulk_data *regul_bulk;
05fdf987 100 struct regulator *reg_hdmi_en;
590f418a
JS
101 int regul_count;
102};
103
104struct hdmi_context {
2b8376c8 105 struct drm_encoder encoder;
590f418a
JS
106 struct device *dev;
107 struct drm_device *drm_dev;
d9716ee3 108 struct drm_connector connector;
cf67cc9a 109 bool hpd;
cf8fc4f1 110 bool powered;
872d20d6 111 bool dvi_mode;
590f418a 112
590f418a 113 void __iomem *regs;
77006a7a 114 int irq;
724fd140 115 struct delayed_work hotplug_work;
590f418a 116
8fa04aae 117 struct i2c_adapter *ddc_adpt;
590f418a
JS
118 struct i2c_client *hdmiphy_port;
119
6b986edf 120 /* current hdmiphy conf regs */
bfa48423 121 struct drm_display_mode current_mode;
c93aaebf 122 u8 cea_video_id;
590f418a
JS
123
124 struct hdmi_resources res;
cd240cde 125 const struct hdmi_driver_data *drv_data;
7ecd34e8 126
fca57122 127 int hpd_gpio;
d5e9ca4c 128 void __iomem *regs_hdmiphy;
5a325071 129
049d34e9 130 struct regmap *pmureg;
590f418a
JS
131};
132
2b8376c8 133static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
0d8424f8 134{
cf67cc9a 135 return container_of(e, struct hdmi_context, encoder);
0d8424f8
AH
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{
d9716ee3 945 struct hdmi_context *hdata = ctx_from_connector(connector);
4551789f 946
ef6ce28b
AH
947 if (gpio_get_value(hdata->hpd_gpio))
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
d9716ee3 959static 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{
d9716ee3
SP
971 struct hdmi_context *hdata = ctx_from_connector(connector);
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{
d9716ee3 1011 struct hdmi_context *hdata = ctx_from_connector(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
f041b257
SP
1019 ret = mixer_check_mode(mode);
1020 if (ret)
d9716ee3 1021 return MODE_BAD;
f041b257 1022
16844fb1 1023 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
6b986edf 1024 if (ret < 0)
d9716ee3
SP
1025 return MODE_BAD;
1026
1027 return MODE_OK;
1028}
1029
1030static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
1031{
1032 struct hdmi_context *hdata = ctx_from_connector(connector);
1033
2b8376c8 1034 return &hdata->encoder;
d9716ee3
SP
1035}
1036
1037static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
1038 .get_modes = hdmi_get_modes,
1039 .mode_valid = hdmi_mode_valid,
1040 .best_encoder = hdmi_best_encoder,
1041};
1042
2b8376c8 1043static int hdmi_create_connector(struct drm_encoder *encoder)
d9716ee3 1044{
2b8376c8 1045 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
d9716ee3
SP
1046 struct drm_connector *connector = &hdata->connector;
1047 int ret;
1048
d9716ee3
SP
1049 connector->interlace_allowed = true;
1050 connector->polled = DRM_CONNECTOR_POLL_HPD;
1051
1052 ret = drm_connector_init(hdata->drm_dev, connector,
1053 &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
1054 if (ret) {
1055 DRM_ERROR("Failed to initialize connector with drm\n");
6b986edf 1056 return ret;
d9716ee3
SP
1057 }
1058
1059 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
34ea3d38 1060 drm_connector_register(connector);
2b8376c8 1061 drm_mode_connector_attach_encoder(connector, encoder);
d9716ee3
SP
1062
1063 return 0;
1064}
1065
2b8376c8
GP
1066static bool hdmi_mode_fixup(struct drm_encoder *encoder,
1067 const struct drm_display_mode *mode,
1068 struct drm_display_mode *adjusted_mode)
f041b257 1069{
2b8376c8
GP
1070 struct drm_device *dev = encoder->dev;
1071 struct drm_connector *connector;
f041b257
SP
1072 struct drm_display_mode *m;
1073 int mode_ok;
1074
f041b257
SP
1075 drm_mode_set_crtcinfo(adjusted_mode, 0);
1076
2b8376c8
GP
1077 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1078 if (connector->encoder == encoder)
1079 break;
1080 }
1081
1082 if (connector->encoder != encoder)
1083 return true;
1084
d9716ee3 1085 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
f041b257
SP
1086
1087 /* just return if user desired mode exists. */
d9716ee3 1088 if (mode_ok == MODE_OK)
2b8376c8 1089 return true;
f041b257
SP
1090
1091 /*
1092 * otherwise, find the most suitable mode among modes and change it
1093 * to adjusted_mode.
1094 */
1095 list_for_each_entry(m, &connector->modes, head) {
d9716ee3 1096 mode_ok = hdmi_mode_valid(connector, m);
f041b257 1097
d9716ee3 1098 if (mode_ok == MODE_OK) {
f041b257
SP
1099 DRM_INFO("desired mode doesn't exist so\n");
1100 DRM_INFO("use the most suitable mode among modes.\n");
1101
1102 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
1103 m->hdisplay, m->vdisplay, m->vrefresh);
1104
75626853 1105 drm_mode_copy(adjusted_mode, m);
f041b257
SP
1106 break;
1107 }
1108 }
2b8376c8
GP
1109
1110 return true;
f041b257
SP
1111}
1112
3e148baf
SWK
1113static void hdmi_set_acr(u32 freq, u8 *acr)
1114{
1115 u32 n, cts;
1116
1117 switch (freq) {
1118 case 32000:
1119 n = 4096;
1120 cts = 27000;
1121 break;
1122 case 44100:
1123 n = 6272;
1124 cts = 30000;
1125 break;
1126 case 88200:
1127 n = 12544;
1128 cts = 30000;
1129 break;
1130 case 176400:
1131 n = 25088;
1132 cts = 30000;
1133 break;
1134 case 48000:
1135 n = 6144;
1136 cts = 27000;
1137 break;
1138 case 96000:
1139 n = 12288;
1140 cts = 27000;
1141 break;
1142 case 192000:
1143 n = 24576;
1144 cts = 27000;
1145 break;
1146 default:
1147 n = 0;
1148 cts = 0;
1149 break;
1150 }
1151
1152 acr[1] = cts >> 16;
1153 acr[2] = cts >> 8 & 0xff;
1154 acr[3] = cts & 0xff;
1155
1156 acr[4] = n >> 16;
1157 acr[5] = n >> 8 & 0xff;
1158 acr[6] = n & 0xff;
1159}
1160
1161static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1162{
1163 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1164 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1165 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1166 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1167 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1168 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1169 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1170 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1171 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
633d00b3 1172 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
3e148baf
SWK
1173}
1174
1175static void hdmi_audio_init(struct hdmi_context *hdata)
1176{
7a9bf6e5 1177 u32 sample_rate, bits_per_sample;
3e148baf
SWK
1178 u32 data_num, bit_ch, sample_frq;
1179 u32 val;
1180 u8 acr[7];
1181
1182 sample_rate = 44100;
1183 bits_per_sample = 16;
3e148baf
SWK
1184
1185 switch (bits_per_sample) {
1186 case 20:
1187 data_num = 2;
1188 bit_ch = 1;
1189 break;
1190 case 24:
1191 data_num = 3;
1192 bit_ch = 1;
1193 break;
1194 default:
1195 data_num = 1;
1196 bit_ch = 0;
1197 break;
1198 }
1199
1200 hdmi_set_acr(sample_rate, acr);
1201 hdmi_reg_acr(hdata, acr);
1202
1203 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1204 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1205 | HDMI_I2S_MUX_ENABLE);
1206
1207 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1208 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1209
1210 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1211
1212 sample_frq = (sample_rate == 44100) ? 0 :
1213 (sample_rate == 48000) ? 2 :
1214 (sample_rate == 32000) ? 3 :
1215 (sample_rate == 96000) ? 0xa : 0x0;
1216
1217 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1218 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1219
1220 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1221 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1222
1223 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1224 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1225 | HDMI_I2S_SEL_LRCK(6));
1226 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1227 | HDMI_I2S_SEL_SDATA2(4));
1228 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1229 | HDMI_I2S_SEL_SDATA2(2));
1230 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1231
1232 /* I2S_CON_1 & 2 */
1233 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1234 | HDMI_I2S_L_CH_LOW_POL);
1235 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1236 | HDMI_I2S_SET_BIT_CH(bit_ch)
1237 | HDMI_I2S_SET_SDATA_BIT(data_num)
1238 | HDMI_I2S_BASIC_FORMAT);
1239
1240 /* Configure register related to CUV information */
1241 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1242 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1243 | HDMI_I2S_COPYRIGHT
1244 | HDMI_I2S_LINEAR_PCM
1245 | HDMI_I2S_CONSUMER_FORMAT);
1246 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1247 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1248 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1249 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1250 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1251 HDMI_I2S_ORG_SMP_FREQ_44_1
1252 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1253 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1254
1255 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1256}
1257
1258static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1259{
872d20d6 1260 if (hdata->dvi_mode)
3e148baf
SWK
1261 return;
1262
1263 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1264 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1265 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1266}
1267
bfa48423 1268static void hdmi_start(struct hdmi_context *hdata, bool start)
d8408326 1269{
bfa48423 1270 u32 val = start ? HDMI_TG_EN : 0;
3ecd70b1 1271
bfa48423
RS
1272 if (hdata->current_mode.flags & DRM_MODE_FLAG_INTERLACE)
1273 val |= HDMI_FIELD_EN;
3ecd70b1 1274
bfa48423
RS
1275 hdmi_reg_writemask(hdata, HDMI_CON_0, val, HDMI_EN);
1276 hdmi_reg_writemask(hdata, HDMI_TG_CMD, val, HDMI_TG_EN | HDMI_FIELD_EN);
d8408326
SWK
1277}
1278
1279static void hdmi_conf_init(struct hdmi_context *hdata)
1280{
d34d59bd 1281 union hdmi_infoframe infoframe;
a144c2e9 1282
77006a7a 1283 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
d8408326
SWK
1284 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1285 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
d8408326
SWK
1286
1287 /* choose HDMI mode */
1288 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1289 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
9a8e1cb0
S
1290 /* Apply Video preable and Guard band in HDMI mode only */
1291 hdmi_reg_writeb(hdata, HDMI_CON_2, 0);
d8408326
SWK
1292 /* disable bluescreen */
1293 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
3ecd70b1 1294
872d20d6
SWK
1295 if (hdata->dvi_mode) {
1296 /* choose DVI mode */
1297 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1298 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1299 hdmi_reg_writeb(hdata, HDMI_CON_2,
1300 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1301 }
1302
cd240cde 1303 if (hdata->drv_data->type == HDMI_TYPE13) {
3ecd70b1
JS
1304 /* choose bluescreen (fecal) color */
1305 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1306 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1307 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1308
1309 /* enable AVI packet every vsync, fixes purple line problem */
1310 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1311 /* force RGB, look to CEA-861-D, table 7 for more detail */
1312 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1313 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1314
1315 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1316 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1317 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1318 } else {
d34d59bd
SK
1319 infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
1320 infoframe.any.version = HDMI_AVI_VERSION;
1321 infoframe.any.length = HDMI_AVI_LENGTH;
a144c2e9
RS
1322 hdmi_reg_infoframe(hdata, &infoframe);
1323
d34d59bd
SK
1324 infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
1325 infoframe.any.version = HDMI_AUI_VERSION;
1326 infoframe.any.length = HDMI_AUI_LENGTH;
a144c2e9
RS
1327 hdmi_reg_infoframe(hdata, &infoframe);
1328
3ecd70b1 1329 /* enable AVI packet every vsync, fixes purple line problem */
3ecd70b1
JS
1330 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1331 }
d8408326
SWK
1332}
1333
8eb6d4ec
AH
1334static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
1335{
1336 int tries;
1337
1338 for (tries = 0; tries < 10; ++tries) {
1339 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
1340
1341 if (val & HDMI_PHY_STATUS_READY) {
1342 DRM_DEBUG_KMS("PLL stabilized after %d tries\n", tries);
1343 return;
1344 }
1345 usleep_range(10, 20);
1346 }
1347
1348 DRM_ERROR("PLL could not reach steady state\n");
1349}
1350
16844fb1 1351static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
d8408326 1352{
edb6e412
AH
1353 struct drm_display_mode *m = &hdata->current_mode;
1354 unsigned int val;
3ecd70b1 1355
edb6e412
AH
1356 hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1357 hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
1358 (m->htotal << 12) | m->vtotal);
1359
1360 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1361 hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1, val);
1362
1363 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1364 hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1, val);
1365
1366 val = (m->hsync_start - m->hdisplay - 2);
1367 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1368 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1369 hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val);
1370
1371 /*
1372 * Quirk requirement for exynos HDMI IP design,
1373 * 2 pixels less than the actual calculation for hsync_start
1374 * and end.
1375 */
1376
1377 /* Following values & calculations differ for different type of modes */
1378 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1379 /* Interlaced Mode */
1380 val = ((m->vsync_end - m->vdisplay) / 2);
1381 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1382 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1383
1384 val = m->vtotal / 2;
1385 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1386 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1387
1388 val = (m->vtotal +
1389 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1390 val |= m->vtotal << 11;
1391 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, val);
1392
1393 val = ((m->vtotal / 2) + 7);
1394 val |= ((m->vtotal / 2) + 2) << 12;
1395 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, val);
1396
1397 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1398 val |= ((m->htotal / 2) +
1399 (m->hsync_start - m->hdisplay)) << 12;
1400 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, val);
1401
1402 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1403 (m->vtotal - m->vdisplay) / 2);
1404 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1405
1406 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249);
1407 } else {
1408 /* Progressive Mode */
1409
1410 val = m->vtotal;
1411 val |= (m->vtotal - m->vdisplay) << 11;
1412 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
1413
1414 hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_F_0, 3, 0);
1415
1416 val = (m->vsync_end - m->vdisplay);
1417 val |= ((m->vsync_start - m->vdisplay) << 12);
1418 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
1419
1420 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_2_0, 3, 0x1001);
1421 hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_3_0, 3, 0x1001);
1422 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1423 m->vtotal - m->vdisplay);
1424 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
1425 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248);
1426 }
1427
3ecd70b1 1428 /* Timing generator registers */
edb6e412
AH
1429 hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1430 hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1431 hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1432 hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
1433 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1);
1434 hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233);
1435 hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233);
1436 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1);
1437 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233);
1438 hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
1439 hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233);
3ecd70b1
JS
1440}
1441
16844fb1 1442static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
3ecd70b1 1443{
7b5102da 1444 struct drm_display_mode *m = &hdata->current_mode;
d8408326 1445
7b5102da
AH
1446 hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
1447 hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
1448 hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal);
1449 hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1,
1450 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1451 hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1,
1452 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1453 hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1,
1454 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1455
1456 /*
1457 * Quirk requirement for exynos 5 HDMI IP design,
1458 * 2 pixels less than the actual calculation for hsync_start
1459 * and end.
1460 */
1461
1462 /* Following values & calculations differ for different type of modes */
1463 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1464 /* Interlaced Mode */
1465 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1466 (m->vsync_end - m->vdisplay) / 2);
1467 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1468 (m->vsync_start - m->vdisplay) / 2);
1469 hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal / 2);
1470 hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1471 (m->vtotal - m->vdisplay) / 2);
1472 hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2,
1473 m->vtotal - m->vdisplay / 2);
1474 hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, m->vtotal);
1475 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2,
1476 (m->vtotal / 2) + 7);
1477 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2,
1478 (m->vtotal / 2) + 2);
1479 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2,
1480 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1481 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2,
1482 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1483 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1484 (m->vtotal - m->vdisplay) / 2);
1485 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay / 2);
1486 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2,
1487 m->vtotal - m->vdisplay / 2);
1488 hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2,
1489 (m->vtotal / 2) + 1);
1490 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2,
1491 (m->vtotal / 2) + 1);
1492 hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2,
1493 (m->vtotal / 2) + 1);
1494 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0);
1495 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0);
1496 } else {
1497 /* Progressive Mode */
1498 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
1499 m->vsync_end - m->vdisplay);
1500 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
1501 m->vsync_start - m->vdisplay);
1502 hdmi_reg_writev(hdata, HDMI_V2_BLANK_0, 2, m->vtotal);
1503 hdmi_reg_writev(hdata, HDMI_V1_BLANK_0, 2,
1504 m->vtotal - m->vdisplay);
1505 hdmi_reg_writev(hdata, HDMI_V_BLANK_F0_0, 2, 0xffff);
1506 hdmi_reg_writev(hdata, HDMI_V_BLANK_F1_0, 2, 0xffff);
1507 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_2_0, 2, 0xffff);
1508 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_1_0, 2, 0xffff);
1509 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0, 2, 0xffff);
1510 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0, 2, 0xffff);
1511 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
1512 m->vtotal - m->vdisplay);
1513 hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
1514 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248);
1515 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x47b);
1516 hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x6ae);
1517 hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233);
1518 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233);
1519 hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233);
1520 }
1521
1522 /* Following values & calculations are same irrespective of mode type */
1523 hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2,
1524 m->hsync_start - m->hdisplay - 2);
1525 hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2,
1526 m->hsync_end - m->hdisplay - 2);
1527 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_1_0, 2, 0xffff);
1528 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_2_0, 2, 0xffff);
1529 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_3_0, 2, 0xffff);
1530 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_4_0, 2, 0xffff);
1531 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_5_0, 2, 0xffff);
1532 hdmi_reg_writev(hdata, HDMI_VACT_SPACE_6_0, 2, 0xffff);
1533 hdmi_reg_writev(hdata, HDMI_V_BLANK_F2_0, 2, 0xffff);
1534 hdmi_reg_writev(hdata, HDMI_V_BLANK_F3_0, 2, 0xffff);
1535 hdmi_reg_writev(hdata, HDMI_V_BLANK_F4_0, 2, 0xffff);
1536 hdmi_reg_writev(hdata, HDMI_V_BLANK_F5_0, 2, 0xffff);
1537 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_3_0, 2, 0xffff);
1538 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_4_0, 2, 0xffff);
1539 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_5_0, 2, 0xffff);
1540 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_6_0, 2, 0xffff);
1541 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0, 2, 0xffff);
1542 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0, 2, 0xffff);
1543 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff);
1544 hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff);
3ecd70b1 1545
d8408326 1546 /* Timing generator registers */
7b5102da
AH
1547 hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
1548 hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
1549 hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
1550 hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
1551 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1);
1552 hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233);
1553 hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1);
1554 hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
1555 hdmi_reg_writev(hdata, HDMI_TG_3D, 1, 0x0);
d8408326
SWK
1556}
1557
16844fb1 1558static void hdmi_mode_apply(struct hdmi_context *hdata)
3ecd70b1 1559{
cd240cde 1560 if (hdata->drv_data->type == HDMI_TYPE13)
16844fb1 1561 hdmi_v13_mode_apply(hdata);
3ecd70b1 1562 else
16844fb1 1563 hdmi_v14_mode_apply(hdata);
8eb6d4ec
AH
1564
1565 hdmiphy_wait_for_pll(hdata);
1566
1567 clk_disable_unprepare(hdata->res.sclk_hdmi);
1568 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
1569 clk_prepare_enable(hdata->res.sclk_hdmi);
1570
1571 /* enable HDMI and timing generator */
1572 hdmi_start(hdata, true);
3ecd70b1
JS
1573}
1574
d8408326
SWK
1575static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1576{
0bfb1f8b 1577 clk_disable_unprepare(hdata->res.sclk_hdmi);
59956d35 1578 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
0bfb1f8b 1579 clk_prepare_enable(hdata->res.sclk_hdmi);
d8408326 1580
d8408326 1581 /* reset hdmiphy */
633d00b3 1582 hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
09760ea3 1583 usleep_range(10000, 12000);
633d00b3 1584 hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
09760ea3 1585 usleep_range(10000, 12000);
d8408326
SWK
1586}
1587
1588static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1589{
d8408326
SWK
1590 int ret;
1591 int i;
1592
d8408326 1593 /* pixel clock */
c93aaebf 1594 i = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000);
6b986edf
RS
1595 if (i < 0) {
1596 DRM_ERROR("failed to find hdmiphy conf\n");
1597 return;
1598 }
1599
cd240cde
AH
1600 ret = hdmiphy_reg_write_buf(hdata, 0,
1601 hdata->drv_data->phy_confs[i].conf, 32);
d5e9ca4c
RS
1602 if (ret) {
1603 DRM_ERROR("failed to configure hdmiphy\n");
d8408326
SWK
1604 return;
1605 }
1606
09760ea3 1607 usleep_range(10000, 12000);
d8408326
SWK
1608}
1609
1610static void hdmi_conf_apply(struct hdmi_context *hdata)
1611{
d8408326
SWK
1612 hdmiphy_conf_reset(hdata);
1613 hdmiphy_conf_apply(hdata);
1614
bfa48423 1615 hdmi_start(hdata, false);
d8408326 1616 hdmi_conf_init(hdata);
cf8fc4f1 1617
3e148baf 1618 hdmi_audio_init(hdata);
d8408326
SWK
1619
1620 /* setting core registers */
16844fb1 1621 hdmi_mode_apply(hdata);
3e148baf 1622 hdmi_audio_control(hdata, true);
d8408326
SWK
1623
1624 hdmi_regs_dump(hdata, "start");
1625}
1626
2b8376c8
GP
1627static void hdmi_mode_set(struct drm_encoder *encoder,
1628 struct drm_display_mode *mode,
1629 struct drm_display_mode *adjusted_mode)
d8408326 1630{
cf67cc9a 1631 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
2b8376c8 1632 struct drm_display_mode *m = adjusted_mode;
d8408326 1633
cbc4c33d
YC
1634 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1635 m->hdisplay, m->vdisplay,
6b986edf 1636 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1e6d459d 1637 "INTERLACED" : "PROGRESSIVE");
d8408326 1638
2b8376c8 1639 drm_mode_copy(&hdata->current_mode, m);
c93aaebf 1640 hdata->cea_video_id = drm_match_cea_mode(mode);
d8408326
SWK
1641}
1642
2b8376c8 1643static void hdmi_enable(struct drm_encoder *encoder)
cf8fc4f1 1644{
cf67cc9a 1645 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
cf8fc4f1
JS
1646 struct hdmi_resources *res = &hdata->res;
1647
882a0644 1648 if (hdata->powered)
cf8fc4f1 1649 return;
d8408326 1650
cf8fc4f1
JS
1651 hdata->powered = true;
1652
af65c804
SP
1653 pm_runtime_get_sync(hdata->dev);
1654
ad07945a
SWK
1655 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1656 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1657
049d34e9
RS
1658 /* set pmu hdmiphy control bit to enable hdmiphy */
1659 regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1660 PMU_HDMI_PHY_ENABLE_BIT, 1);
1661
0bfb1f8b
SP
1662 clk_prepare_enable(res->hdmi);
1663 clk_prepare_enable(res->sclk_hdmi);
a5562257 1664
c2c099f2 1665 hdmi_conf_apply(hdata);
cf8fc4f1
JS
1666}
1667
2b8376c8 1668static void hdmi_disable(struct drm_encoder *encoder)
cf8fc4f1 1669{
cf67cc9a 1670 struct hdmi_context *hdata = encoder_to_hdmi(encoder);
cf8fc4f1 1671 struct hdmi_resources *res = &hdata->res;
2b8376c8 1672 struct drm_crtc *crtc = encoder->crtc;
b6595dc7 1673 const struct drm_crtc_helper_funcs *funcs = NULL;
cf8fc4f1 1674
cf8fc4f1 1675 if (!hdata->powered)
882a0644 1676 return;
cf8fc4f1 1677
b6595dc7
GP
1678 /*
1679 * The SFRs of VP and Mixer are updated by Vertical Sync of
1680 * Timing generator which is a part of HDMI so the sequence
1681 * to disable TV Subsystem should be as following,
1682 * VP -> Mixer -> HDMI
1683 *
1684 * Below codes will try to disable Mixer and VP(if used)
1685 * prior to disabling HDMI.
1686 */
1687 if (crtc)
1688 funcs = crtc->helper_private;
1689 if (funcs && funcs->disable)
1690 (*funcs->disable)(crtc);
1691
bfa48423
RS
1692 /* HDMI System Disable */
1693 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
1694
724fd140
SP
1695 cancel_delayed_work(&hdata->hotplug_work);
1696
0bfb1f8b
SP
1697 clk_disable_unprepare(res->sclk_hdmi);
1698 clk_disable_unprepare(res->hdmi);
049d34e9
RS
1699
1700 /* reset pmu hdmiphy control bit to disable hdmiphy */
1701 regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
1702 PMU_HDMI_PHY_ENABLE_BIT, 0);
1703
cf8fc4f1
JS
1704 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1705
af65c804 1706 pm_runtime_put_sync(hdata->dev);
cf8fc4f1
JS
1707
1708 hdata->powered = false;
d8408326
SWK
1709}
1710
2b8376c8 1711static struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
f041b257 1712 .mode_fixup = hdmi_mode_fixup,
d8408326 1713 .mode_set = hdmi_mode_set,
b6595dc7
GP
1714 .enable = hdmi_enable,
1715 .disable = hdmi_disable,
d8408326
SWK
1716};
1717
2b8376c8
GP
1718static struct drm_encoder_funcs exynos_hdmi_encoder_funcs = {
1719 .destroy = drm_encoder_cleanup,
1720};
1721
724fd140 1722static void hdmi_hotplug_work_func(struct work_struct *work)
cf8fc4f1 1723{
724fd140
SP
1724 struct hdmi_context *hdata;
1725
1726 hdata = container_of(work, struct hdmi_context, hotplug_work.work);
cf8fc4f1 1727
4551789f
SP
1728 if (hdata->drm_dev)
1729 drm_helper_hpd_irq_event(hdata->drm_dev);
724fd140
SP
1730}
1731
1732static irqreturn_t hdmi_irq_thread(int irq, void *arg)
1733{
1734 struct hdmi_context *hdata = arg;
1735
1736 mod_delayed_work(system_wq, &hdata->hotplug_work,
1737 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
cf8fc4f1 1738
cf8fc4f1
JS
1739 return IRQ_HANDLED;
1740}
1741
56550d94 1742static int hdmi_resources_init(struct hdmi_context *hdata)
d8408326
SWK
1743{
1744 struct device *dev = hdata->dev;
1745 struct hdmi_resources *res = &hdata->res;
1746 static char *supply[] = {
d8408326
SWK
1747 "vdd",
1748 "vdd_osc",
1749 "vdd_pll",
1750 };
1751 int i, ret;
1752
1753 DRM_DEBUG_KMS("HDMI resource init\n");
1754
d8408326 1755 /* get clocks, power */
9f49d9fb 1756 res->hdmi = devm_clk_get(dev, "hdmi");
ee7cbafa 1757 if (IS_ERR(res->hdmi)) {
d8408326 1758 DRM_ERROR("failed to get clock 'hdmi'\n");
df5225bc 1759 ret = PTR_ERR(res->hdmi);
d8408326
SWK
1760 goto fail;
1761 }
9f49d9fb 1762 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
ee7cbafa 1763 if (IS_ERR(res->sclk_hdmi)) {
d8408326 1764 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
df5225bc 1765 ret = PTR_ERR(res->sclk_hdmi);
d8408326
SWK
1766 goto fail;
1767 }
9f49d9fb 1768 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
ee7cbafa 1769 if (IS_ERR(res->sclk_pixel)) {
d8408326 1770 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
df5225bc 1771 ret = PTR_ERR(res->sclk_pixel);
d8408326
SWK
1772 goto fail;
1773 }
9f49d9fb 1774 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
ee7cbafa 1775 if (IS_ERR(res->sclk_hdmiphy)) {
d8408326 1776 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
df5225bc 1777 ret = PTR_ERR(res->sclk_hdmiphy);
d8408326
SWK
1778 goto fail;
1779 }
59956d35
RS
1780 res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
1781 if (IS_ERR(res->mout_hdmi)) {
1782 DRM_ERROR("failed to get clock 'mout_hdmi'\n");
df5225bc 1783 ret = PTR_ERR(res->mout_hdmi);
59956d35
RS
1784 goto fail;
1785 }
d8408326 1786
59956d35 1787 clk_set_parent(res->mout_hdmi, res->sclk_pixel);
d8408326 1788
9f49d9fb 1789 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
adc837ac 1790 sizeof(res->regul_bulk[0]), GFP_KERNEL);
df5225bc
ID
1791 if (!res->regul_bulk) {
1792 ret = -ENOMEM;
d8408326 1793 goto fail;
df5225bc 1794 }
d8408326
SWK
1795 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
1796 res->regul_bulk[i].supply = supply[i];
1797 res->regul_bulk[i].consumer = NULL;
1798 }
9f49d9fb 1799 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
d8408326
SWK
1800 if (ret) {
1801 DRM_ERROR("failed to get regulators\n");
df5225bc 1802 return ret;
d8408326
SWK
1803 }
1804 res->regul_count = ARRAY_SIZE(supply);
1805
05fdf987
MS
1806 res->reg_hdmi_en = devm_regulator_get(dev, "hdmi-en");
1807 if (IS_ERR(res->reg_hdmi_en) && PTR_ERR(res->reg_hdmi_en) != -ENOENT) {
1808 DRM_ERROR("failed to get hdmi-en regulator\n");
1809 return PTR_ERR(res->reg_hdmi_en);
1810 }
1811 if (!IS_ERR(res->reg_hdmi_en)) {
1812 ret = regulator_enable(res->reg_hdmi_en);
1813 if (ret) {
1814 DRM_ERROR("failed to enable hdmi-en regulator\n");
1815 return ret;
1816 }
1817 } else
1818 res->reg_hdmi_en = NULL;
1819
df5225bc 1820 return ret;
d8408326
SWK
1821fail:
1822 DRM_ERROR("HDMI resource init - failed\n");
df5225bc 1823 return ret;
d8408326
SWK
1824}
1825
22c4f428
RS
1826static struct of_device_id hdmi_match_types[] = {
1827 {
ff830c96
MS
1828 .compatible = "samsung,exynos4210-hdmi",
1829 .data = &exynos4210_hdmi_driver_data,
cc57caf0
RS
1830 }, {
1831 .compatible = "samsung,exynos4212-hdmi",
bfe4e84c 1832 .data = &exynos4212_hdmi_driver_data,
a18a2dda
RS
1833 }, {
1834 .compatible = "samsung,exynos5420-hdmi",
1835 .data = &exynos5420_hdmi_driver_data,
c119ed05
TS
1836 }, {
1837 /* end node */
1838 }
1839};
39b58a39 1840MODULE_DEVICE_TABLE (of, hdmi_match_types);
c119ed05 1841
f37cd5e8
ID
1842static int hdmi_bind(struct device *dev, struct device *master, void *data)
1843{
1844 struct drm_device *drm_dev = data;
930865fb 1845 struct hdmi_context *hdata = dev_get_drvdata(dev);
2b8376c8
GP
1846 struct drm_encoder *encoder = &hdata->encoder;
1847 int ret, pipe;
f37cd5e8 1848
f37cd5e8
ID
1849 hdata->drm_dev = drm_dev;
1850
2b8376c8
GP
1851 pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
1852 EXYNOS_DISPLAY_TYPE_HDMI);
1853 if (pipe < 0)
1854 return pipe;
1855
1856 encoder->possible_crtcs = 1 << pipe;
1857
1858 DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
1859
1860 drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
1861 DRM_MODE_ENCODER_TMDS);
1862
1863 drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
a2986e80 1864
2b8376c8 1865 ret = hdmi_create_connector(encoder);
a2986e80
GP
1866 if (ret) {
1867 DRM_ERROR("failed to create connector ret = %d\n", ret);
2b8376c8 1868 drm_encoder_cleanup(encoder);
a2986e80
GP
1869 return ret;
1870 }
1871
1872 return 0;
f37cd5e8
ID
1873}
1874
1875static void hdmi_unbind(struct device *dev, struct device *master, void *data)
1876{
f37cd5e8
ID
1877}
1878
1879static const struct component_ops hdmi_component_ops = {
1880 .bind = hdmi_bind,
1881 .unbind = hdmi_unbind,
1882};
1883
e2a562dc
ID
1884static struct device_node *hdmi_legacy_ddc_dt_binding(struct device *dev)
1885{
1886 const char *compatible_str = "samsung,exynos4210-hdmiddc";
1887 struct device_node *np;
1888
1889 np = of_find_compatible_node(NULL, NULL, compatible_str);
1890 if (np)
1891 return of_get_next_parent(np);
1892
1893 return NULL;
1894}
1895
1896static struct device_node *hdmi_legacy_phy_dt_binding(struct device *dev)
1897{
1898 const char *compatible_str = "samsung,exynos4212-hdmiphy";
1899
1900 return of_find_compatible_node(NULL, NULL, compatible_str);
1901}
1902
56550d94 1903static int hdmi_probe(struct platform_device *pdev)
d8408326 1904{
f37cd5e8 1905 struct device_node *ddc_node, *phy_node;
f37cd5e8 1906 const struct of_device_id *match;
d8408326 1907 struct device *dev = &pdev->dev;
d8408326 1908 struct hdmi_context *hdata;
d8408326
SWK
1909 struct resource *res;
1910 int ret;
1911
88c49815 1912 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
930865fb
AH
1913 if (!hdata)
1914 return -ENOMEM;
1915
cd240cde
AH
1916 match = of_match_device(hdmi_match_types, dev);
1917 if (!match)
1918 return -ENODEV;
1919
1920 hdata->drv_data = match->data;
930865fb 1921
930865fb 1922 platform_set_drvdata(pdev, hdata);
d8408326 1923
d8408326 1924 hdata->dev = dev;
d36b3004
AH
1925 hdata->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpio", 0);
1926 if (hdata->hpd_gpio < 0) {
1927 DRM_ERROR("cannot get hpd gpio property\n");
1928 return hdata->hpd_gpio;
1929 }
d8408326
SWK
1930
1931 ret = hdmi_resources_init(hdata);
1932 if (ret) {
22c4f428 1933 DRM_ERROR("hdmi_resources_init failed\n");
df5225bc 1934 return ret;
d8408326
SWK
1935 }
1936
1937 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
d873ab99 1938 hdata->regs = devm_ioremap_resource(dev, res);
df5225bc
ID
1939 if (IS_ERR(hdata->regs)) {
1940 ret = PTR_ERR(hdata->regs);
86650408 1941 return ret;
df5225bc 1942 }
d8408326 1943
d873ab99 1944 ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
fca57122
TS
1945 if (ret) {
1946 DRM_ERROR("failed to request HPD gpio\n");
86650408 1947 return ret;
fca57122
TS
1948 }
1949
e2a562dc
ID
1950 ddc_node = hdmi_legacy_ddc_dt_binding(dev);
1951 if (ddc_node)
1952 goto out_get_ddc_adpt;
1953
d8408326 1954 /* DDC i2c driver */
2b768132
DK
1955 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
1956 if (!ddc_node) {
1957 DRM_ERROR("Failed to find ddc node in device tree\n");
86650408 1958 return -ENODEV;
2b768132 1959 }
e2a562dc
ID
1960
1961out_get_ddc_adpt:
8fa04aae
ID
1962 hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
1963 if (!hdata->ddc_adpt) {
1964 DRM_ERROR("Failed to get ddc i2c adapter by node\n");
df5225bc 1965 return -EPROBE_DEFER;
d8408326 1966 }
d8408326 1967
e2a562dc
ID
1968 phy_node = hdmi_legacy_phy_dt_binding(dev);
1969 if (phy_node)
1970 goto out_get_phy_port;
1971
d8408326 1972 /* hdmiphy i2c driver */
2b768132
DK
1973 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
1974 if (!phy_node) {
1975 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
1976 ret = -ENODEV;
1977 goto err_ddc;
1978 }
d5e9ca4c 1979
e2a562dc 1980out_get_phy_port:
cd240cde 1981 if (hdata->drv_data->is_apb_phy) {
d5e9ca4c
RS
1982 hdata->regs_hdmiphy = of_iomap(phy_node, 0);
1983 if (!hdata->regs_hdmiphy) {
1984 DRM_ERROR("failed to ioremap hdmi phy\n");
1985 ret = -ENOMEM;
1986 goto err_ddc;
1987 }
1988 } else {
1989 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
1990 if (!hdata->hdmiphy_port) {
1991 DRM_ERROR("Failed to get hdmi phy i2c client\n");
df5225bc 1992 ret = -EPROBE_DEFER;
d5e9ca4c
RS
1993 goto err_ddc;
1994 }
d8408326 1995 }
d8408326 1996
77006a7a
SP
1997 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
1998 if (hdata->irq < 0) {
1999 DRM_ERROR("failed to get GPIO irq\n");
2000 ret = hdata->irq;
cf8fc4f1
JS
2001 goto err_hdmiphy;
2002 }
2003
724fd140
SP
2004 INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
2005
dcb9a7c7 2006 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
77006a7a 2007 hdmi_irq_thread, IRQF_TRIGGER_RISING |
cf8fc4f1 2008 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
f041b257 2009 "hdmi", hdata);
d8408326 2010 if (ret) {
77006a7a 2011 DRM_ERROR("failed to register hdmi interrupt\n");
66265a2e 2012 goto err_hdmiphy;
d8408326 2013 }
d8408326 2014
049d34e9
RS
2015 hdata->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
2016 "samsung,syscon-phandle");
2017 if (IS_ERR(hdata->pmureg)) {
2018 DRM_ERROR("syscon regmap lookup failed.\n");
df5225bc 2019 ret = -EPROBE_DEFER;
049d34e9
RS
2020 goto err_hdmiphy;
2021 }
2022
af65c804 2023 pm_runtime_enable(dev);
d8408326 2024
df5225bc
ID
2025 ret = component_add(&pdev->dev, &hdmi_component_ops);
2026 if (ret)
2027 goto err_disable_pm_runtime;
2028
2029 return ret;
2030
2031err_disable_pm_runtime:
2032 pm_runtime_disable(dev);
d8408326 2033
d8408326 2034err_hdmiphy:
b21a3bf4
PT
2035 if (hdata->hdmiphy_port)
2036 put_device(&hdata->hdmiphy_port->dev);
d8408326 2037err_ddc:
8fa04aae 2038 put_device(&hdata->ddc_adpt->dev);
df5225bc 2039
d8408326
SWK
2040 return ret;
2041}
2042
56550d94 2043static int hdmi_remove(struct platform_device *pdev)
d8408326 2044{
930865fb 2045 struct hdmi_context *hdata = platform_get_drvdata(pdev);
d8408326 2046
724fd140
SP
2047 cancel_delayed_work_sync(&hdata->hotplug_work);
2048
05fdf987
MS
2049 if (hdata->res.reg_hdmi_en)
2050 regulator_disable(hdata->res.reg_hdmi_en);
2051
9d1e25c9
SWK
2052 if (hdata->hdmiphy_port)
2053 put_device(&hdata->hdmiphy_port->dev);
8fa04aae 2054 put_device(&hdata->ddc_adpt->dev);
f37cd5e8 2055
af65c804 2056 pm_runtime_disable(&pdev->dev);
df5225bc 2057 component_del(&pdev->dev, &hdmi_component_ops);
d8408326 2058
d8408326
SWK
2059 return 0;
2060}
2061
2062struct platform_driver hdmi_driver = {
2063 .probe = hdmi_probe,
56550d94 2064 .remove = hdmi_remove,
d8408326 2065 .driver = {
22c4f428 2066 .name = "exynos-hdmi",
d8408326 2067 .owner = THIS_MODULE,
88c49815 2068 .of_match_table = hdmi_match_types,
d8408326
SWK
2069 },
2070};
This page took 0.559851 seconds and 5 git commands to generate.