blob: b31a51da50f671c53e21b9d317c7c0ad43d6ef34 [file] [log] [blame]
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001/*
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
David Howells760285e2012-10-02 18:01:07 +010017#include <drm/drmP.h>
18#include <drm/drm_edid.h>
19#include <drm/drm_crtc_helper.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090020
21#include "regs-hdmi.h"
22
23#include <linux/kernel.h>
24#include <linux/spinlock.h>
25#include <linux/wait.h>
26#include <linux/i2c.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090027#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>
Rahul Sharma22c4f422012-10-04 20:48:55 +053034#include <linux/io.h>
Sachin Kamat3f1c7812013-08-14 16:38:01 +053035#include <linux/of.h>
Daniel Kurtz2b768132014-02-24 18:52:51 +090036#include <linux/i2c.h>
Rahul Sharma22c4f422012-10-04 20:48:55 +053037#include <linux/of_gpio.h>
Sachin Kamatd34d59b2014-02-04 08:40:18 +053038#include <linux/hdmi.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090039
40#include <drm/exynos_drm.h>
41
42#include "exynos_drm_drv.h"
Sean Paulf041b252014-01-30 16:19:15 -050043#include "exynos_mixer.h"
Seung-Woo Kimd8408322011-12-21 17:39:39 +090044
Tomasz Stanislawskifca57122012-10-04 20:48:46 +053045#include <linux/gpio.h>
46#include <media/s5p_hdmi.h>
47
Inki Dae1de425b2012-03-16 18:47:04 +090048#define MAX_WIDTH 1920
49#define MAX_HEIGHT 1080
Sean Paulf041b252014-01-30 16:19:15 -050050#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev))
Seung-Woo Kimd8408322011-12-21 17:39:39 +090051
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053052/* AVI header and aspect ratio */
53#define HDMI_AVI_VERSION 0x02
54#define HDMI_AVI_LENGTH 0x0D
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053055
56/* AUI header info */
57#define HDMI_AUI_VERSION 0x01
58#define HDMI_AUI_LENGTH 0x0A
Shirish S46154152014-03-13 10:58:28 +053059#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
60#define AVI_4_3_CENTER_RATIO 0x9
61#define AVI_16_9_CENTER_RATIO 0xa
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053062
Rahul Sharma5a325072012-10-04 20:48:54 +053063enum hdmi_type {
64 HDMI_TYPE13,
65 HDMI_TYPE14,
66};
67
Joonyoung Shim590f4182012-03-16 18:47:14 +090068struct hdmi_resources {
69 struct clk *hdmi;
70 struct clk *sclk_hdmi;
71 struct clk *sclk_pixel;
72 struct clk *sclk_hdmiphy;
73 struct clk *hdmiphy;
Rahul Sharma59956d32013-06-11 12:24:03 +053074 struct clk *mout_hdmi;
Joonyoung Shim590f4182012-03-16 18:47:14 +090075 struct regulator_bulk_data *regul_bulk;
76 int regul_count;
77};
78
Sean Paul2f7e2ed2013-01-15 08:11:08 -050079struct hdmi_tg_regs {
80 u8 cmd[1];
81 u8 h_fsz[2];
82 u8 hact_st[2];
83 u8 hact_sz[2];
84 u8 v_fsz[2];
85 u8 vsync[2];
86 u8 vsync2[2];
87 u8 vact_st[2];
88 u8 vact_sz[2];
89 u8 field_chg[2];
90 u8 vact_st2[2];
91 u8 vact_st3[2];
92 u8 vact_st4[2];
93 u8 vsync_top_hdmi[2];
94 u8 vsync_bot_hdmi[2];
95 u8 field_top_hdmi[2];
96 u8 field_bot_hdmi[2];
97 u8 tg_3d[1];
98};
99
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900100struct hdmi_v13_core_regs {
101 u8 h_blank[2];
102 u8 v_blank[3];
103 u8 h_v_line[3];
104 u8 vsync_pol[1];
105 u8 int_pro_mode[1];
106 u8 v_blank_f[3];
107 u8 h_sync_gen[3];
108 u8 v_sync_gen1[3];
109 u8 v_sync_gen2[3];
110 u8 v_sync_gen3[3];
111};
112
113struct hdmi_v14_core_regs {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500114 u8 h_blank[2];
115 u8 v2_blank[2];
116 u8 v1_blank[2];
117 u8 v_line[2];
118 u8 h_line[2];
119 u8 hsync_pol[1];
120 u8 vsync_pol[1];
121 u8 int_pro_mode[1];
122 u8 v_blank_f0[2];
123 u8 v_blank_f1[2];
124 u8 h_sync_start[2];
125 u8 h_sync_end[2];
126 u8 v_sync_line_bef_2[2];
127 u8 v_sync_line_bef_1[2];
128 u8 v_sync_line_aft_2[2];
129 u8 v_sync_line_aft_1[2];
130 u8 v_sync_line_aft_pxl_2[2];
131 u8 v_sync_line_aft_pxl_1[2];
132 u8 v_blank_f2[2]; /* for 3D mode */
133 u8 v_blank_f3[2]; /* for 3D mode */
134 u8 v_blank_f4[2]; /* for 3D mode */
135 u8 v_blank_f5[2]; /* for 3D mode */
136 u8 v_sync_line_aft_3[2];
137 u8 v_sync_line_aft_4[2];
138 u8 v_sync_line_aft_5[2];
139 u8 v_sync_line_aft_6[2];
140 u8 v_sync_line_aft_pxl_3[2];
141 u8 v_sync_line_aft_pxl_4[2];
142 u8 v_sync_line_aft_pxl_5[2];
143 u8 v_sync_line_aft_pxl_6[2];
144 u8 vact_space_1[2];
145 u8 vact_space_2[2];
146 u8 vact_space_3[2];
147 u8 vact_space_4[2];
148 u8 vact_space_5[2];
149 u8 vact_space_6[2];
150};
151
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900152struct hdmi_v13_conf {
153 struct hdmi_v13_core_regs core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500154 struct hdmi_tg_regs tg;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900155};
156
157struct hdmi_v14_conf {
158 struct hdmi_v14_core_regs core;
159 struct hdmi_tg_regs tg;
160};
161
162struct hdmi_conf_regs {
163 int pixel_clock;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500164 int cea_video_id;
Shirish S46154152014-03-13 10:58:28 +0530165 enum hdmi_picture_aspect aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900166 union {
167 struct hdmi_v13_conf v13_conf;
168 struct hdmi_v14_conf v14_conf;
169 } conf;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500170};
171
Joonyoung Shim590f4182012-03-16 18:47:14 +0900172struct hdmi_context {
173 struct device *dev;
174 struct drm_device *drm_dev;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900175 bool hpd;
176 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +0900177 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900178 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900179
Joonyoung Shim590f4182012-03-16 18:47:14 +0900180 void __iomem *regs;
Sean Paul77006a72013-01-16 10:17:20 -0500181 int irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900182
183 struct i2c_client *ddc_port;
184 struct i2c_client *hdmiphy_port;
185
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900186 /* current hdmiphy conf regs */
187 struct hdmi_conf_regs mode_conf;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900188
189 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900190
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530191 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530192
193 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900194};
195
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500196struct hdmiphy_config {
197 int pixel_clock;
198 u8 conf[32];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900199};
200
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900201/* list of phy config settings */
202static const struct hdmiphy_config hdmiphy_v13_configs[] = {
203 {
204 .pixel_clock = 27000000,
205 .conf = {
206 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
207 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
208 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
209 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
210 },
211 },
212 {
213 .pixel_clock = 27027000,
214 .conf = {
215 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
216 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
217 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
218 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
219 },
220 },
221 {
222 .pixel_clock = 74176000,
223 .conf = {
224 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
225 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
226 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
227 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
228 },
229 },
230 {
231 .pixel_clock = 74250000,
232 .conf = {
233 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
234 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
235 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
236 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
237 },
238 },
239 {
240 .pixel_clock = 148500000,
241 .conf = {
242 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
243 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
244 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
245 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
246 },
247 },
248};
249
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500250static const struct hdmiphy_config hdmiphy_v14_configs[] = {
251 {
252 .pixel_clock = 25200000,
253 .conf = {
254 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
255 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
256 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
257 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
258 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900259 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500260 {
261 .pixel_clock = 27000000,
262 .conf = {
263 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
264 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
265 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
266 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
267 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900268 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500269 {
270 .pixel_clock = 27027000,
271 .conf = {
272 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
273 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
274 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
275 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
276 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900277 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500278 {
279 .pixel_clock = 36000000,
280 .conf = {
281 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
282 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
283 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
284 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
285 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900286 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500287 {
288 .pixel_clock = 40000000,
289 .conf = {
290 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
291 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
292 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
293 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
294 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900295 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500296 {
297 .pixel_clock = 65000000,
298 .conf = {
299 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
300 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
301 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
302 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
303 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900304 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500305 {
Shirish Se1d883c2014-03-13 14:28:27 +0900306 .pixel_clock = 71000000,
307 .conf = {
308 0x01, 0x91, 0x1e, 0x15, 0x40, 0x3c, 0xce, 0x08,
309 0x04, 0x20, 0xb2, 0xd8, 0x45, 0xa0, 0xac, 0x80,
310 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
311 0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
312 },
313 },
314 {
315 .pixel_clock = 73250000,
316 .conf = {
317 0x01, 0xd1, 0x1f, 0x15, 0x40, 0x18, 0xe9, 0x08,
318 0x02, 0xa0, 0xb7, 0xd8, 0x45, 0xa0, 0xac, 0x80,
319 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
320 0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
321 },
322 },
323 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500324 .pixel_clock = 74176000,
325 .conf = {
326 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
327 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
328 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
329 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
330 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900331 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500332 {
333 .pixel_clock = 74250000,
334 .conf = {
335 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
336 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
337 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
338 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
339 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900340 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500341 {
342 .pixel_clock = 83500000,
343 .conf = {
344 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
345 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
346 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
347 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
348 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900349 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500350 {
Shirish Se1d883c2014-03-13 14:28:27 +0900351 .pixel_clock = 88750000,
352 .conf = {
353 0x01, 0x91, 0x25, 0x17, 0x40, 0x30, 0xfe, 0x08,
354 0x06, 0x20, 0xde, 0xd8, 0x45, 0xa0, 0xac, 0x80,
355 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
356 0x54, 0x8a, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
357 },
358 },
359 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500360 .pixel_clock = 106500000,
361 .conf = {
362 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
363 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
364 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
365 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
366 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900367 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500368 {
369 .pixel_clock = 108000000,
370 .conf = {
371 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
372 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
373 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
374 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
375 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900376 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500377 {
Shirish Se1d883c2014-03-13 14:28:27 +0900378 .pixel_clock = 115500000,
379 .conf = {
380 0x01, 0xd1, 0x30, 0x1a, 0x40, 0x40, 0x10, 0x04,
381 0x04, 0xa0, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
382 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
383 0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
384 },
385 },
386 {
387 .pixel_clock = 119000000,
388 .conf = {
389 0x01, 0x91, 0x32, 0x14, 0x40, 0x60, 0xd8, 0x08,
390 0x06, 0x20, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
391 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
392 0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
393 },
394 },
395 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500396 .pixel_clock = 146250000,
397 .conf = {
398 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
399 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
400 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
401 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
402 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900403 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500404 {
405 .pixel_clock = 148500000,
406 .conf = {
407 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
408 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
409 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
410 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
411 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900412 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900413};
414
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900415static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
416{
417 return readl(hdata->regs + reg_id);
418}
419
420static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
421 u32 reg_id, u8 value)
422{
423 writeb(value, hdata->regs + reg_id);
424}
425
426static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
427 u32 reg_id, u32 value, u32 mask)
428{
429 u32 old = readl(hdata->regs + reg_id);
430 value = (value & mask) | (old & ~mask);
431 writel(value, hdata->regs + reg_id);
432}
433
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900434static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900435{
436#define DUMPREG(reg_id) \
437 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
438 readl(hdata->regs + reg_id))
439 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
440 DUMPREG(HDMI_INTC_FLAG);
441 DUMPREG(HDMI_INTC_CON);
442 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900443 DUMPREG(HDMI_V13_PHY_RSTOUT);
444 DUMPREG(HDMI_V13_PHY_VPLL);
445 DUMPREG(HDMI_V13_PHY_CMU);
446 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900447
448 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
449 DUMPREG(HDMI_CON_0);
450 DUMPREG(HDMI_CON_1);
451 DUMPREG(HDMI_CON_2);
452 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900453 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900454 DUMPREG(HDMI_STATUS_EN);
455 DUMPREG(HDMI_HPD);
456 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900457 DUMPREG(HDMI_V13_HPD_GEN);
458 DUMPREG(HDMI_V13_DC_CONTROL);
459 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900460
461 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
462 DUMPREG(HDMI_H_BLANK_0);
463 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900464 DUMPREG(HDMI_V13_V_BLANK_0);
465 DUMPREG(HDMI_V13_V_BLANK_1);
466 DUMPREG(HDMI_V13_V_BLANK_2);
467 DUMPREG(HDMI_V13_H_V_LINE_0);
468 DUMPREG(HDMI_V13_H_V_LINE_1);
469 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900470 DUMPREG(HDMI_VSYNC_POL);
471 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900472 DUMPREG(HDMI_V13_V_BLANK_F_0);
473 DUMPREG(HDMI_V13_V_BLANK_F_1);
474 DUMPREG(HDMI_V13_V_BLANK_F_2);
475 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
476 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
477 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
478 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
479 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
480 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
481 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
482 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
483 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
484 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
485 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
486 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900487
488 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
489 DUMPREG(HDMI_TG_CMD);
490 DUMPREG(HDMI_TG_H_FSZ_L);
491 DUMPREG(HDMI_TG_H_FSZ_H);
492 DUMPREG(HDMI_TG_HACT_ST_L);
493 DUMPREG(HDMI_TG_HACT_ST_H);
494 DUMPREG(HDMI_TG_HACT_SZ_L);
495 DUMPREG(HDMI_TG_HACT_SZ_H);
496 DUMPREG(HDMI_TG_V_FSZ_L);
497 DUMPREG(HDMI_TG_V_FSZ_H);
498 DUMPREG(HDMI_TG_VSYNC_L);
499 DUMPREG(HDMI_TG_VSYNC_H);
500 DUMPREG(HDMI_TG_VSYNC2_L);
501 DUMPREG(HDMI_TG_VSYNC2_H);
502 DUMPREG(HDMI_TG_VACT_ST_L);
503 DUMPREG(HDMI_TG_VACT_ST_H);
504 DUMPREG(HDMI_TG_VACT_SZ_L);
505 DUMPREG(HDMI_TG_VACT_SZ_H);
506 DUMPREG(HDMI_TG_FIELD_CHG_L);
507 DUMPREG(HDMI_TG_FIELD_CHG_H);
508 DUMPREG(HDMI_TG_VACT_ST2_L);
509 DUMPREG(HDMI_TG_VACT_ST2_H);
510 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
511 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
512 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
513 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
514 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
515 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
516 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
517 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
518#undef DUMPREG
519}
520
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900521static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
522{
523 int i;
524
525#define DUMPREG(reg_id) \
526 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
527 readl(hdata->regs + reg_id))
528
529 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
530 DUMPREG(HDMI_INTC_CON);
531 DUMPREG(HDMI_INTC_FLAG);
532 DUMPREG(HDMI_HPD_STATUS);
533 DUMPREG(HDMI_INTC_CON_1);
534 DUMPREG(HDMI_INTC_FLAG_1);
535 DUMPREG(HDMI_PHY_STATUS_0);
536 DUMPREG(HDMI_PHY_STATUS_PLL);
537 DUMPREG(HDMI_PHY_CON_0);
538 DUMPREG(HDMI_PHY_RSTOUT);
539 DUMPREG(HDMI_PHY_VPLL);
540 DUMPREG(HDMI_PHY_CMU);
541 DUMPREG(HDMI_CORE_RSTOUT);
542
543 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
544 DUMPREG(HDMI_CON_0);
545 DUMPREG(HDMI_CON_1);
546 DUMPREG(HDMI_CON_2);
547 DUMPREG(HDMI_SYS_STATUS);
548 DUMPREG(HDMI_PHY_STATUS_0);
549 DUMPREG(HDMI_STATUS_EN);
550 DUMPREG(HDMI_HPD);
551 DUMPREG(HDMI_MODE_SEL);
552 DUMPREG(HDMI_ENC_EN);
553 DUMPREG(HDMI_DC_CONTROL);
554 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
555
556 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
557 DUMPREG(HDMI_H_BLANK_0);
558 DUMPREG(HDMI_H_BLANK_1);
559 DUMPREG(HDMI_V2_BLANK_0);
560 DUMPREG(HDMI_V2_BLANK_1);
561 DUMPREG(HDMI_V1_BLANK_0);
562 DUMPREG(HDMI_V1_BLANK_1);
563 DUMPREG(HDMI_V_LINE_0);
564 DUMPREG(HDMI_V_LINE_1);
565 DUMPREG(HDMI_H_LINE_0);
566 DUMPREG(HDMI_H_LINE_1);
567 DUMPREG(HDMI_HSYNC_POL);
568
569 DUMPREG(HDMI_VSYNC_POL);
570 DUMPREG(HDMI_INT_PRO_MODE);
571 DUMPREG(HDMI_V_BLANK_F0_0);
572 DUMPREG(HDMI_V_BLANK_F0_1);
573 DUMPREG(HDMI_V_BLANK_F1_0);
574 DUMPREG(HDMI_V_BLANK_F1_1);
575
576 DUMPREG(HDMI_H_SYNC_START_0);
577 DUMPREG(HDMI_H_SYNC_START_1);
578 DUMPREG(HDMI_H_SYNC_END_0);
579 DUMPREG(HDMI_H_SYNC_END_1);
580
581 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
582 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
583 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
584 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
585
586 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
587 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
588 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
589 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
590
591 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
592 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
593 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
594 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
595
596 DUMPREG(HDMI_V_BLANK_F2_0);
597 DUMPREG(HDMI_V_BLANK_F2_1);
598 DUMPREG(HDMI_V_BLANK_F3_0);
599 DUMPREG(HDMI_V_BLANK_F3_1);
600 DUMPREG(HDMI_V_BLANK_F4_0);
601 DUMPREG(HDMI_V_BLANK_F4_1);
602 DUMPREG(HDMI_V_BLANK_F5_0);
603 DUMPREG(HDMI_V_BLANK_F5_1);
604
605 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
606 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
607 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
608 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
609 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
610 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
611 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
612 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
613
614 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
615 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
616 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
617 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
618 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
619 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
620 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
621 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
622
623 DUMPREG(HDMI_VACT_SPACE_1_0);
624 DUMPREG(HDMI_VACT_SPACE_1_1);
625 DUMPREG(HDMI_VACT_SPACE_2_0);
626 DUMPREG(HDMI_VACT_SPACE_2_1);
627 DUMPREG(HDMI_VACT_SPACE_3_0);
628 DUMPREG(HDMI_VACT_SPACE_3_1);
629 DUMPREG(HDMI_VACT_SPACE_4_0);
630 DUMPREG(HDMI_VACT_SPACE_4_1);
631 DUMPREG(HDMI_VACT_SPACE_5_0);
632 DUMPREG(HDMI_VACT_SPACE_5_1);
633 DUMPREG(HDMI_VACT_SPACE_6_0);
634 DUMPREG(HDMI_VACT_SPACE_6_1);
635
636 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
637 DUMPREG(HDMI_TG_CMD);
638 DUMPREG(HDMI_TG_H_FSZ_L);
639 DUMPREG(HDMI_TG_H_FSZ_H);
640 DUMPREG(HDMI_TG_HACT_ST_L);
641 DUMPREG(HDMI_TG_HACT_ST_H);
642 DUMPREG(HDMI_TG_HACT_SZ_L);
643 DUMPREG(HDMI_TG_HACT_SZ_H);
644 DUMPREG(HDMI_TG_V_FSZ_L);
645 DUMPREG(HDMI_TG_V_FSZ_H);
646 DUMPREG(HDMI_TG_VSYNC_L);
647 DUMPREG(HDMI_TG_VSYNC_H);
648 DUMPREG(HDMI_TG_VSYNC2_L);
649 DUMPREG(HDMI_TG_VSYNC2_H);
650 DUMPREG(HDMI_TG_VACT_ST_L);
651 DUMPREG(HDMI_TG_VACT_ST_H);
652 DUMPREG(HDMI_TG_VACT_SZ_L);
653 DUMPREG(HDMI_TG_VACT_SZ_H);
654 DUMPREG(HDMI_TG_FIELD_CHG_L);
655 DUMPREG(HDMI_TG_FIELD_CHG_H);
656 DUMPREG(HDMI_TG_VACT_ST2_L);
657 DUMPREG(HDMI_TG_VACT_ST2_H);
658 DUMPREG(HDMI_TG_VACT_ST3_L);
659 DUMPREG(HDMI_TG_VACT_ST3_H);
660 DUMPREG(HDMI_TG_VACT_ST4_L);
661 DUMPREG(HDMI_TG_VACT_ST4_H);
662 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
663 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
664 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
665 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
666 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
667 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
668 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
669 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
670 DUMPREG(HDMI_TG_3D);
671
672 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
673 DUMPREG(HDMI_AVI_CON);
674 DUMPREG(HDMI_AVI_HEADER0);
675 DUMPREG(HDMI_AVI_HEADER1);
676 DUMPREG(HDMI_AVI_HEADER2);
677 DUMPREG(HDMI_AVI_CHECK_SUM);
678 DUMPREG(HDMI_VSI_CON);
679 DUMPREG(HDMI_VSI_HEADER0);
680 DUMPREG(HDMI_VSI_HEADER1);
681 DUMPREG(HDMI_VSI_HEADER2);
682 for (i = 0; i < 7; ++i)
683 DUMPREG(HDMI_VSI_DATA(i));
684
685#undef DUMPREG
686}
687
688static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
689{
Rahul Sharma5a325072012-10-04 20:48:54 +0530690 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900691 hdmi_v13_regs_dump(hdata, prefix);
692 else
693 hdmi_v14_regs_dump(hdata, prefix);
694}
695
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530696static u8 hdmi_chksum(struct hdmi_context *hdata,
697 u32 start, u8 len, u32 hdr_sum)
698{
699 int i;
700
701 /* hdr_sum : header0 + header1 + header2
702 * start : start address of packet byte1
703 * len : packet bytes - 1 */
704 for (i = 0; i < len; ++i)
705 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
706
707 /* return 2's complement of 8 bit hdr_sum */
708 return (u8)(~(hdr_sum & 0xff) + 1);
709}
710
711static void hdmi_reg_infoframe(struct hdmi_context *hdata,
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530712 union hdmi_infoframe *infoframe)
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530713{
714 u32 hdr_sum;
715 u8 chksum;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530716 u32 mod;
717 u32 vic;
718
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530719 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
720 if (hdata->dvi_mode) {
721 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
722 HDMI_VSI_CON_DO_NOT_TRANSMIT);
723 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
724 HDMI_AVI_CON_DO_NOT_TRANSMIT);
725 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
726 return;
727 }
728
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530729 switch (infoframe->any.type) {
730 case HDMI_INFOFRAME_TYPE_AVI:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530731 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530732 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
733 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
734 infoframe->any.version);
735 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
736 hdr_sum = infoframe->any.type + infoframe->any.version +
737 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530738
739 /* Output format zero hardcoded ,RGB YBCR selection */
740 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
741 AVI_ACTIVE_FORMAT_VALID |
742 AVI_UNDERSCANNED_DISPLAY_VALID);
743
Shirish S46154152014-03-13 10:58:28 +0530744 /*
745 * Set the aspect ratio as per the mode, mentioned in
746 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
747 */
748 switch (hdata->mode_conf.aspect_ratio) {
749 case HDMI_PICTURE_ASPECT_4_3:
750 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
751 hdata->mode_conf.aspect_ratio |
752 AVI_4_3_CENTER_RATIO);
753 break;
754 case HDMI_PICTURE_ASPECT_16_9:
755 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
756 hdata->mode_conf.aspect_ratio |
757 AVI_16_9_CENTER_RATIO);
758 break;
759 case HDMI_PICTURE_ASPECT_NONE:
760 default:
761 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
762 hdata->mode_conf.aspect_ratio |
763 AVI_SAME_AS_PIC_ASPECT_RATIO);
764 break;
765 }
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530766
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900767 vic = hdata->mode_conf.cea_video_id;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530768 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
769
770 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530771 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530772 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
773 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
774 break;
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530775 case HDMI_INFOFRAME_TYPE_AUDIO:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530776 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530777 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
778 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
779 infoframe->any.version);
780 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
781 hdr_sum = infoframe->any.type + infoframe->any.version +
782 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530783 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530784 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530785 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
786 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
787 break;
788 default:
789 break;
790 }
791}
792
Sean Paulf041b252014-01-30 16:19:15 -0500793static int hdmi_initialize(struct exynos_drm_display *display,
794 struct drm_device *drm_dev)
Sean Paul45517892014-01-30 16:19:05 -0500795{
Sean Paulf041b252014-01-30 16:19:15 -0500796 struct hdmi_context *hdata = display->ctx;
Sean Paul45517892014-01-30 16:19:05 -0500797
798 hdata->drm_dev = drm_dev;
799
800 return 0;
801}
802
Sean Paulf041b252014-01-30 16:19:15 -0500803static bool hdmi_is_connected(struct exynos_drm_display *display)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900804{
Sean Paulf041b252014-01-30 16:19:15 -0500805 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900806
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900807 return hdata->hpd;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900808}
809
Sean Paulf041b252014-01-30 16:19:15 -0500810static struct edid *hdmi_get_edid(struct exynos_drm_display *display,
811 struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900812{
813 struct edid *raw_edid;
Sean Paulf041b252014-01-30 16:19:15 -0500814 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900815
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900816 if (!hdata->ddc_port)
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500817 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900818
819 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500820 if (!raw_edid)
821 return ERR_PTR(-ENODEV);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900822
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500823 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
824 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
825 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
826 raw_edid->width_cm, raw_edid->height_cm);
827
828 return raw_edid;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900829}
830
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900831static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900832{
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900833 const struct hdmiphy_config *confs;
834 int count, i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900835
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900836 if (hdata->type == HDMI_TYPE13) {
837 confs = hdmiphy_v13_configs;
838 count = ARRAY_SIZE(hdmiphy_v13_configs);
839 } else if (hdata->type == HDMI_TYPE14) {
840 confs = hdmiphy_v14_configs;
841 count = ARRAY_SIZE(hdmiphy_v14_configs);
842 } else
843 return -EINVAL;
Inki Dae1de425b2012-03-16 18:47:04 +0900844
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900845 for (i = 0; i < count; i++)
846 if (confs[i].pixel_clock == pixel_clock)
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500847 return i;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500848
849 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
850 return -EINVAL;
851}
852
Sean Paulf041b252014-01-30 16:19:15 -0500853static int hdmi_check_mode(struct exynos_drm_display *display,
854 struct drm_display_mode *mode)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900855{
Sean Paulf041b252014-01-30 16:19:15 -0500856 struct hdmi_context *hdata = display->ctx;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900857 int ret;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900858
Rahul Sharma16844fb2013-06-10 14:50:00 +0530859 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
860 mode->hdisplay, mode->vdisplay, mode->vrefresh,
861 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
862 false, mode->clock * 1000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900863
Sean Paulf041b252014-01-30 16:19:15 -0500864 ret = mixer_check_mode(mode);
865 if (ret)
866 return ret;
867
Rahul Sharma16844fb2013-06-10 14:50:00 +0530868 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900869 if (ret < 0)
870 return ret;
871 return 0;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900872}
873
Sean Paulf041b252014-01-30 16:19:15 -0500874static void hdmi_mode_fixup(struct exynos_drm_display *display,
875 struct drm_connector *connector,
876 const struct drm_display_mode *mode,
877 struct drm_display_mode *adjusted_mode)
878{
879 struct drm_display_mode *m;
880 int mode_ok;
881
882 DRM_DEBUG_KMS("%s\n", __FILE__);
883
884 drm_mode_set_crtcinfo(adjusted_mode, 0);
885
886 mode_ok = hdmi_check_mode(display, adjusted_mode);
887
888 /* just return if user desired mode exists. */
889 if (mode_ok == 0)
890 return;
891
892 /*
893 * otherwise, find the most suitable mode among modes and change it
894 * to adjusted_mode.
895 */
896 list_for_each_entry(m, &connector->modes, head) {
897 mode_ok = hdmi_check_mode(display, m);
898
899 if (mode_ok == 0) {
Sean Paulf041b252014-01-30 16:19:15 -0500900 DRM_INFO("desired mode doesn't exist so\n");
901 DRM_INFO("use the most suitable mode among modes.\n");
902
903 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
904 m->hdisplay, m->vdisplay, m->vrefresh);
905
Sean Paul75626852014-01-30 16:19:16 -0500906 drm_mode_copy(adjusted_mode, m);
Sean Paulf041b252014-01-30 16:19:15 -0500907 break;
908 }
909 }
910}
911
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900912static void hdmi_set_acr(u32 freq, u8 *acr)
913{
914 u32 n, cts;
915
916 switch (freq) {
917 case 32000:
918 n = 4096;
919 cts = 27000;
920 break;
921 case 44100:
922 n = 6272;
923 cts = 30000;
924 break;
925 case 88200:
926 n = 12544;
927 cts = 30000;
928 break;
929 case 176400:
930 n = 25088;
931 cts = 30000;
932 break;
933 case 48000:
934 n = 6144;
935 cts = 27000;
936 break;
937 case 96000:
938 n = 12288;
939 cts = 27000;
940 break;
941 case 192000:
942 n = 24576;
943 cts = 27000;
944 break;
945 default:
946 n = 0;
947 cts = 0;
948 break;
949 }
950
951 acr[1] = cts >> 16;
952 acr[2] = cts >> 8 & 0xff;
953 acr[3] = cts & 0xff;
954
955 acr[4] = n >> 16;
956 acr[5] = n >> 8 & 0xff;
957 acr[6] = n & 0xff;
958}
959
960static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
961{
962 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
963 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
964 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
965 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
966 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
967 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
968 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
969 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
970 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
971
Rahul Sharma5a325072012-10-04 20:48:54 +0530972 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900973 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
974 else
975 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
976}
977
978static void hdmi_audio_init(struct hdmi_context *hdata)
979{
980 u32 sample_rate, bits_per_sample, frame_size_code;
981 u32 data_num, bit_ch, sample_frq;
982 u32 val;
983 u8 acr[7];
984
985 sample_rate = 44100;
986 bits_per_sample = 16;
987 frame_size_code = 0;
988
989 switch (bits_per_sample) {
990 case 20:
991 data_num = 2;
992 bit_ch = 1;
993 break;
994 case 24:
995 data_num = 3;
996 bit_ch = 1;
997 break;
998 default:
999 data_num = 1;
1000 bit_ch = 0;
1001 break;
1002 }
1003
1004 hdmi_set_acr(sample_rate, acr);
1005 hdmi_reg_acr(hdata, acr);
1006
1007 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1008 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1009 | HDMI_I2S_MUX_ENABLE);
1010
1011 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1012 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1013
1014 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1015
1016 sample_frq = (sample_rate == 44100) ? 0 :
1017 (sample_rate == 48000) ? 2 :
1018 (sample_rate == 32000) ? 3 :
1019 (sample_rate == 96000) ? 0xa : 0x0;
1020
1021 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1022 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1023
1024 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1025 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1026
1027 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1028 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1029 | HDMI_I2S_SEL_LRCK(6));
1030 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1031 | HDMI_I2S_SEL_SDATA2(4));
1032 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1033 | HDMI_I2S_SEL_SDATA2(2));
1034 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1035
1036 /* I2S_CON_1 & 2 */
1037 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1038 | HDMI_I2S_L_CH_LOW_POL);
1039 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1040 | HDMI_I2S_SET_BIT_CH(bit_ch)
1041 | HDMI_I2S_SET_SDATA_BIT(data_num)
1042 | HDMI_I2S_BASIC_FORMAT);
1043
1044 /* Configure register related to CUV information */
1045 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1046 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1047 | HDMI_I2S_COPYRIGHT
1048 | HDMI_I2S_LINEAR_PCM
1049 | HDMI_I2S_CONSUMER_FORMAT);
1050 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1051 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1052 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1053 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1054 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1055 HDMI_I2S_ORG_SMP_FREQ_44_1
1056 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1057 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1058
1059 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1060}
1061
1062static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1063{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001064 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001065 return;
1066
1067 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1068 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1069 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1070}
1071
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001072static void hdmi_conf_reset(struct hdmi_context *hdata)
1073{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001074 u32 reg;
1075
Rahul Sharma5a325072012-10-04 20:48:54 +05301076 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001077 reg = HDMI_V13_CORE_RSTOUT;
1078 else
1079 reg = HDMI_CORE_RSTOUT;
1080
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001081 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001082 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001083 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001084 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001085 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001086}
1087
1088static void hdmi_conf_init(struct hdmi_context *hdata)
1089{
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301090 union hdmi_infoframe infoframe;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301091
Sean Paul77006a72013-01-16 10:17:20 -05001092 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001093 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1094 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001095
1096 /* choose HDMI mode */
1097 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1098 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1099 /* disable bluescreen */
1100 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001101
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001102 if (hdata->dvi_mode) {
1103 /* choose DVI mode */
1104 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1105 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1106 hdmi_reg_writeb(hdata, HDMI_CON_2,
1107 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1108 }
1109
Rahul Sharma5a325072012-10-04 20:48:54 +05301110 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001111 /* choose bluescreen (fecal) color */
1112 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1113 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1114 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1115
1116 /* enable AVI packet every vsync, fixes purple line problem */
1117 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1118 /* force RGB, look to CEA-861-D, table 7 for more detail */
1119 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1120 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1121
1122 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1123 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1124 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1125 } else {
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301126 infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
1127 infoframe.any.version = HDMI_AVI_VERSION;
1128 infoframe.any.length = HDMI_AVI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301129 hdmi_reg_infoframe(hdata, &infoframe);
1130
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301131 infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
1132 infoframe.any.version = HDMI_AUI_VERSION;
1133 infoframe.any.length = HDMI_AUI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301134 hdmi_reg_infoframe(hdata, &infoframe);
1135
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001136 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001137 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1138 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001139}
1140
Rahul Sharma16844fb2013-06-10 14:50:00 +05301141static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001142{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001143 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1144 const struct hdmi_v13_core_regs *core =
1145 &hdata->mode_conf.conf.v13_conf.core;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001146 int tries;
1147
1148 /* setting core registers */
1149 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1150 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001151 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1152 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1153 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1154 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1155 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1156 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001157 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1158 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001159 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1160 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1161 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1162 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1163 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1164 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1165 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1166 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1167 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1168 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1169 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1170 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1171 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1172 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1173 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001174 /* Timing generator registers */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001175 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1176 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1177 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1178 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1179 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1180 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1181 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1182 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1183 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1184 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1185 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1186 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1187 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1188 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1189 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1190 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1191 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1192 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1193 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1194 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1195 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1196 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1197 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1198 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1199 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1200 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1201 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1202 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001203
1204 /* waiting for HDMIPHY's PLL to get to steady state */
1205 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001206 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001207 if (val & HDMI_PHY_STATUS_READY)
1208 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001209 usleep_range(1000, 2000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001210 }
1211 /* steady state not achieved */
1212 if (tries == 0) {
1213 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1214 hdmi_regs_dump(hdata, "timing apply");
1215 }
1216
Sean Paul0bfb1f82013-06-11 12:24:02 +05301217 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301218 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301219 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001220
1221 /* enable HDMI and timing generator */
1222 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1223 if (core->int_pro_mode[0])
1224 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1225 HDMI_FIELD_EN);
1226 else
1227 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1228}
1229
Rahul Sharma16844fb2013-06-10 14:50:00 +05301230static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001231{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001232 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1233 const struct hdmi_v14_core_regs *core =
1234 &hdata->mode_conf.conf.v14_conf.core;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001235 int tries;
1236
1237 /* setting core registers */
1238 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1239 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1240 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1241 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1242 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1243 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1244 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1245 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1246 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1247 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1248 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1249 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1250 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1251 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1252 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1253 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1254 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1255 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1256 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1257 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1258 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1259 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1260 core->v_sync_line_bef_2[0]);
1261 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1262 core->v_sync_line_bef_2[1]);
1263 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1264 core->v_sync_line_bef_1[0]);
1265 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1266 core->v_sync_line_bef_1[1]);
1267 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1268 core->v_sync_line_aft_2[0]);
1269 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1270 core->v_sync_line_aft_2[1]);
1271 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1272 core->v_sync_line_aft_1[0]);
1273 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1274 core->v_sync_line_aft_1[1]);
1275 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1276 core->v_sync_line_aft_pxl_2[0]);
1277 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1278 core->v_sync_line_aft_pxl_2[1]);
1279 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1280 core->v_sync_line_aft_pxl_1[0]);
1281 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1282 core->v_sync_line_aft_pxl_1[1]);
1283 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1284 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1285 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1286 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1287 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1288 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1289 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1290 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1291 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1292 core->v_sync_line_aft_3[0]);
1293 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1294 core->v_sync_line_aft_3[1]);
1295 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1296 core->v_sync_line_aft_4[0]);
1297 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1298 core->v_sync_line_aft_4[1]);
1299 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1300 core->v_sync_line_aft_5[0]);
1301 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1302 core->v_sync_line_aft_5[1]);
1303 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1304 core->v_sync_line_aft_6[0]);
1305 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1306 core->v_sync_line_aft_6[1]);
1307 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1308 core->v_sync_line_aft_pxl_3[0]);
1309 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1310 core->v_sync_line_aft_pxl_3[1]);
1311 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1312 core->v_sync_line_aft_pxl_4[0]);
1313 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1314 core->v_sync_line_aft_pxl_4[1]);
1315 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1316 core->v_sync_line_aft_pxl_5[0]);
1317 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1318 core->v_sync_line_aft_pxl_5[1]);
1319 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1320 core->v_sync_line_aft_pxl_6[0]);
1321 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1322 core->v_sync_line_aft_pxl_6[1]);
1323 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1324 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1325 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1326 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1327 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1328 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1329 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1330 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1331 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1332 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1333 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1334 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1335
1336 /* Timing generator registers */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001337 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1338 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1339 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1340 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1341 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1342 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1343 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1344 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1345 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1346 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1347 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1348 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1349 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1350 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1351 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1352 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1353 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1354 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1355 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1356 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1357 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
1358 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
1359 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
1360 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
1361 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1362 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1363 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1364 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1365 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1366 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1367 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1368 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1369 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001370
1371 /* waiting for HDMIPHY's PLL to get to steady state */
1372 for (tries = 100; tries; --tries) {
1373 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1374 if (val & HDMI_PHY_STATUS_READY)
1375 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001376 usleep_range(1000, 2000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001377 }
1378 /* steady state not achieved */
1379 if (tries == 0) {
1380 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1381 hdmi_regs_dump(hdata, "timing apply");
1382 }
1383
Sean Paul0bfb1f82013-06-11 12:24:02 +05301384 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301385 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301386 clk_prepare_enable(hdata->res.sclk_hdmi);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001387
1388 /* enable HDMI and timing generator */
1389 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1390 if (core->int_pro_mode[0])
1391 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1392 HDMI_FIELD_EN);
1393 else
1394 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1395}
1396
Rahul Sharma16844fb2013-06-10 14:50:00 +05301397static void hdmi_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001398{
Rahul Sharma5a325072012-10-04 20:48:54 +05301399 if (hdata->type == HDMI_TYPE13)
Rahul Sharma16844fb2013-06-10 14:50:00 +05301400 hdmi_v13_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001401 else
Rahul Sharma16844fb2013-06-10 14:50:00 +05301402 hdmi_v14_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001403}
1404
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001405static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1406{
1407 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001408 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001409
Sean Paul0bfb1f82013-06-11 12:24:02 +05301410 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301411 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301412 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001413
1414 /* operation mode */
1415 buffer[0] = 0x1f;
1416 buffer[1] = 0x00;
1417
1418 if (hdata->hdmiphy_port)
1419 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1420
Rahul Sharma5a325072012-10-04 20:48:54 +05301421 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001422 reg = HDMI_V13_PHY_RSTOUT;
1423 else
1424 reg = HDMI_PHY_RSTOUT;
1425
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001426 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001427 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001428 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001429 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001430 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001431}
1432
Rahul Sharmaa5562252012-11-28 11:30:25 +05301433static void hdmiphy_poweron(struct hdmi_context *hdata)
1434{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301435 if (hdata->type == HDMI_TYPE14)
1436 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
1437 HDMI_PHY_POWER_OFF_EN);
1438}
1439
1440static void hdmiphy_poweroff(struct hdmi_context *hdata)
1441{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301442 if (hdata->type == HDMI_TYPE14)
1443 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
1444 HDMI_PHY_POWER_OFF_EN);
1445}
1446
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001447static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1448{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001449 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001450 u8 buffer[32];
1451 u8 operation[2];
1452 u8 read_buffer[32] = {0, };
1453 int ret;
1454 int i;
1455
1456 if (!hdata->hdmiphy_port) {
1457 DRM_ERROR("hdmiphy is not attached\n");
1458 return;
1459 }
1460
1461 /* pixel clock */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001462 i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);
1463 if (i < 0) {
1464 DRM_ERROR("failed to find hdmiphy conf\n");
1465 return;
1466 }
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001467
Sachin Kamat5f46c332013-04-26 11:29:00 +05301468 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001469 hdmiphy_data = hdmiphy_v13_configs[i].conf;
Sachin Kamat5f46c332013-04-26 11:29:00 +05301470 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001471 hdmiphy_data = hdmiphy_v14_configs[i].conf;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001472
1473 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001474 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1475 if (ret != 32) {
1476 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1477 return;
1478 }
1479
Sean Paul09760ea2013-01-14 17:03:20 -05001480 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001481
1482 /* operation mode */
1483 operation[0] = 0x1f;
1484 operation[1] = 0x80;
1485
1486 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1487 if (ret != 2) {
1488 DRM_ERROR("failed to enable hdmiphy\n");
1489 return;
1490 }
1491
1492 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1493 if (ret < 0) {
1494 DRM_ERROR("failed to read hdmiphy config\n");
1495 return;
1496 }
1497
1498 for (i = 0; i < ret; i++)
1499 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1500 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1501}
1502
1503static void hdmi_conf_apply(struct hdmi_context *hdata)
1504{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001505 hdmiphy_conf_reset(hdata);
1506 hdmiphy_conf_apply(hdata);
1507
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001508 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001509 hdmi_conf_reset(hdata);
1510 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001511 mutex_unlock(&hdata->hdmi_mutex);
1512
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001513 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001514
1515 /* setting core registers */
Rahul Sharma16844fb2013-06-10 14:50:00 +05301516 hdmi_mode_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001517 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001518
1519 hdmi_regs_dump(hdata, "start");
1520}
1521
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001522static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1523{
1524 int i;
1525 BUG_ON(num_bytes > 4);
1526 for (i = 0; i < num_bytes; i++)
1527 reg_pair[i] = (value >> (8 * i)) & 0xff;
1528}
1529
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001530static void hdmi_v13_mode_set(struct hdmi_context *hdata,
1531 struct drm_display_mode *m)
1532{
1533 struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core;
1534 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1535 unsigned int val;
1536
1537 hdata->mode_conf.cea_video_id =
1538 drm_match_cea_mode((struct drm_display_mode *)m);
1539 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301540 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001541
1542 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1543 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
1544
1545 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1546 hdmi_set_reg(core->vsync_pol, 1, val);
1547
1548 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1549 hdmi_set_reg(core->int_pro_mode, 1, val);
1550
1551 val = (m->hsync_start - m->hdisplay - 2);
1552 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1553 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1554 hdmi_set_reg(core->h_sync_gen, 3, val);
1555
1556 /*
1557 * Quirk requirement for exynos HDMI IP design,
1558 * 2 pixels less than the actual calculation for hsync_start
1559 * and end.
1560 */
1561
1562 /* Following values & calculations differ for different type of modes */
1563 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1564 /* Interlaced Mode */
1565 val = ((m->vsync_end - m->vdisplay) / 2);
1566 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1567 hdmi_set_reg(core->v_sync_gen1, 3, val);
1568
1569 val = m->vtotal / 2;
1570 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1571 hdmi_set_reg(core->v_blank, 3, val);
1572
1573 val = (m->vtotal +
1574 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1575 val |= m->vtotal << 11;
1576 hdmi_set_reg(core->v_blank_f, 3, val);
1577
1578 val = ((m->vtotal / 2) + 7);
1579 val |= ((m->vtotal / 2) + 2) << 12;
1580 hdmi_set_reg(core->v_sync_gen2, 3, val);
1581
1582 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1583 val |= ((m->htotal / 2) +
1584 (m->hsync_start - m->hdisplay)) << 12;
1585 hdmi_set_reg(core->v_sync_gen3, 3, val);
1586
1587 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1588 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1589
1590 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1591 } else {
1592 /* Progressive Mode */
1593
1594 val = m->vtotal;
1595 val |= (m->vtotal - m->vdisplay) << 11;
1596 hdmi_set_reg(core->v_blank, 3, val);
1597
1598 hdmi_set_reg(core->v_blank_f, 3, 0);
1599
1600 val = (m->vsync_end - m->vdisplay);
1601 val |= ((m->vsync_start - m->vdisplay) << 12);
1602 hdmi_set_reg(core->v_sync_gen1, 3, val);
1603
1604 hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value */
1605 hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value */
1606 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1607 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1608 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1609 }
1610
1611 /* Timing generator registers */
1612 hdmi_set_reg(tg->cmd, 1, 0x0);
1613 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1614 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1615 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1616 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1617 hdmi_set_reg(tg->vsync, 2, 0x1);
1618 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1619 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1620 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1621 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1622 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1623 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1624 hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */
1625}
1626
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001627static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1628 struct drm_display_mode *m)
1629{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001630 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1631 struct hdmi_v14_core_regs *core =
1632 &hdata->mode_conf.conf.v14_conf.core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001633
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001634 hdata->mode_conf.cea_video_id =
1635 drm_match_cea_mode((struct drm_display_mode *)m);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001636 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301637 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001638
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001639 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1640 hdmi_set_reg(core->v_line, 2, m->vtotal);
1641 hdmi_set_reg(core->h_line, 2, m->htotal);
1642 hdmi_set_reg(core->hsync_pol, 1,
1643 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1644 hdmi_set_reg(core->vsync_pol, 1,
1645 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1646 hdmi_set_reg(core->int_pro_mode, 1,
1647 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1648
1649 /*
1650 * Quirk requirement for exynos 5 HDMI IP design,
1651 * 2 pixels less than the actual calculation for hsync_start
1652 * and end.
1653 */
1654
1655 /* Following values & calculations differ for different type of modes */
1656 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1657 /* Interlaced Mode */
1658 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1659 (m->vsync_end - m->vdisplay) / 2);
1660 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1661 (m->vsync_start - m->vdisplay) / 2);
1662 hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
1663 hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301664 hdmi_set_reg(core->v_blank_f0, 2, m->vtotal - m->vdisplay / 2);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001665 hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
1666 hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
1667 hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
1668 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
1669 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1670 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
1671 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1672 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1673 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301674 hdmi_set_reg(tg->vact_st2, 2, m->vtotal - m->vdisplay / 2);
1675 hdmi_set_reg(tg->vsync2, 2, (m->vtotal / 2) + 1);
1676 hdmi_set_reg(tg->vsync_bot_hdmi, 2, (m->vtotal / 2) + 1);
1677 hdmi_set_reg(tg->field_bot_hdmi, 2, (m->vtotal / 2) + 1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001678 hdmi_set_reg(tg->vact_st3, 2, 0x0);
1679 hdmi_set_reg(tg->vact_st4, 2, 0x0);
1680 } else {
1681 /* Progressive Mode */
1682 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1683 m->vsync_end - m->vdisplay);
1684 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1685 m->vsync_start - m->vdisplay);
1686 hdmi_set_reg(core->v2_blank, 2, m->vtotal);
1687 hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
1688 hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
1689 hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
1690 hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
1691 hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
1692 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
1693 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
1694 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1695 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1696 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1697 hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
1698 hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
Rahul Sharma14829952013-06-18 18:19:37 +05301699 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1700 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1701 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001702 }
1703
1704 /* Following values & calculations are same irrespective of mode type */
1705 hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
1706 hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
1707 hdmi_set_reg(core->vact_space_1, 2, 0xffff);
1708 hdmi_set_reg(core->vact_space_2, 2, 0xffff);
1709 hdmi_set_reg(core->vact_space_3, 2, 0xffff);
1710 hdmi_set_reg(core->vact_space_4, 2, 0xffff);
1711 hdmi_set_reg(core->vact_space_5, 2, 0xffff);
1712 hdmi_set_reg(core->vact_space_6, 2, 0xffff);
1713 hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
1714 hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
1715 hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
1716 hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
1717 hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
1718 hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
1719 hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
1720 hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
1721 hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
1722 hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
1723 hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
1724 hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
1725
1726 /* Timing generator registers */
1727 hdmi_set_reg(tg->cmd, 1, 0x0);
1728 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1729 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1730 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1731 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1732 hdmi_set_reg(tg->vsync, 2, 0x1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001733 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1734 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001735 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001736 hdmi_set_reg(tg->tg_3d, 1, 0x0);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001737}
1738
Sean Paulf041b252014-01-30 16:19:15 -05001739static void hdmi_mode_set(struct exynos_drm_display *display,
1740 struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001741{
Sean Paulf041b252014-01-30 16:19:15 -05001742 struct hdmi_context *hdata = display->ctx;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001743 struct drm_display_mode *m = mode;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001744
YoungJun Chocbc4c332013-06-12 10:44:40 +09001745 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1746 m->hdisplay, m->vdisplay,
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001747 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1748 "INTERLACED" : "PROGERESSIVE");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001749
Sachin Kamat5f46c332013-04-26 11:29:00 +05301750 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001751 hdmi_v13_mode_set(hdata, mode);
Sachin Kamat5f46c332013-04-26 11:29:00 +05301752 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001753 hdmi_v14_mode_set(hdata, mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001754}
1755
Sean Paulf041b252014-01-30 16:19:15 -05001756static void hdmi_get_max_resol(struct exynos_drm_display *display,
1757 unsigned int *width, unsigned int *height)
Inki Dae1de425b2012-03-16 18:47:04 +09001758{
Inki Dae1de425b2012-03-16 18:47:04 +09001759 *width = MAX_WIDTH;
1760 *height = MAX_HEIGHT;
1761}
1762
Sean Paulf041b252014-01-30 16:19:15 -05001763static void hdmi_commit(struct exynos_drm_display *display)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001764{
Sean Paulf041b252014-01-30 16:19:15 -05001765 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001766
Shirish Sdda90122013-01-23 22:03:18 -05001767 mutex_lock(&hdata->hdmi_mutex);
1768 if (!hdata->powered) {
1769 mutex_unlock(&hdata->hdmi_mutex);
1770 return;
1771 }
1772 mutex_unlock(&hdata->hdmi_mutex);
1773
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001774 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001775}
1776
Sean Paulf041b252014-01-30 16:19:15 -05001777static void hdmi_poweron(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001778{
Sean Paulf041b252014-01-30 16:19:15 -05001779 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001780 struct hdmi_resources *res = &hdata->res;
1781
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001782 mutex_lock(&hdata->hdmi_mutex);
1783 if (hdata->powered) {
1784 mutex_unlock(&hdata->hdmi_mutex);
1785 return;
1786 }
1787
1788 hdata->powered = true;
1789
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001790 mutex_unlock(&hdata->hdmi_mutex);
1791
Seung-Woo Kimad079452013-06-05 14:34:38 +09001792 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1793 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1794
Sean Paul0bfb1f82013-06-11 12:24:02 +05301795 clk_prepare_enable(res->hdmiphy);
1796 clk_prepare_enable(res->hdmi);
1797 clk_prepare_enable(res->sclk_hdmi);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301798
1799 hdmiphy_poweron(hdata);
Sean Paulf041b252014-01-30 16:19:15 -05001800 hdmi_commit(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001801}
1802
Sean Paulf041b252014-01-30 16:19:15 -05001803static void hdmi_poweroff(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001804{
Sean Paulf041b252014-01-30 16:19:15 -05001805 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001806 struct hdmi_resources *res = &hdata->res;
1807
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001808 mutex_lock(&hdata->hdmi_mutex);
1809 if (!hdata->powered)
1810 goto out;
1811 mutex_unlock(&hdata->hdmi_mutex);
1812
1813 /*
1814 * The TV power domain needs any condition of hdmiphy to turn off and
1815 * its reset state seems to meet the condition.
1816 */
1817 hdmiphy_conf_reset(hdata);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301818 hdmiphy_poweroff(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001819
Sean Paul0bfb1f82013-06-11 12:24:02 +05301820 clk_disable_unprepare(res->sclk_hdmi);
1821 clk_disable_unprepare(res->hdmi);
1822 clk_disable_unprepare(res->hdmiphy);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001823 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1824
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001825 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001826
1827 hdata->powered = false;
1828
1829out:
1830 mutex_unlock(&hdata->hdmi_mutex);
1831}
1832
Sean Paulf041b252014-01-30 16:19:15 -05001833static void hdmi_dpms(struct exynos_drm_display *display, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001834{
Sean Paulf041b252014-01-30 16:19:15 -05001835 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001836
YoungJun Chocbc4c332013-06-12 10:44:40 +09001837 DRM_DEBUG_KMS("mode %d\n", mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001838
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001839 switch (mode) {
1840 case DRM_MODE_DPMS_ON:
Rahul Sharma64327cb2012-11-28 11:30:23 +05301841 if (pm_runtime_suspended(hdata->dev))
1842 pm_runtime_get_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001843 break;
1844 case DRM_MODE_DPMS_STANDBY:
1845 case DRM_MODE_DPMS_SUSPEND:
1846 case DRM_MODE_DPMS_OFF:
Rahul Sharma64327cb2012-11-28 11:30:23 +05301847 if (!pm_runtime_suspended(hdata->dev))
1848 pm_runtime_put_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001849 break;
1850 default:
1851 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1852 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001853 }
1854}
1855
Sean Paulf041b252014-01-30 16:19:15 -05001856static struct exynos_drm_display_ops hdmi_display_ops = {
Sean Paul45517892014-01-30 16:19:05 -05001857 .initialize = hdmi_initialize,
Joonyoung Shim578b6062012-04-05 20:49:26 +09001858 .is_connected = hdmi_is_connected,
Sean Paulf041b252014-01-30 16:19:15 -05001859 .get_max_resol = hdmi_get_max_resol,
Joonyoung Shim578b6062012-04-05 20:49:26 +09001860 .get_edid = hdmi_get_edid,
Rahul Sharma16844fb2013-06-10 14:50:00 +05301861 .check_mode = hdmi_check_mode,
Sean Paulf041b252014-01-30 16:19:15 -05001862 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001863 .mode_set = hdmi_mode_set,
Sean Paulf041b252014-01-30 16:19:15 -05001864 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001865 .commit = hdmi_commit,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001866};
1867
Sean Paulf041b252014-01-30 16:19:15 -05001868static struct exynos_drm_display hdmi_display = {
1869 .type = EXYNOS_DISPLAY_TYPE_HDMI,
1870 .ops = &hdmi_display_ops,
1871};
1872
Sean Paul77006a72013-01-16 10:17:20 -05001873static irqreturn_t hdmi_irq_thread(int irq, void *arg)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001874{
Sean Paulf041b252014-01-30 16:19:15 -05001875 struct hdmi_context *hdata = arg;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001876
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001877 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301878 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001879 mutex_unlock(&hdata->hdmi_mutex);
1880
Sean Paul45517892014-01-30 16:19:05 -05001881 if (hdata->drm_dev)
1882 drm_helper_hpd_irq_event(hdata->drm_dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001883
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001884 return IRQ_HANDLED;
1885}
1886
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001887static int hdmi_resources_init(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001888{
1889 struct device *dev = hdata->dev;
1890 struct hdmi_resources *res = &hdata->res;
1891 static char *supply[] = {
1892 "hdmi-en",
1893 "vdd",
1894 "vdd_osc",
1895 "vdd_pll",
1896 };
1897 int i, ret;
1898
1899 DRM_DEBUG_KMS("HDMI resource init\n");
1900
Sachin Kamatadc837a2012-08-31 15:50:47 +05301901 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001902
1903 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301904 res->hdmi = devm_clk_get(dev, "hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301905 if (IS_ERR(res->hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001906 DRM_ERROR("failed to get clock 'hdmi'\n");
1907 goto fail;
1908 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301909 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301910 if (IS_ERR(res->sclk_hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001911 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
1912 goto fail;
1913 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301914 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301915 if (IS_ERR(res->sclk_pixel)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001916 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1917 goto fail;
1918 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301919 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301920 if (IS_ERR(res->sclk_hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001921 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
1922 goto fail;
1923 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301924 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301925 if (IS_ERR(res->hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001926 DRM_ERROR("failed to get clock 'hdmiphy'\n");
1927 goto fail;
1928 }
Rahul Sharma59956d32013-06-11 12:24:03 +05301929 res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
1930 if (IS_ERR(res->mout_hdmi)) {
1931 DRM_ERROR("failed to get clock 'mout_hdmi'\n");
1932 goto fail;
1933 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001934
Rahul Sharma59956d32013-06-11 12:24:03 +05301935 clk_set_parent(res->mout_hdmi, res->sclk_pixel);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001936
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301937 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05301938 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09001939 if (!res->regul_bulk)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001940 goto fail;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001941 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
1942 res->regul_bulk[i].supply = supply[i];
1943 res->regul_bulk[i].consumer = NULL;
1944 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301945 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001946 if (ret) {
1947 DRM_ERROR("failed to get regulators\n");
1948 goto fail;
1949 }
1950 res->regul_count = ARRAY_SIZE(supply);
1951
1952 return 0;
1953fail:
1954 DRM_ERROR("HDMI resource init - failed\n");
1955 return -ENODEV;
1956}
1957
Rahul Sharma22c4f422012-10-04 20:48:55 +05301958static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
1959 (struct device *dev)
1960{
1961 struct device_node *np = dev->of_node;
1962 struct s5p_hdmi_platform_data *pd;
Rahul Sharma22c4f422012-10-04 20:48:55 +05301963 u32 value;
1964
1965 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09001966 if (!pd)
Rahul Sharma22c4f422012-10-04 20:48:55 +05301967 goto err_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05301968
1969 if (!of_find_property(np, "hpd-gpio", &value)) {
1970 DRM_ERROR("no hpd gpio property found\n");
1971 goto err_data;
1972 }
1973
Rahul Sharma5f916e22013-06-11 19:41:29 +05301974 pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05301975
1976 return pd;
1977
1978err_data:
1979 return NULL;
1980}
Rahul Sharma22c4f422012-10-04 20:48:55 +05301981
Rahul Sharma22c4f422012-10-04 20:48:55 +05301982static struct of_device_id hdmi_match_types[] = {
1983 {
1984 .compatible = "samsung,exynos5-hdmi",
1985 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05301986 }, {
Rahul Sharmacc57caf2013-06-19 18:21:07 +05301987 .compatible = "samsung,exynos4212-hdmi",
1988 .data = (void *)HDMI_TYPE14,
1989 }, {
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05301990 /* end node */
1991 }
1992};
1993
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001994static int hdmi_probe(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001995{
1996 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001997 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301998 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001999 struct resource *res;
Sachin Kamat88c49812013-08-28 10:47:57 +05302000 const struct of_device_id *match;
Daniel Kurtz2b768132014-02-24 18:52:51 +09002001 struct device_node *ddc_node, *phy_node;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002002 int ret;
2003
Sachin Kamat88c49812013-08-28 10:47:57 +05302004 if (!dev->of_node)
2005 return -ENODEV;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302006
Sachin Kamat88c49812013-08-28 10:47:57 +05302007 pdata = drm_hdmi_dt_parse_pdata(dev);
2008 if (!pdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002009 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002010
Sachin Kamat88c49812013-08-28 10:47:57 +05302011 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09002012 if (!hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002013 return -ENOMEM;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002014
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002015 mutex_init(&hdata->hdmi_mutex);
2016
Sean Paulf041b252014-01-30 16:19:15 -05002017 platform_set_drvdata(pdev, &hdmi_display);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002018
Sachin Kamat88c49812013-08-28 10:47:57 +05302019 match = of_match_node(hdmi_match_types, dev->of_node);
2020 if (!match)
2021 return -ENODEV;
2022 hdata->type = (enum hdmi_type)match->data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302023
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302024 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002025 hdata->dev = dev;
2026
2027 ret = hdmi_resources_init(hdata);
2028 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302029 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302030 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002031 }
2032
2033 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002034 hdata->regs = devm_ioremap_resource(dev, res);
Thierry Redingd4ed6022013-01-21 11:09:02 +01002035 if (IS_ERR(hdata->regs))
2036 return PTR_ERR(hdata->regs);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002037
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002038 ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302039 if (ret) {
2040 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302041 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302042 }
2043
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002044 /* DDC i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002045 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
2046 if (!ddc_node) {
2047 DRM_ERROR("Failed to find ddc node in device tree\n");
2048 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002049 }
Daniel Kurtz2b768132014-02-24 18:52:51 +09002050 hdata->ddc_port = of_find_i2c_device_by_node(ddc_node);
2051 if (!hdata->ddc_port) {
2052 DRM_ERROR("Failed to get ddc i2c client by node\n");
2053 return -ENODEV;
2054 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002055
2056 /* hdmiphy i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002057 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
2058 if (!phy_node) {
2059 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
2060 ret = -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002061 goto err_ddc;
2062 }
Daniel Kurtz2b768132014-02-24 18:52:51 +09002063 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
2064 if (!hdata->hdmiphy_port) {
2065 DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
2066 ret = -ENODEV;
2067 goto err_ddc;
2068 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002069
Sean Paul77006a72013-01-16 10:17:20 -05002070 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
2071 if (hdata->irq < 0) {
2072 DRM_ERROR("failed to get GPIO irq\n");
2073 ret = hdata->irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002074 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002075 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002076
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302077 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2078
Seung-Woo Kimdcb9a7c2013-05-22 21:14:17 +09002079 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
Sean Paul77006a72013-01-16 10:17:20 -05002080 hdmi_irq_thread, IRQF_TRIGGER_RISING |
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002081 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sean Paulf041b252014-01-30 16:19:15 -05002082 "hdmi", hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002083 if (ret) {
Sean Paul77006a72013-01-16 10:17:20 -05002084 DRM_ERROR("failed to register hdmi interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002085 goto err_hdmiphy;
2086 }
2087
Sean Paulf041b252014-01-30 16:19:15 -05002088 hdmi_display.ctx = hdata;
2089 exynos_drm_display_register(&hdmi_display);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002090
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002091 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002092
2093 return 0;
2094
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002095err_hdmiphy:
Daniel Kurtz2b768132014-02-24 18:52:51 +09002096 put_device(&hdata->hdmiphy_port->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002097err_ddc:
Daniel Kurtz2b768132014-02-24 18:52:51 +09002098 put_device(&hdata->ddc_port->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002099 return ret;
2100}
2101
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002102static int hdmi_remove(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002103{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002104 struct device *dev = &pdev->dev;
Sean Paulf041b252014-01-30 16:19:15 -05002105 struct exynos_drm_display *display = get_hdmi_display(dev);
2106 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002107
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002108 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002109
Daniel Kurtz2b768132014-02-24 18:52:51 +09002110 put_device(&hdata->hdmiphy_port->dev);
2111 put_device(&hdata->ddc_port->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002112
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002113 return 0;
2114}
2115
Joonyoung Shimab27af82012-04-23 19:35:51 +09002116#ifdef CONFIG_PM_SLEEP
2117static int hdmi_suspend(struct device *dev)
2118{
Sean Paulf041b252014-01-30 16:19:15 -05002119 struct exynos_drm_display *display = get_hdmi_display(dev);
2120 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimab27af82012-04-23 19:35:51 +09002121
Sean Paul77006a72013-01-16 10:17:20 -05002122 disable_irq(hdata->irq);
Joonyoung Shimab27af82012-04-23 19:35:51 +09002123
2124 hdata->hpd = false;
Sean Paul45517892014-01-30 16:19:05 -05002125 if (hdata->drm_dev)
2126 drm_helper_hpd_irq_event(hdata->drm_dev);
Joonyoung Shimab27af82012-04-23 19:35:51 +09002127
Rahul Sharma64327cb2012-11-28 11:30:23 +05302128 if (pm_runtime_suspended(dev)) {
YoungJun Chocbc4c332013-06-12 10:44:40 +09002129 DRM_DEBUG_KMS("Already suspended\n");
Rahul Sharma64327cb2012-11-28 11:30:23 +05302130 return 0;
2131 }
2132
Sean Paulf041b252014-01-30 16:19:15 -05002133 hdmi_poweroff(display);
Joonyoung Shimab27af82012-04-23 19:35:51 +09002134
2135 return 0;
2136}
2137
2138static int hdmi_resume(struct device *dev)
2139{
Sean Paulf041b252014-01-30 16:19:15 -05002140 struct exynos_drm_display *display = get_hdmi_display(dev);
2141 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimab27af82012-04-23 19:35:51 +09002142
Rahul Sharma64327cb2012-11-28 11:30:23 +05302143 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2144
Sean Paul77006a72013-01-16 10:17:20 -05002145 enable_irq(hdata->irq);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302146
2147 if (!pm_runtime_suspended(dev)) {
YoungJun Chocbc4c332013-06-12 10:44:40 +09002148 DRM_DEBUG_KMS("Already resumed\n");
Rahul Sharma64327cb2012-11-28 11:30:23 +05302149 return 0;
2150 }
2151
Sean Paulf041b252014-01-30 16:19:15 -05002152 hdmi_poweron(display);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302153
Joonyoung Shimab27af82012-04-23 19:35:51 +09002154 return 0;
2155}
2156#endif
2157
Rahul Sharma64327cb2012-11-28 11:30:23 +05302158#ifdef CONFIG_PM_RUNTIME
2159static int hdmi_runtime_suspend(struct device *dev)
2160{
Sean Paulf041b252014-01-30 16:19:15 -05002161 struct exynos_drm_display *display = get_hdmi_display(dev);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302162
Sean Paulf041b252014-01-30 16:19:15 -05002163 hdmi_poweroff(display);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302164
2165 return 0;
2166}
2167
2168static int hdmi_runtime_resume(struct device *dev)
2169{
Sean Paulf041b252014-01-30 16:19:15 -05002170 struct exynos_drm_display *display = get_hdmi_display(dev);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302171
Sean Paulf041b252014-01-30 16:19:15 -05002172 hdmi_poweron(display);
Rahul Sharma64327cb2012-11-28 11:30:23 +05302173
2174 return 0;
2175}
2176#endif
2177
2178static const struct dev_pm_ops hdmi_pm_ops = {
2179 SET_SYSTEM_SLEEP_PM_OPS(hdmi_suspend, hdmi_resume)
2180 SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
2181};
Joonyoung Shimab27af82012-04-23 19:35:51 +09002182
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002183struct platform_driver hdmi_driver = {
2184 .probe = hdmi_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002185 .remove = hdmi_remove,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002186 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302187 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002188 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002189 .pm = &hdmi_pm_ops,
Sachin Kamat88c49812013-08-28 10:47:57 +05302190 .of_match_table = hdmi_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002191 },
2192};