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