blob: bffe24ee561d94d19269a44211a8bdf5bfd8ffae [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>
Inki Daef37cd5e2014-05-09 14:25:20 +090039#include <linux/component.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090040
41#include <drm/exynos_drm.h>
42
43#include "exynos_drm_drv.h"
Inki Daef37cd5e2014-05-09 14:25:20 +090044#include "exynos_drm_crtc.h"
Sean Paulf041b252014-01-30 16:19:15 -050045#include "exynos_mixer.h"
Seung-Woo Kimd8408322011-12-21 17:39:39 +090046
Tomasz Stanislawskifca57122012-10-04 20:48:46 +053047#include <linux/gpio.h>
48#include <media/s5p_hdmi.h>
49
Sean Paulf041b252014-01-30 16:19:15 -050050#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev))
Sean Pauld9716ee2014-01-30 16:19:29 -050051#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +090052
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053053/* AVI header and aspect ratio */
54#define HDMI_AVI_VERSION 0x02
55#define HDMI_AVI_LENGTH 0x0D
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053056
57/* AUI header info */
58#define HDMI_AUI_VERSION 0x01
59#define HDMI_AUI_LENGTH 0x0A
Shirish S46154152014-03-13 10:58:28 +053060#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
61#define AVI_4_3_CENTER_RATIO 0x9
62#define AVI_16_9_CENTER_RATIO 0xa
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053063
Rahul Sharma5a325072012-10-04 20:48:54 +053064enum hdmi_type {
65 HDMI_TYPE13,
66 HDMI_TYPE14,
67};
68
Inki Daebfe4e842014-03-06 14:18:17 +090069struct hdmi_driver_data {
70 unsigned int type;
71 unsigned int is_apb_phy:1;
72};
73
Joonyoung Shim590f4182012-03-16 18:47:14 +090074struct hdmi_resources {
75 struct clk *hdmi;
76 struct clk *sclk_hdmi;
77 struct clk *sclk_pixel;
78 struct clk *sclk_hdmiphy;
79 struct clk *hdmiphy;
Rahul Sharma59956d32013-06-11 12:24:03 +053080 struct clk *mout_hdmi;
Joonyoung Shim590f4182012-03-16 18:47:14 +090081 struct regulator_bulk_data *regul_bulk;
82 int regul_count;
83};
84
Sean Paul2f7e2ed2013-01-15 08:11:08 -050085struct hdmi_tg_regs {
86 u8 cmd[1];
87 u8 h_fsz[2];
88 u8 hact_st[2];
89 u8 hact_sz[2];
90 u8 v_fsz[2];
91 u8 vsync[2];
92 u8 vsync2[2];
93 u8 vact_st[2];
94 u8 vact_sz[2];
95 u8 field_chg[2];
96 u8 vact_st2[2];
97 u8 vact_st3[2];
98 u8 vact_st4[2];
99 u8 vsync_top_hdmi[2];
100 u8 vsync_bot_hdmi[2];
101 u8 field_top_hdmi[2];
102 u8 field_bot_hdmi[2];
103 u8 tg_3d[1];
104};
105
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900106struct hdmi_v13_core_regs {
107 u8 h_blank[2];
108 u8 v_blank[3];
109 u8 h_v_line[3];
110 u8 vsync_pol[1];
111 u8 int_pro_mode[1];
112 u8 v_blank_f[3];
113 u8 h_sync_gen[3];
114 u8 v_sync_gen1[3];
115 u8 v_sync_gen2[3];
116 u8 v_sync_gen3[3];
117};
118
119struct hdmi_v14_core_regs {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500120 u8 h_blank[2];
121 u8 v2_blank[2];
122 u8 v1_blank[2];
123 u8 v_line[2];
124 u8 h_line[2];
125 u8 hsync_pol[1];
126 u8 vsync_pol[1];
127 u8 int_pro_mode[1];
128 u8 v_blank_f0[2];
129 u8 v_blank_f1[2];
130 u8 h_sync_start[2];
131 u8 h_sync_end[2];
132 u8 v_sync_line_bef_2[2];
133 u8 v_sync_line_bef_1[2];
134 u8 v_sync_line_aft_2[2];
135 u8 v_sync_line_aft_1[2];
136 u8 v_sync_line_aft_pxl_2[2];
137 u8 v_sync_line_aft_pxl_1[2];
138 u8 v_blank_f2[2]; /* for 3D mode */
139 u8 v_blank_f3[2]; /* for 3D mode */
140 u8 v_blank_f4[2]; /* for 3D mode */
141 u8 v_blank_f5[2]; /* for 3D mode */
142 u8 v_sync_line_aft_3[2];
143 u8 v_sync_line_aft_4[2];
144 u8 v_sync_line_aft_5[2];
145 u8 v_sync_line_aft_6[2];
146 u8 v_sync_line_aft_pxl_3[2];
147 u8 v_sync_line_aft_pxl_4[2];
148 u8 v_sync_line_aft_pxl_5[2];
149 u8 v_sync_line_aft_pxl_6[2];
150 u8 vact_space_1[2];
151 u8 vact_space_2[2];
152 u8 vact_space_3[2];
153 u8 vact_space_4[2];
154 u8 vact_space_5[2];
155 u8 vact_space_6[2];
156};
157
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900158struct hdmi_v13_conf {
159 struct hdmi_v13_core_regs core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500160 struct hdmi_tg_regs tg;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900161};
162
163struct hdmi_v14_conf {
164 struct hdmi_v14_core_regs core;
165 struct hdmi_tg_regs tg;
166};
167
168struct hdmi_conf_regs {
169 int pixel_clock;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500170 int cea_video_id;
Shirish S46154152014-03-13 10:58:28 +0530171 enum hdmi_picture_aspect aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900172 union {
173 struct hdmi_v13_conf v13_conf;
174 struct hdmi_v14_conf v14_conf;
175 } conf;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500176};
177
Joonyoung Shim590f4182012-03-16 18:47:14 +0900178struct hdmi_context {
179 struct device *dev;
180 struct drm_device *drm_dev;
Sean Pauld9716ee2014-01-30 16:19:29 -0500181 struct drm_connector connector;
182 struct drm_encoder *encoder;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900183 bool hpd;
184 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +0900185 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900186 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900187
Joonyoung Shim590f4182012-03-16 18:47:14 +0900188 void __iomem *regs;
Sean Paul77006a72013-01-16 10:17:20 -0500189 int irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900190
Inki Dae8fa04aa2014-03-13 16:38:31 +0900191 struct i2c_adapter *ddc_adpt;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900192 struct i2c_client *hdmiphy_port;
193
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900194 /* current hdmiphy conf regs */
195 struct hdmi_conf_regs mode_conf;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900196
197 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900198
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530199 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530200
201 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900202};
203
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500204struct hdmiphy_config {
205 int pixel_clock;
206 u8 conf[32];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900207};
208
Jingoo Han153df692014-04-17 19:07:42 +0900209static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
Inki Daebfe4e842014-03-06 14:18:17 +0900210 .type = HDMI_TYPE14,
211};
212
Jingoo Han153df692014-04-17 19:07:42 +0900213static struct hdmi_driver_data exynos5_hdmi_driver_data = {
Inki Daebfe4e842014-03-06 14:18:17 +0900214 .type = HDMI_TYPE14,
215};
216
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900217/* list of phy config settings */
218static const struct hdmiphy_config hdmiphy_v13_configs[] = {
219 {
220 .pixel_clock = 27000000,
221 .conf = {
222 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
223 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
224 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
225 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
226 },
227 },
228 {
229 .pixel_clock = 27027000,
230 .conf = {
231 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
232 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
233 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
234 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
235 },
236 },
237 {
238 .pixel_clock = 74176000,
239 .conf = {
240 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
241 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
242 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
243 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
244 },
245 },
246 {
247 .pixel_clock = 74250000,
248 .conf = {
249 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
250 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
251 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
252 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
253 },
254 },
255 {
256 .pixel_clock = 148500000,
257 .conf = {
258 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
259 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
260 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
261 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
262 },
263 },
264};
265
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500266static const struct hdmiphy_config hdmiphy_v14_configs[] = {
267 {
268 .pixel_clock = 25200000,
269 .conf = {
270 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
271 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
272 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
273 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
274 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900275 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500276 {
277 .pixel_clock = 27000000,
278 .conf = {
279 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
280 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
281 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
282 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
283 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900284 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500285 {
286 .pixel_clock = 27027000,
287 .conf = {
288 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
289 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
290 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
291 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
292 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900293 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500294 {
295 .pixel_clock = 36000000,
296 .conf = {
297 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
298 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
299 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
300 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
301 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900302 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500303 {
304 .pixel_clock = 40000000,
305 .conf = {
306 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
307 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
308 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
309 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
310 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900311 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500312 {
313 .pixel_clock = 65000000,
314 .conf = {
315 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
316 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
317 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
318 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
319 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900320 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500321 {
Shirish Se1d883c2014-03-13 14:28:27 +0900322 .pixel_clock = 71000000,
323 .conf = {
324 0x01, 0x91, 0x1e, 0x15, 0x40, 0x3c, 0xce, 0x08,
325 0x04, 0x20, 0xb2, 0xd8, 0x45, 0xa0, 0xac, 0x80,
326 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
327 0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
328 },
329 },
330 {
331 .pixel_clock = 73250000,
332 .conf = {
333 0x01, 0xd1, 0x1f, 0x15, 0x40, 0x18, 0xe9, 0x08,
334 0x02, 0xa0, 0xb7, 0xd8, 0x45, 0xa0, 0xac, 0x80,
335 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
336 0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
337 },
338 },
339 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500340 .pixel_clock = 74176000,
341 .conf = {
342 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
343 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
344 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
345 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
346 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900347 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500348 {
349 .pixel_clock = 74250000,
350 .conf = {
351 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
352 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
353 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
354 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
355 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900356 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500357 {
358 .pixel_clock = 83500000,
359 .conf = {
360 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
361 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
362 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
363 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
364 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900365 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500366 {
Shirish Se1d883c2014-03-13 14:28:27 +0900367 .pixel_clock = 88750000,
368 .conf = {
369 0x01, 0x91, 0x25, 0x17, 0x40, 0x30, 0xfe, 0x08,
370 0x06, 0x20, 0xde, 0xd8, 0x45, 0xa0, 0xac, 0x80,
371 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
372 0x54, 0x8a, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
373 },
374 },
375 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500376 .pixel_clock = 106500000,
377 .conf = {
378 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
379 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
380 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
381 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
382 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900383 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500384 {
385 .pixel_clock = 108000000,
386 .conf = {
387 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
388 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
389 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
390 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
391 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900392 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500393 {
Shirish Se1d883c2014-03-13 14:28:27 +0900394 .pixel_clock = 115500000,
395 .conf = {
396 0x01, 0xd1, 0x30, 0x1a, 0x40, 0x40, 0x10, 0x04,
397 0x04, 0xa0, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
398 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
399 0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
400 },
401 },
402 {
403 .pixel_clock = 119000000,
404 .conf = {
405 0x01, 0x91, 0x32, 0x14, 0x40, 0x60, 0xd8, 0x08,
406 0x06, 0x20, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
407 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
408 0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
409 },
410 },
411 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500412 .pixel_clock = 146250000,
413 .conf = {
414 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
415 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
416 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
417 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
418 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900419 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500420 {
421 .pixel_clock = 148500000,
422 .conf = {
423 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
424 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
425 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
426 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
427 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900428 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900429};
430
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900431static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
432{
433 return readl(hdata->regs + reg_id);
434}
435
436static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
437 u32 reg_id, u8 value)
438{
439 writeb(value, hdata->regs + reg_id);
440}
441
442static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
443 u32 reg_id, u32 value, u32 mask)
444{
445 u32 old = readl(hdata->regs + reg_id);
446 value = (value & mask) | (old & ~mask);
447 writel(value, hdata->regs + reg_id);
448}
449
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900450static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900451{
452#define DUMPREG(reg_id) \
453 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
454 readl(hdata->regs + reg_id))
455 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
456 DUMPREG(HDMI_INTC_FLAG);
457 DUMPREG(HDMI_INTC_CON);
458 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900459 DUMPREG(HDMI_V13_PHY_RSTOUT);
460 DUMPREG(HDMI_V13_PHY_VPLL);
461 DUMPREG(HDMI_V13_PHY_CMU);
462 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900463
464 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
465 DUMPREG(HDMI_CON_0);
466 DUMPREG(HDMI_CON_1);
467 DUMPREG(HDMI_CON_2);
468 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900469 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900470 DUMPREG(HDMI_STATUS_EN);
471 DUMPREG(HDMI_HPD);
472 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900473 DUMPREG(HDMI_V13_HPD_GEN);
474 DUMPREG(HDMI_V13_DC_CONTROL);
475 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900476
477 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
478 DUMPREG(HDMI_H_BLANK_0);
479 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900480 DUMPREG(HDMI_V13_V_BLANK_0);
481 DUMPREG(HDMI_V13_V_BLANK_1);
482 DUMPREG(HDMI_V13_V_BLANK_2);
483 DUMPREG(HDMI_V13_H_V_LINE_0);
484 DUMPREG(HDMI_V13_H_V_LINE_1);
485 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900486 DUMPREG(HDMI_VSYNC_POL);
487 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900488 DUMPREG(HDMI_V13_V_BLANK_F_0);
489 DUMPREG(HDMI_V13_V_BLANK_F_1);
490 DUMPREG(HDMI_V13_V_BLANK_F_2);
491 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
492 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
493 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
494 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
495 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
496 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
497 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
498 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
499 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
500 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
501 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
502 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900503
504 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
505 DUMPREG(HDMI_TG_CMD);
506 DUMPREG(HDMI_TG_H_FSZ_L);
507 DUMPREG(HDMI_TG_H_FSZ_H);
508 DUMPREG(HDMI_TG_HACT_ST_L);
509 DUMPREG(HDMI_TG_HACT_ST_H);
510 DUMPREG(HDMI_TG_HACT_SZ_L);
511 DUMPREG(HDMI_TG_HACT_SZ_H);
512 DUMPREG(HDMI_TG_V_FSZ_L);
513 DUMPREG(HDMI_TG_V_FSZ_H);
514 DUMPREG(HDMI_TG_VSYNC_L);
515 DUMPREG(HDMI_TG_VSYNC_H);
516 DUMPREG(HDMI_TG_VSYNC2_L);
517 DUMPREG(HDMI_TG_VSYNC2_H);
518 DUMPREG(HDMI_TG_VACT_ST_L);
519 DUMPREG(HDMI_TG_VACT_ST_H);
520 DUMPREG(HDMI_TG_VACT_SZ_L);
521 DUMPREG(HDMI_TG_VACT_SZ_H);
522 DUMPREG(HDMI_TG_FIELD_CHG_L);
523 DUMPREG(HDMI_TG_FIELD_CHG_H);
524 DUMPREG(HDMI_TG_VACT_ST2_L);
525 DUMPREG(HDMI_TG_VACT_ST2_H);
526 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
527 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
528 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
529 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
530 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
531 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
532 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
533 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
534#undef DUMPREG
535}
536
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900537static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
538{
539 int i;
540
541#define DUMPREG(reg_id) \
542 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
543 readl(hdata->regs + reg_id))
544
545 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
546 DUMPREG(HDMI_INTC_CON);
547 DUMPREG(HDMI_INTC_FLAG);
548 DUMPREG(HDMI_HPD_STATUS);
549 DUMPREG(HDMI_INTC_CON_1);
550 DUMPREG(HDMI_INTC_FLAG_1);
551 DUMPREG(HDMI_PHY_STATUS_0);
552 DUMPREG(HDMI_PHY_STATUS_PLL);
553 DUMPREG(HDMI_PHY_CON_0);
554 DUMPREG(HDMI_PHY_RSTOUT);
555 DUMPREG(HDMI_PHY_VPLL);
556 DUMPREG(HDMI_PHY_CMU);
557 DUMPREG(HDMI_CORE_RSTOUT);
558
559 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
560 DUMPREG(HDMI_CON_0);
561 DUMPREG(HDMI_CON_1);
562 DUMPREG(HDMI_CON_2);
563 DUMPREG(HDMI_SYS_STATUS);
564 DUMPREG(HDMI_PHY_STATUS_0);
565 DUMPREG(HDMI_STATUS_EN);
566 DUMPREG(HDMI_HPD);
567 DUMPREG(HDMI_MODE_SEL);
568 DUMPREG(HDMI_ENC_EN);
569 DUMPREG(HDMI_DC_CONTROL);
570 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
571
572 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
573 DUMPREG(HDMI_H_BLANK_0);
574 DUMPREG(HDMI_H_BLANK_1);
575 DUMPREG(HDMI_V2_BLANK_0);
576 DUMPREG(HDMI_V2_BLANK_1);
577 DUMPREG(HDMI_V1_BLANK_0);
578 DUMPREG(HDMI_V1_BLANK_1);
579 DUMPREG(HDMI_V_LINE_0);
580 DUMPREG(HDMI_V_LINE_1);
581 DUMPREG(HDMI_H_LINE_0);
582 DUMPREG(HDMI_H_LINE_1);
583 DUMPREG(HDMI_HSYNC_POL);
584
585 DUMPREG(HDMI_VSYNC_POL);
586 DUMPREG(HDMI_INT_PRO_MODE);
587 DUMPREG(HDMI_V_BLANK_F0_0);
588 DUMPREG(HDMI_V_BLANK_F0_1);
589 DUMPREG(HDMI_V_BLANK_F1_0);
590 DUMPREG(HDMI_V_BLANK_F1_1);
591
592 DUMPREG(HDMI_H_SYNC_START_0);
593 DUMPREG(HDMI_H_SYNC_START_1);
594 DUMPREG(HDMI_H_SYNC_END_0);
595 DUMPREG(HDMI_H_SYNC_END_1);
596
597 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
598 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
599 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
600 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
601
602 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
603 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
604 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
605 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
606
607 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
608 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
609 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
610 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
611
612 DUMPREG(HDMI_V_BLANK_F2_0);
613 DUMPREG(HDMI_V_BLANK_F2_1);
614 DUMPREG(HDMI_V_BLANK_F3_0);
615 DUMPREG(HDMI_V_BLANK_F3_1);
616 DUMPREG(HDMI_V_BLANK_F4_0);
617 DUMPREG(HDMI_V_BLANK_F4_1);
618 DUMPREG(HDMI_V_BLANK_F5_0);
619 DUMPREG(HDMI_V_BLANK_F5_1);
620
621 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
622 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
623 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
624 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
625 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
626 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
627 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
628 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
629
630 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
631 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
632 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
633 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
634 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
635 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
636 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
637 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
638
639 DUMPREG(HDMI_VACT_SPACE_1_0);
640 DUMPREG(HDMI_VACT_SPACE_1_1);
641 DUMPREG(HDMI_VACT_SPACE_2_0);
642 DUMPREG(HDMI_VACT_SPACE_2_1);
643 DUMPREG(HDMI_VACT_SPACE_3_0);
644 DUMPREG(HDMI_VACT_SPACE_3_1);
645 DUMPREG(HDMI_VACT_SPACE_4_0);
646 DUMPREG(HDMI_VACT_SPACE_4_1);
647 DUMPREG(HDMI_VACT_SPACE_5_0);
648 DUMPREG(HDMI_VACT_SPACE_5_1);
649 DUMPREG(HDMI_VACT_SPACE_6_0);
650 DUMPREG(HDMI_VACT_SPACE_6_1);
651
652 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
653 DUMPREG(HDMI_TG_CMD);
654 DUMPREG(HDMI_TG_H_FSZ_L);
655 DUMPREG(HDMI_TG_H_FSZ_H);
656 DUMPREG(HDMI_TG_HACT_ST_L);
657 DUMPREG(HDMI_TG_HACT_ST_H);
658 DUMPREG(HDMI_TG_HACT_SZ_L);
659 DUMPREG(HDMI_TG_HACT_SZ_H);
660 DUMPREG(HDMI_TG_V_FSZ_L);
661 DUMPREG(HDMI_TG_V_FSZ_H);
662 DUMPREG(HDMI_TG_VSYNC_L);
663 DUMPREG(HDMI_TG_VSYNC_H);
664 DUMPREG(HDMI_TG_VSYNC2_L);
665 DUMPREG(HDMI_TG_VSYNC2_H);
666 DUMPREG(HDMI_TG_VACT_ST_L);
667 DUMPREG(HDMI_TG_VACT_ST_H);
668 DUMPREG(HDMI_TG_VACT_SZ_L);
669 DUMPREG(HDMI_TG_VACT_SZ_H);
670 DUMPREG(HDMI_TG_FIELD_CHG_L);
671 DUMPREG(HDMI_TG_FIELD_CHG_H);
672 DUMPREG(HDMI_TG_VACT_ST2_L);
673 DUMPREG(HDMI_TG_VACT_ST2_H);
674 DUMPREG(HDMI_TG_VACT_ST3_L);
675 DUMPREG(HDMI_TG_VACT_ST3_H);
676 DUMPREG(HDMI_TG_VACT_ST4_L);
677 DUMPREG(HDMI_TG_VACT_ST4_H);
678 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
679 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
680 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
681 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
682 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
683 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
684 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
685 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
686 DUMPREG(HDMI_TG_3D);
687
688 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
689 DUMPREG(HDMI_AVI_CON);
690 DUMPREG(HDMI_AVI_HEADER0);
691 DUMPREG(HDMI_AVI_HEADER1);
692 DUMPREG(HDMI_AVI_HEADER2);
693 DUMPREG(HDMI_AVI_CHECK_SUM);
694 DUMPREG(HDMI_VSI_CON);
695 DUMPREG(HDMI_VSI_HEADER0);
696 DUMPREG(HDMI_VSI_HEADER1);
697 DUMPREG(HDMI_VSI_HEADER2);
698 for (i = 0; i < 7; ++i)
699 DUMPREG(HDMI_VSI_DATA(i));
700
701#undef DUMPREG
702}
703
704static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
705{
Rahul Sharma5a325072012-10-04 20:48:54 +0530706 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900707 hdmi_v13_regs_dump(hdata, prefix);
708 else
709 hdmi_v14_regs_dump(hdata, prefix);
710}
711
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530712static u8 hdmi_chksum(struct hdmi_context *hdata,
713 u32 start, u8 len, u32 hdr_sum)
714{
715 int i;
716
717 /* hdr_sum : header0 + header1 + header2
718 * start : start address of packet byte1
719 * len : packet bytes - 1 */
720 for (i = 0; i < len; ++i)
721 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
722
723 /* return 2's complement of 8 bit hdr_sum */
724 return (u8)(~(hdr_sum & 0xff) + 1);
725}
726
727static void hdmi_reg_infoframe(struct hdmi_context *hdata,
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530728 union hdmi_infoframe *infoframe)
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530729{
730 u32 hdr_sum;
731 u8 chksum;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530732 u32 mod;
733 u32 vic;
734
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530735 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
736 if (hdata->dvi_mode) {
737 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
738 HDMI_VSI_CON_DO_NOT_TRANSMIT);
739 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
740 HDMI_AVI_CON_DO_NOT_TRANSMIT);
741 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
742 return;
743 }
744
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530745 switch (infoframe->any.type) {
746 case HDMI_INFOFRAME_TYPE_AVI:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530747 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530748 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
749 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
750 infoframe->any.version);
751 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
752 hdr_sum = infoframe->any.type + infoframe->any.version +
753 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530754
755 /* Output format zero hardcoded ,RGB YBCR selection */
756 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
757 AVI_ACTIVE_FORMAT_VALID |
758 AVI_UNDERSCANNED_DISPLAY_VALID);
759
Shirish S46154152014-03-13 10:58:28 +0530760 /*
761 * Set the aspect ratio as per the mode, mentioned in
762 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
763 */
764 switch (hdata->mode_conf.aspect_ratio) {
765 case HDMI_PICTURE_ASPECT_4_3:
766 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
767 hdata->mode_conf.aspect_ratio |
768 AVI_4_3_CENTER_RATIO);
769 break;
770 case HDMI_PICTURE_ASPECT_16_9:
771 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
772 hdata->mode_conf.aspect_ratio |
773 AVI_16_9_CENTER_RATIO);
774 break;
775 case HDMI_PICTURE_ASPECT_NONE:
776 default:
777 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
778 hdata->mode_conf.aspect_ratio |
779 AVI_SAME_AS_PIC_ASPECT_RATIO);
780 break;
781 }
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530782
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900783 vic = hdata->mode_conf.cea_video_id;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530784 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
785
786 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530787 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530788 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
789 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
790 break;
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530791 case HDMI_INFOFRAME_TYPE_AUDIO:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530792 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530793 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
794 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
795 infoframe->any.version);
796 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
797 hdr_sum = infoframe->any.type + infoframe->any.version +
798 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530799 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530800 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530801 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
802 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
803 break;
804 default:
805 break;
806 }
807}
808
Sean Pauld9716ee2014-01-30 16:19:29 -0500809static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
810 bool force)
Sean Paul45517892014-01-30 16:19:05 -0500811{
Sean Pauld9716ee2014-01-30 16:19:29 -0500812 struct hdmi_context *hdata = ctx_from_connector(connector);
Sean Paul45517892014-01-30 16:19:05 -0500813
Sean Pauld9716ee2014-01-30 16:19:29 -0500814 return hdata->hpd ? connector_status_connected :
815 connector_status_disconnected;
Sean Paul45517892014-01-30 16:19:05 -0500816}
817
Sean Pauld9716ee2014-01-30 16:19:29 -0500818static void hdmi_connector_destroy(struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900819{
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900820}
821
Sean Pauld9716ee2014-01-30 16:19:29 -0500822static struct drm_connector_funcs hdmi_connector_funcs = {
823 .dpms = drm_helper_connector_dpms,
824 .fill_modes = drm_helper_probe_single_connector_modes,
825 .detect = hdmi_detect,
826 .destroy = hdmi_connector_destroy,
827};
828
829static int hdmi_get_modes(struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900830{
Sean Pauld9716ee2014-01-30 16:19:29 -0500831 struct hdmi_context *hdata = ctx_from_connector(connector);
832 struct edid *edid;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900833
Inki Dae8fa04aa2014-03-13 16:38:31 +0900834 if (!hdata->ddc_adpt)
Sean Pauld9716ee2014-01-30 16:19:29 -0500835 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900836
Inki Dae8fa04aa2014-03-13 16:38:31 +0900837 edid = drm_get_edid(connector, hdata->ddc_adpt);
Sean Pauld9716ee2014-01-30 16:19:29 -0500838 if (!edid)
839 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900840
Sean Pauld9716ee2014-01-30 16:19:29 -0500841 hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500842 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
843 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
Sean Pauld9716ee2014-01-30 16:19:29 -0500844 edid->width_cm, edid->height_cm);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500845
Sean Pauld9716ee2014-01-30 16:19:29 -0500846 drm_mode_connector_update_edid_property(connector, edid);
847
848 return drm_add_edid_modes(connector, edid);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900849}
850
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900851static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900852{
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900853 const struct hdmiphy_config *confs;
854 int count, i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900855
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900856 if (hdata->type == HDMI_TYPE13) {
857 confs = hdmiphy_v13_configs;
858 count = ARRAY_SIZE(hdmiphy_v13_configs);
859 } else if (hdata->type == HDMI_TYPE14) {
860 confs = hdmiphy_v14_configs;
861 count = ARRAY_SIZE(hdmiphy_v14_configs);
862 } else
863 return -EINVAL;
Inki Dae1de425b2012-03-16 18:47:04 +0900864
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900865 for (i = 0; i < count; i++)
866 if (confs[i].pixel_clock == pixel_clock)
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500867 return i;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500868
869 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
870 return -EINVAL;
871}
872
Sean Pauld9716ee2014-01-30 16:19:29 -0500873static int hdmi_mode_valid(struct drm_connector *connector,
Sean Paulf041b252014-01-30 16:19:15 -0500874 struct drm_display_mode *mode)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900875{
Sean Pauld9716ee2014-01-30 16:19:29 -0500876 struct hdmi_context *hdata = ctx_from_connector(connector);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900877 int ret;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900878
Rahul Sharma16844fb2013-06-10 14:50:00 +0530879 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
880 mode->hdisplay, mode->vdisplay, mode->vrefresh,
881 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
882 false, mode->clock * 1000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900883
Sean Paulf041b252014-01-30 16:19:15 -0500884 ret = mixer_check_mode(mode);
885 if (ret)
Sean Pauld9716ee2014-01-30 16:19:29 -0500886 return MODE_BAD;
Sean Paulf041b252014-01-30 16:19:15 -0500887
Rahul Sharma16844fb2013-06-10 14:50:00 +0530888 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900889 if (ret < 0)
Sean Pauld9716ee2014-01-30 16:19:29 -0500890 return MODE_BAD;
891
892 return MODE_OK;
893}
894
895static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
896{
897 struct hdmi_context *hdata = ctx_from_connector(connector);
898
899 return hdata->encoder;
900}
901
902static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
903 .get_modes = hdmi_get_modes,
904 .mode_valid = hdmi_mode_valid,
905 .best_encoder = hdmi_best_encoder,
906};
907
908static int hdmi_create_connector(struct exynos_drm_display *display,
909 struct drm_encoder *encoder)
910{
911 struct hdmi_context *hdata = display->ctx;
912 struct drm_connector *connector = &hdata->connector;
913 int ret;
914
915 hdata->encoder = encoder;
916 connector->interlace_allowed = true;
917 connector->polled = DRM_CONNECTOR_POLL_HPD;
918
919 ret = drm_connector_init(hdata->drm_dev, connector,
920 &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
921 if (ret) {
922 DRM_ERROR("Failed to initialize connector with drm\n");
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900923 return ret;
Sean Pauld9716ee2014-01-30 16:19:29 -0500924 }
925
926 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
927 drm_sysfs_connector_add(connector);
928 drm_mode_connector_attach_encoder(connector, encoder);
929
930 return 0;
931}
932
Sean Paulf041b252014-01-30 16:19:15 -0500933static void hdmi_mode_fixup(struct exynos_drm_display *display,
934 struct drm_connector *connector,
935 const struct drm_display_mode *mode,
936 struct drm_display_mode *adjusted_mode)
937{
938 struct drm_display_mode *m;
939 int mode_ok;
940
941 DRM_DEBUG_KMS("%s\n", __FILE__);
942
943 drm_mode_set_crtcinfo(adjusted_mode, 0);
944
Sean Pauld9716ee2014-01-30 16:19:29 -0500945 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
Sean Paulf041b252014-01-30 16:19:15 -0500946
947 /* just return if user desired mode exists. */
Sean Pauld9716ee2014-01-30 16:19:29 -0500948 if (mode_ok == MODE_OK)
Sean Paulf041b252014-01-30 16:19:15 -0500949 return;
950
951 /*
952 * otherwise, find the most suitable mode among modes and change it
953 * to adjusted_mode.
954 */
955 list_for_each_entry(m, &connector->modes, head) {
Sean Pauld9716ee2014-01-30 16:19:29 -0500956 mode_ok = hdmi_mode_valid(connector, m);
Sean Paulf041b252014-01-30 16:19:15 -0500957
Sean Pauld9716ee2014-01-30 16:19:29 -0500958 if (mode_ok == MODE_OK) {
Sean Paulf041b252014-01-30 16:19:15 -0500959 DRM_INFO("desired mode doesn't exist so\n");
960 DRM_INFO("use the most suitable mode among modes.\n");
961
962 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
963 m->hdisplay, m->vdisplay, m->vrefresh);
964
Sean Paul75626852014-01-30 16:19:16 -0500965 drm_mode_copy(adjusted_mode, m);
Sean Paulf041b252014-01-30 16:19:15 -0500966 break;
967 }
968 }
969}
970
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900971static void hdmi_set_acr(u32 freq, u8 *acr)
972{
973 u32 n, cts;
974
975 switch (freq) {
976 case 32000:
977 n = 4096;
978 cts = 27000;
979 break;
980 case 44100:
981 n = 6272;
982 cts = 30000;
983 break;
984 case 88200:
985 n = 12544;
986 cts = 30000;
987 break;
988 case 176400:
989 n = 25088;
990 cts = 30000;
991 break;
992 case 48000:
993 n = 6144;
994 cts = 27000;
995 break;
996 case 96000:
997 n = 12288;
998 cts = 27000;
999 break;
1000 case 192000:
1001 n = 24576;
1002 cts = 27000;
1003 break;
1004 default:
1005 n = 0;
1006 cts = 0;
1007 break;
1008 }
1009
1010 acr[1] = cts >> 16;
1011 acr[2] = cts >> 8 & 0xff;
1012 acr[3] = cts & 0xff;
1013
1014 acr[4] = n >> 16;
1015 acr[5] = n >> 8 & 0xff;
1016 acr[6] = n & 0xff;
1017}
1018
1019static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1020{
1021 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1022 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1023 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1024 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1025 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1026 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1027 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1028 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1029 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1030
Rahul Sharma5a325072012-10-04 20:48:54 +05301031 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001032 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1033 else
1034 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1035}
1036
1037static void hdmi_audio_init(struct hdmi_context *hdata)
1038{
1039 u32 sample_rate, bits_per_sample, frame_size_code;
1040 u32 data_num, bit_ch, sample_frq;
1041 u32 val;
1042 u8 acr[7];
1043
1044 sample_rate = 44100;
1045 bits_per_sample = 16;
1046 frame_size_code = 0;
1047
1048 switch (bits_per_sample) {
1049 case 20:
1050 data_num = 2;
1051 bit_ch = 1;
1052 break;
1053 case 24:
1054 data_num = 3;
1055 bit_ch = 1;
1056 break;
1057 default:
1058 data_num = 1;
1059 bit_ch = 0;
1060 break;
1061 }
1062
1063 hdmi_set_acr(sample_rate, acr);
1064 hdmi_reg_acr(hdata, acr);
1065
1066 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1067 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1068 | HDMI_I2S_MUX_ENABLE);
1069
1070 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1071 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1072
1073 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1074
1075 sample_frq = (sample_rate == 44100) ? 0 :
1076 (sample_rate == 48000) ? 2 :
1077 (sample_rate == 32000) ? 3 :
1078 (sample_rate == 96000) ? 0xa : 0x0;
1079
1080 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1081 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1082
1083 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1084 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1085
1086 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1087 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1088 | HDMI_I2S_SEL_LRCK(6));
1089 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1090 | HDMI_I2S_SEL_SDATA2(4));
1091 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1092 | HDMI_I2S_SEL_SDATA2(2));
1093 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1094
1095 /* I2S_CON_1 & 2 */
1096 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1097 | HDMI_I2S_L_CH_LOW_POL);
1098 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1099 | HDMI_I2S_SET_BIT_CH(bit_ch)
1100 | HDMI_I2S_SET_SDATA_BIT(data_num)
1101 | HDMI_I2S_BASIC_FORMAT);
1102
1103 /* Configure register related to CUV information */
1104 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1105 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1106 | HDMI_I2S_COPYRIGHT
1107 | HDMI_I2S_LINEAR_PCM
1108 | HDMI_I2S_CONSUMER_FORMAT);
1109 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1110 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1111 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1112 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1113 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1114 HDMI_I2S_ORG_SMP_FREQ_44_1
1115 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1116 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1117
1118 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1119}
1120
1121static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1122{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001123 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001124 return;
1125
1126 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1127 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1128 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1129}
1130
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001131static void hdmi_conf_reset(struct hdmi_context *hdata)
1132{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001133 u32 reg;
1134
Rahul Sharma5a325072012-10-04 20:48:54 +05301135 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001136 reg = HDMI_V13_CORE_RSTOUT;
1137 else
1138 reg = HDMI_CORE_RSTOUT;
1139
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001140 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001141 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001142 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001143 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001144 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001145}
1146
1147static void hdmi_conf_init(struct hdmi_context *hdata)
1148{
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301149 union hdmi_infoframe infoframe;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301150
Sean Paul77006a72013-01-16 10:17:20 -05001151 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001152 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1153 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001154
1155 /* choose HDMI mode */
1156 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1157 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1158 /* disable bluescreen */
1159 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001160
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001161 if (hdata->dvi_mode) {
1162 /* choose DVI mode */
1163 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1164 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1165 hdmi_reg_writeb(hdata, HDMI_CON_2,
1166 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1167 }
1168
Rahul Sharma5a325072012-10-04 20:48:54 +05301169 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001170 /* choose bluescreen (fecal) color */
1171 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1172 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1173 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1174
1175 /* enable AVI packet every vsync, fixes purple line problem */
1176 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1177 /* force RGB, look to CEA-861-D, table 7 for more detail */
1178 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1179 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1180
1181 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1182 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1183 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1184 } else {
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301185 infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
1186 infoframe.any.version = HDMI_AVI_VERSION;
1187 infoframe.any.length = HDMI_AVI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301188 hdmi_reg_infoframe(hdata, &infoframe);
1189
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301190 infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
1191 infoframe.any.version = HDMI_AUI_VERSION;
1192 infoframe.any.length = HDMI_AUI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301193 hdmi_reg_infoframe(hdata, &infoframe);
1194
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001195 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001196 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1197 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001198}
1199
Rahul Sharma16844fb2013-06-10 14:50:00 +05301200static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001201{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001202 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1203 const struct hdmi_v13_core_regs *core =
1204 &hdata->mode_conf.conf.v13_conf.core;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001205 int tries;
1206
1207 /* setting core registers */
1208 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1209 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001210 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1211 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1212 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1213 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1214 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1215 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001216 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1217 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001218 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1219 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1220 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1221 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1222 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1223 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1224 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1225 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1226 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1227 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1228 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1229 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1230 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1231 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1232 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001233 /* Timing generator registers */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001234 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1235 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1236 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1237 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1238 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1239 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1240 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1241 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1242 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1243 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1244 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1245 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1246 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1247 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1248 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1249 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1250 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1251 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1252 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1253 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1254 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1255 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1256 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1257 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1258 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1259 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1260 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1261 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001262
1263 /* waiting for HDMIPHY's PLL to get to steady state */
1264 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001265 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001266 if (val & HDMI_PHY_STATUS_READY)
1267 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001268 usleep_range(1000, 2000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001269 }
1270 /* steady state not achieved */
1271 if (tries == 0) {
1272 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1273 hdmi_regs_dump(hdata, "timing apply");
1274 }
1275
Sean Paul0bfb1f82013-06-11 12:24:02 +05301276 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301277 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301278 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001279
1280 /* enable HDMI and timing generator */
1281 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1282 if (core->int_pro_mode[0])
1283 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1284 HDMI_FIELD_EN);
1285 else
1286 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1287}
1288
Rahul Sharma16844fb2013-06-10 14:50:00 +05301289static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001290{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001291 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1292 const struct hdmi_v14_core_regs *core =
1293 &hdata->mode_conf.conf.v14_conf.core;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001294 int tries;
1295
1296 /* setting core registers */
1297 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1298 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1299 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1300 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1301 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1302 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1303 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1304 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1305 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1306 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1307 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1308 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1309 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1310 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1311 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1312 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1313 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1314 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1315 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1316 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1317 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1318 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1319 core->v_sync_line_bef_2[0]);
1320 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1321 core->v_sync_line_bef_2[1]);
1322 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1323 core->v_sync_line_bef_1[0]);
1324 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1325 core->v_sync_line_bef_1[1]);
1326 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1327 core->v_sync_line_aft_2[0]);
1328 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1329 core->v_sync_line_aft_2[1]);
1330 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1331 core->v_sync_line_aft_1[0]);
1332 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1333 core->v_sync_line_aft_1[1]);
1334 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1335 core->v_sync_line_aft_pxl_2[0]);
1336 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1337 core->v_sync_line_aft_pxl_2[1]);
1338 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1339 core->v_sync_line_aft_pxl_1[0]);
1340 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1341 core->v_sync_line_aft_pxl_1[1]);
1342 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1343 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1344 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1345 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1346 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1347 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1348 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1349 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1350 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1351 core->v_sync_line_aft_3[0]);
1352 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1353 core->v_sync_line_aft_3[1]);
1354 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1355 core->v_sync_line_aft_4[0]);
1356 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1357 core->v_sync_line_aft_4[1]);
1358 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1359 core->v_sync_line_aft_5[0]);
1360 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1361 core->v_sync_line_aft_5[1]);
1362 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1363 core->v_sync_line_aft_6[0]);
1364 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1365 core->v_sync_line_aft_6[1]);
1366 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1367 core->v_sync_line_aft_pxl_3[0]);
1368 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1369 core->v_sync_line_aft_pxl_3[1]);
1370 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1371 core->v_sync_line_aft_pxl_4[0]);
1372 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1373 core->v_sync_line_aft_pxl_4[1]);
1374 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1375 core->v_sync_line_aft_pxl_5[0]);
1376 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1377 core->v_sync_line_aft_pxl_5[1]);
1378 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1379 core->v_sync_line_aft_pxl_6[0]);
1380 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1381 core->v_sync_line_aft_pxl_6[1]);
1382 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1383 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1384 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1385 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1386 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1387 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1388 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1389 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1390 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1391 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1392 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1393 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1394
1395 /* Timing generator registers */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001396 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1397 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1398 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1399 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1400 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1401 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1402 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1403 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1404 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1405 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1406 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1407 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1408 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1409 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1410 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1411 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1412 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1413 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1414 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1415 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1416 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
1417 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
1418 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
1419 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
1420 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1421 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1422 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1423 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1424 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1425 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1426 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1427 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1428 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001429
1430 /* waiting for HDMIPHY's PLL to get to steady state */
1431 for (tries = 100; tries; --tries) {
1432 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1433 if (val & HDMI_PHY_STATUS_READY)
1434 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001435 usleep_range(1000, 2000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001436 }
1437 /* steady state not achieved */
1438 if (tries == 0) {
1439 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1440 hdmi_regs_dump(hdata, "timing apply");
1441 }
1442
Sean Paul0bfb1f82013-06-11 12:24:02 +05301443 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301444 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301445 clk_prepare_enable(hdata->res.sclk_hdmi);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001446
1447 /* enable HDMI and timing generator */
1448 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1449 if (core->int_pro_mode[0])
1450 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1451 HDMI_FIELD_EN);
1452 else
1453 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1454}
1455
Rahul Sharma16844fb2013-06-10 14:50:00 +05301456static void hdmi_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001457{
Rahul Sharma5a325072012-10-04 20:48:54 +05301458 if (hdata->type == HDMI_TYPE13)
Rahul Sharma16844fb2013-06-10 14:50:00 +05301459 hdmi_v13_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001460 else
Rahul Sharma16844fb2013-06-10 14:50:00 +05301461 hdmi_v14_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001462}
1463
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001464static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1465{
1466 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001467 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001468
Sean Paul0bfb1f82013-06-11 12:24:02 +05301469 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301470 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301471 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001472
1473 /* operation mode */
1474 buffer[0] = 0x1f;
1475 buffer[1] = 0x00;
1476
1477 if (hdata->hdmiphy_port)
1478 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1479
Rahul Sharma5a325072012-10-04 20:48:54 +05301480 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001481 reg = HDMI_V13_PHY_RSTOUT;
1482 else
1483 reg = HDMI_PHY_RSTOUT;
1484
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001485 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001486 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001487 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001488 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001489 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001490}
1491
Rahul Sharmaa5562252012-11-28 11:30:25 +05301492static void hdmiphy_poweron(struct hdmi_context *hdata)
1493{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301494 if (hdata->type == HDMI_TYPE14)
1495 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
1496 HDMI_PHY_POWER_OFF_EN);
1497}
1498
1499static void hdmiphy_poweroff(struct hdmi_context *hdata)
1500{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301501 if (hdata->type == HDMI_TYPE14)
1502 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
1503 HDMI_PHY_POWER_OFF_EN);
1504}
1505
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001506static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1507{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001508 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001509 u8 buffer[32];
1510 u8 operation[2];
1511 u8 read_buffer[32] = {0, };
1512 int ret;
1513 int i;
1514
1515 if (!hdata->hdmiphy_port) {
1516 DRM_ERROR("hdmiphy is not attached\n");
1517 return;
1518 }
1519
1520 /* pixel clock */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001521 i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);
1522 if (i < 0) {
1523 DRM_ERROR("failed to find hdmiphy conf\n");
1524 return;
1525 }
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001526
Sachin Kamat5f46c332013-04-26 11:29:00 +05301527 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001528 hdmiphy_data = hdmiphy_v13_configs[i].conf;
Sachin Kamat5f46c332013-04-26 11:29:00 +05301529 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001530 hdmiphy_data = hdmiphy_v14_configs[i].conf;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001531
1532 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001533 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1534 if (ret != 32) {
1535 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1536 return;
1537 }
1538
Sean Paul09760ea2013-01-14 17:03:20 -05001539 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001540
1541 /* operation mode */
1542 operation[0] = 0x1f;
1543 operation[1] = 0x80;
1544
1545 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1546 if (ret != 2) {
1547 DRM_ERROR("failed to enable hdmiphy\n");
1548 return;
1549 }
1550
1551 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1552 if (ret < 0) {
1553 DRM_ERROR("failed to read hdmiphy config\n");
1554 return;
1555 }
1556
1557 for (i = 0; i < ret; i++)
1558 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1559 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1560}
1561
1562static void hdmi_conf_apply(struct hdmi_context *hdata)
1563{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001564 hdmiphy_conf_reset(hdata);
1565 hdmiphy_conf_apply(hdata);
1566
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001567 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001568 hdmi_conf_reset(hdata);
1569 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001570 mutex_unlock(&hdata->hdmi_mutex);
1571
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001572 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001573
1574 /* setting core registers */
Rahul Sharma16844fb2013-06-10 14:50:00 +05301575 hdmi_mode_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001576 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001577
1578 hdmi_regs_dump(hdata, "start");
1579}
1580
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001581static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1582{
1583 int i;
1584 BUG_ON(num_bytes > 4);
1585 for (i = 0; i < num_bytes; i++)
1586 reg_pair[i] = (value >> (8 * i)) & 0xff;
1587}
1588
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001589static void hdmi_v13_mode_set(struct hdmi_context *hdata,
1590 struct drm_display_mode *m)
1591{
1592 struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core;
1593 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1594 unsigned int val;
1595
1596 hdata->mode_conf.cea_video_id =
1597 drm_match_cea_mode((struct drm_display_mode *)m);
1598 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301599 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001600
1601 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1602 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
1603
1604 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1605 hdmi_set_reg(core->vsync_pol, 1, val);
1606
1607 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1608 hdmi_set_reg(core->int_pro_mode, 1, val);
1609
1610 val = (m->hsync_start - m->hdisplay - 2);
1611 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1612 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1613 hdmi_set_reg(core->h_sync_gen, 3, val);
1614
1615 /*
1616 * Quirk requirement for exynos HDMI IP design,
1617 * 2 pixels less than the actual calculation for hsync_start
1618 * and end.
1619 */
1620
1621 /* Following values & calculations differ for different type of modes */
1622 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1623 /* Interlaced Mode */
1624 val = ((m->vsync_end - m->vdisplay) / 2);
1625 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1626 hdmi_set_reg(core->v_sync_gen1, 3, val);
1627
1628 val = m->vtotal / 2;
1629 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1630 hdmi_set_reg(core->v_blank, 3, val);
1631
1632 val = (m->vtotal +
1633 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1634 val |= m->vtotal << 11;
1635 hdmi_set_reg(core->v_blank_f, 3, val);
1636
1637 val = ((m->vtotal / 2) + 7);
1638 val |= ((m->vtotal / 2) + 2) << 12;
1639 hdmi_set_reg(core->v_sync_gen2, 3, val);
1640
1641 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1642 val |= ((m->htotal / 2) +
1643 (m->hsync_start - m->hdisplay)) << 12;
1644 hdmi_set_reg(core->v_sync_gen3, 3, val);
1645
1646 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1647 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1648
1649 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1650 } else {
1651 /* Progressive Mode */
1652
1653 val = m->vtotal;
1654 val |= (m->vtotal - m->vdisplay) << 11;
1655 hdmi_set_reg(core->v_blank, 3, val);
1656
1657 hdmi_set_reg(core->v_blank_f, 3, 0);
1658
1659 val = (m->vsync_end - m->vdisplay);
1660 val |= ((m->vsync_start - m->vdisplay) << 12);
1661 hdmi_set_reg(core->v_sync_gen1, 3, val);
1662
1663 hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value */
1664 hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value */
1665 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1666 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1667 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1668 }
1669
1670 /* Timing generator registers */
1671 hdmi_set_reg(tg->cmd, 1, 0x0);
1672 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1673 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1674 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1675 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1676 hdmi_set_reg(tg->vsync, 2, 0x1);
1677 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1678 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1679 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1680 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1681 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1682 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1683 hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */
1684}
1685
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001686static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1687 struct drm_display_mode *m)
1688{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001689 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1690 struct hdmi_v14_core_regs *core =
1691 &hdata->mode_conf.conf.v14_conf.core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001692
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001693 hdata->mode_conf.cea_video_id =
1694 drm_match_cea_mode((struct drm_display_mode *)m);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001695 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301696 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001697
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001698 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1699 hdmi_set_reg(core->v_line, 2, m->vtotal);
1700 hdmi_set_reg(core->h_line, 2, m->htotal);
1701 hdmi_set_reg(core->hsync_pol, 1,
1702 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1703 hdmi_set_reg(core->vsync_pol, 1,
1704 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1705 hdmi_set_reg(core->int_pro_mode, 1,
1706 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1707
1708 /*
1709 * Quirk requirement for exynos 5 HDMI IP design,
1710 * 2 pixels less than the actual calculation for hsync_start
1711 * and end.
1712 */
1713
1714 /* Following values & calculations differ for different type of modes */
1715 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1716 /* Interlaced Mode */
1717 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1718 (m->vsync_end - m->vdisplay) / 2);
1719 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1720 (m->vsync_start - m->vdisplay) / 2);
1721 hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
1722 hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301723 hdmi_set_reg(core->v_blank_f0, 2, m->vtotal - m->vdisplay / 2);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001724 hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
1725 hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
1726 hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
1727 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
1728 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1729 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
1730 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1731 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1732 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301733 hdmi_set_reg(tg->vact_st2, 2, m->vtotal - m->vdisplay / 2);
1734 hdmi_set_reg(tg->vsync2, 2, (m->vtotal / 2) + 1);
1735 hdmi_set_reg(tg->vsync_bot_hdmi, 2, (m->vtotal / 2) + 1);
1736 hdmi_set_reg(tg->field_bot_hdmi, 2, (m->vtotal / 2) + 1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001737 hdmi_set_reg(tg->vact_st3, 2, 0x0);
1738 hdmi_set_reg(tg->vact_st4, 2, 0x0);
1739 } else {
1740 /* Progressive Mode */
1741 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1742 m->vsync_end - m->vdisplay);
1743 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1744 m->vsync_start - m->vdisplay);
1745 hdmi_set_reg(core->v2_blank, 2, m->vtotal);
1746 hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
1747 hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
1748 hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
1749 hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
1750 hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
1751 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
1752 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
1753 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1754 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1755 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1756 hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
1757 hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
Rahul Sharma14829952013-06-18 18:19:37 +05301758 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1759 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1760 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001761 }
1762
1763 /* Following values & calculations are same irrespective of mode type */
1764 hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
1765 hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
1766 hdmi_set_reg(core->vact_space_1, 2, 0xffff);
1767 hdmi_set_reg(core->vact_space_2, 2, 0xffff);
1768 hdmi_set_reg(core->vact_space_3, 2, 0xffff);
1769 hdmi_set_reg(core->vact_space_4, 2, 0xffff);
1770 hdmi_set_reg(core->vact_space_5, 2, 0xffff);
1771 hdmi_set_reg(core->vact_space_6, 2, 0xffff);
1772 hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
1773 hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
1774 hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
1775 hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
1776 hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
1777 hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
1778 hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
1779 hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
1780 hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
1781 hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
1782 hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
1783 hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
1784
1785 /* Timing generator registers */
1786 hdmi_set_reg(tg->cmd, 1, 0x0);
1787 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1788 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1789 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1790 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1791 hdmi_set_reg(tg->vsync, 2, 0x1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001792 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1793 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001794 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001795 hdmi_set_reg(tg->tg_3d, 1, 0x0);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001796}
1797
Sean Paulf041b252014-01-30 16:19:15 -05001798static void hdmi_mode_set(struct exynos_drm_display *display,
1799 struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001800{
Sean Paulf041b252014-01-30 16:19:15 -05001801 struct hdmi_context *hdata = display->ctx;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001802 struct drm_display_mode *m = mode;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001803
YoungJun Chocbc4c332013-06-12 10:44:40 +09001804 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1805 m->hdisplay, m->vdisplay,
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001806 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1807 "INTERLACED" : "PROGERESSIVE");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001808
Sachin Kamat5f46c332013-04-26 11:29:00 +05301809 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001810 hdmi_v13_mode_set(hdata, mode);
Sachin Kamat5f46c332013-04-26 11:29:00 +05301811 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001812 hdmi_v14_mode_set(hdata, mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001813}
1814
Sean Paulf041b252014-01-30 16:19:15 -05001815static void hdmi_commit(struct exynos_drm_display *display)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001816{
Sean Paulf041b252014-01-30 16:19:15 -05001817 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001818
Shirish Sdda90122013-01-23 22:03:18 -05001819 mutex_lock(&hdata->hdmi_mutex);
1820 if (!hdata->powered) {
1821 mutex_unlock(&hdata->hdmi_mutex);
1822 return;
1823 }
1824 mutex_unlock(&hdata->hdmi_mutex);
1825
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001826 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001827}
1828
Sean Paulf041b252014-01-30 16:19:15 -05001829static void hdmi_poweron(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001830{
Sean Paulf041b252014-01-30 16:19:15 -05001831 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001832 struct hdmi_resources *res = &hdata->res;
1833
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001834 mutex_lock(&hdata->hdmi_mutex);
1835 if (hdata->powered) {
1836 mutex_unlock(&hdata->hdmi_mutex);
1837 return;
1838 }
1839
1840 hdata->powered = true;
1841
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001842 mutex_unlock(&hdata->hdmi_mutex);
1843
Sean Paulaf65c802014-01-30 16:19:27 -05001844 pm_runtime_get_sync(hdata->dev);
1845
Seung-Woo Kimad079452013-06-05 14:34:38 +09001846 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1847 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1848
Sean Paul0bfb1f82013-06-11 12:24:02 +05301849 clk_prepare_enable(res->hdmiphy);
1850 clk_prepare_enable(res->hdmi);
1851 clk_prepare_enable(res->sclk_hdmi);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301852
1853 hdmiphy_poweron(hdata);
Sean Paulf041b252014-01-30 16:19:15 -05001854 hdmi_commit(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001855}
1856
Sean Paulf041b252014-01-30 16:19:15 -05001857static void hdmi_poweroff(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001858{
Sean Paulf041b252014-01-30 16:19:15 -05001859 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001860 struct hdmi_resources *res = &hdata->res;
1861
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001862 mutex_lock(&hdata->hdmi_mutex);
1863 if (!hdata->powered)
1864 goto out;
1865 mutex_unlock(&hdata->hdmi_mutex);
1866
1867 /*
1868 * The TV power domain needs any condition of hdmiphy to turn off and
1869 * its reset state seems to meet the condition.
1870 */
1871 hdmiphy_conf_reset(hdata);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301872 hdmiphy_poweroff(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001873
Sean Paul0bfb1f82013-06-11 12:24:02 +05301874 clk_disable_unprepare(res->sclk_hdmi);
1875 clk_disable_unprepare(res->hdmi);
1876 clk_disable_unprepare(res->hdmiphy);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001877 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1878
Sean Paulaf65c802014-01-30 16:19:27 -05001879 pm_runtime_put_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001880
Sean Paulaf65c802014-01-30 16:19:27 -05001881 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001882 hdata->powered = false;
1883
1884out:
1885 mutex_unlock(&hdata->hdmi_mutex);
1886}
1887
Sean Paulf041b252014-01-30 16:19:15 -05001888static void hdmi_dpms(struct exynos_drm_display *display, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001889{
YoungJun Chocbc4c332013-06-12 10:44:40 +09001890 DRM_DEBUG_KMS("mode %d\n", mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001891
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001892 switch (mode) {
1893 case DRM_MODE_DPMS_ON:
Sean Paulaf65c802014-01-30 16:19:27 -05001894 hdmi_poweron(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001895 break;
1896 case DRM_MODE_DPMS_STANDBY:
1897 case DRM_MODE_DPMS_SUSPEND:
1898 case DRM_MODE_DPMS_OFF:
Sean Paulaf65c802014-01-30 16:19:27 -05001899 hdmi_poweroff(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001900 break;
1901 default:
1902 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1903 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001904 }
1905}
1906
Sean Paulf041b252014-01-30 16:19:15 -05001907static struct exynos_drm_display_ops hdmi_display_ops = {
Sean Pauld9716ee2014-01-30 16:19:29 -05001908 .create_connector = hdmi_create_connector,
Sean Paulf041b252014-01-30 16:19:15 -05001909 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001910 .mode_set = hdmi_mode_set,
Sean Paulf041b252014-01-30 16:19:15 -05001911 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001912 .commit = hdmi_commit,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001913};
1914
Sean Paulf041b252014-01-30 16:19:15 -05001915static struct exynos_drm_display hdmi_display = {
1916 .type = EXYNOS_DISPLAY_TYPE_HDMI,
1917 .ops = &hdmi_display_ops,
1918};
1919
Sean Paul77006a72013-01-16 10:17:20 -05001920static irqreturn_t hdmi_irq_thread(int irq, void *arg)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001921{
Sean Paulf041b252014-01-30 16:19:15 -05001922 struct hdmi_context *hdata = arg;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001923
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001924 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301925 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001926 mutex_unlock(&hdata->hdmi_mutex);
1927
Sean Paul45517892014-01-30 16:19:05 -05001928 if (hdata->drm_dev)
1929 drm_helper_hpd_irq_event(hdata->drm_dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001930
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001931 return IRQ_HANDLED;
1932}
1933
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001934static int hdmi_resources_init(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001935{
1936 struct device *dev = hdata->dev;
1937 struct hdmi_resources *res = &hdata->res;
1938 static char *supply[] = {
1939 "hdmi-en",
1940 "vdd",
1941 "vdd_osc",
1942 "vdd_pll",
1943 };
1944 int i, ret;
1945
1946 DRM_DEBUG_KMS("HDMI resource init\n");
1947
Sachin Kamatadc837a2012-08-31 15:50:47 +05301948 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001949
1950 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301951 res->hdmi = devm_clk_get(dev, "hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301952 if (IS_ERR(res->hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001953 DRM_ERROR("failed to get clock 'hdmi'\n");
1954 goto fail;
1955 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301956 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301957 if (IS_ERR(res->sclk_hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001958 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
1959 goto fail;
1960 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301961 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301962 if (IS_ERR(res->sclk_pixel)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001963 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1964 goto fail;
1965 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301966 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301967 if (IS_ERR(res->sclk_hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001968 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
1969 goto fail;
1970 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301971 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301972 if (IS_ERR(res->hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001973 DRM_ERROR("failed to get clock 'hdmiphy'\n");
1974 goto fail;
1975 }
Rahul Sharma59956d32013-06-11 12:24:03 +05301976 res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
1977 if (IS_ERR(res->mout_hdmi)) {
1978 DRM_ERROR("failed to get clock 'mout_hdmi'\n");
1979 goto fail;
1980 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001981
Rahul Sharma59956d32013-06-11 12:24:03 +05301982 clk_set_parent(res->mout_hdmi, res->sclk_pixel);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001983
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301984 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05301985 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09001986 if (!res->regul_bulk)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001987 goto fail;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001988 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
1989 res->regul_bulk[i].supply = supply[i];
1990 res->regul_bulk[i].consumer = NULL;
1991 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301992 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001993 if (ret) {
1994 DRM_ERROR("failed to get regulators\n");
1995 goto fail;
1996 }
1997 res->regul_count = ARRAY_SIZE(supply);
1998
1999 return 0;
2000fail:
2001 DRM_ERROR("HDMI resource init - failed\n");
2002 return -ENODEV;
2003}
2004
Rahul Sharma22c4f422012-10-04 20:48:55 +05302005static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2006 (struct device *dev)
2007{
2008 struct device_node *np = dev->of_node;
2009 struct s5p_hdmi_platform_data *pd;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302010 u32 value;
2011
2012 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09002013 if (!pd)
Rahul Sharma22c4f422012-10-04 20:48:55 +05302014 goto err_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302015
2016 if (!of_find_property(np, "hpd-gpio", &value)) {
2017 DRM_ERROR("no hpd gpio property found\n");
2018 goto err_data;
2019 }
2020
Rahul Sharma5f916e22013-06-11 19:41:29 +05302021 pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302022
2023 return pd;
2024
2025err_data:
2026 return NULL;
2027}
Rahul Sharma22c4f422012-10-04 20:48:55 +05302028
Rahul Sharma22c4f422012-10-04 20:48:55 +05302029static struct of_device_id hdmi_match_types[] = {
2030 {
2031 .compatible = "samsung,exynos5-hdmi",
Inki Daebfe4e842014-03-06 14:18:17 +09002032 .data = &exynos5_hdmi_driver_data,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302033 }, {
Rahul Sharmacc57caf2013-06-19 18:21:07 +05302034 .compatible = "samsung,exynos4212-hdmi",
Inki Daebfe4e842014-03-06 14:18:17 +09002035 .data = &exynos4212_hdmi_driver_data,
Rahul Sharmacc57caf2013-06-19 18:21:07 +05302036 }, {
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302037 /* end node */
2038 }
2039};
2040
Inki Daef37cd5e2014-05-09 14:25:20 +09002041static int hdmi_bind(struct device *dev, struct device *master, void *data)
2042{
2043 struct drm_device *drm_dev = data;
2044 struct hdmi_context *hdata;
2045
2046 hdata = hdmi_display.ctx;
2047 hdata->drm_dev = drm_dev;
2048
2049 return exynos_drm_create_enc_conn(drm_dev, &hdmi_display);
2050}
2051
2052static void hdmi_unbind(struct device *dev, struct device *master, void *data)
2053{
2054 struct exynos_drm_display *display = get_hdmi_display(dev);
2055 struct drm_encoder *encoder = display->encoder;
2056 struct hdmi_context *hdata = display->ctx;
2057
2058 encoder->funcs->destroy(encoder);
2059 drm_connector_cleanup(&hdata->connector);
2060}
2061
2062static const struct component_ops hdmi_component_ops = {
2063 .bind = hdmi_bind,
2064 .unbind = hdmi_unbind,
2065};
2066
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002067static int hdmi_probe(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002068{
Inki Daef37cd5e2014-05-09 14:25:20 +09002069 struct device_node *ddc_node, *phy_node;
2070 struct s5p_hdmi_platform_data *pdata;
2071 struct hdmi_driver_data *drv_data;
2072 const struct of_device_id *match;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002073 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002074 struct hdmi_context *hdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002075 struct resource *res;
2076 int ret;
2077
Inki Daef37cd5e2014-05-09 14:25:20 +09002078 if (!dev->of_node)
Sachin Kamat88c49812013-08-28 10:47:57 +05302079 return -ENODEV;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302080
Sachin Kamat88c49812013-08-28 10:47:57 +05302081 pdata = drm_hdmi_dt_parse_pdata(dev);
2082 if (!pdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002083 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002084
Sachin Kamat88c49812013-08-28 10:47:57 +05302085 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09002086 if (!hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002087 return -ENOMEM;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002088
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002089 mutex_init(&hdata->hdmi_mutex);
2090
Sean Paulf041b252014-01-30 16:19:15 -05002091 platform_set_drvdata(pdev, &hdmi_display);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002092
Sachin Kamat88c49812013-08-28 10:47:57 +05302093 match = of_match_node(hdmi_match_types, dev->of_node);
2094 if (!match)
2095 return -ENODEV;
Inki Daebfe4e842014-03-06 14:18:17 +09002096
2097 drv_data = (struct hdmi_driver_data *)match->data;
2098 hdata->type = drv_data->type;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302099
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302100 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002101 hdata->dev = dev;
2102
2103 ret = hdmi_resources_init(hdata);
2104 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302105 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302106 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002107 }
2108
2109 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002110 hdata->regs = devm_ioremap_resource(dev, res);
Thierry Redingd4ed6022013-01-21 11:09:02 +01002111 if (IS_ERR(hdata->regs))
2112 return PTR_ERR(hdata->regs);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002113
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002114 ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302115 if (ret) {
2116 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302117 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302118 }
2119
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002120 /* DDC i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002121 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
2122 if (!ddc_node) {
2123 DRM_ERROR("Failed to find ddc node in device tree\n");
2124 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002125 }
Inki Dae8fa04aa2014-03-13 16:38:31 +09002126 hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
2127 if (!hdata->ddc_adpt) {
2128 DRM_ERROR("Failed to get ddc i2c adapter by node\n");
Daniel Kurtz2b768132014-02-24 18:52:51 +09002129 return -ENODEV;
2130 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002131
Inki Daebfe4e842014-03-06 14:18:17 +09002132 /* Not support APB PHY yet. */
2133 if (drv_data->is_apb_phy)
2134 return -EPERM;
2135
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002136 /* hdmiphy i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002137 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
2138 if (!phy_node) {
2139 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
2140 ret = -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002141 goto err_ddc;
2142 }
Daniel Kurtz2b768132014-02-24 18:52:51 +09002143 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
2144 if (!hdata->hdmiphy_port) {
2145 DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
2146 ret = -ENODEV;
2147 goto err_ddc;
2148 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002149
Sean Paul77006a72013-01-16 10:17:20 -05002150 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
2151 if (hdata->irq < 0) {
2152 DRM_ERROR("failed to get GPIO irq\n");
2153 ret = hdata->irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002154 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002155 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002156
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302157 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2158
Seung-Woo Kimdcb9a7c2013-05-22 21:14:17 +09002159 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
Sean Paul77006a72013-01-16 10:17:20 -05002160 hdmi_irq_thread, IRQF_TRIGGER_RISING |
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002161 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sean Paulf041b252014-01-30 16:19:15 -05002162 "hdmi", hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002163 if (ret) {
Sean Paul77006a72013-01-16 10:17:20 -05002164 DRM_ERROR("failed to register hdmi interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002165 goto err_hdmiphy;
2166 }
2167
Sean Paulaf65c802014-01-30 16:19:27 -05002168 pm_runtime_enable(dev);
Sean Paulf041b252014-01-30 16:19:15 -05002169 hdmi_display.ctx = hdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002170
Inki Daef37cd5e2014-05-09 14:25:20 +09002171 return exynos_drm_component_add(&pdev->dev, &hdmi_component_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002172
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002173err_hdmiphy:
Daniel Kurtz2b768132014-02-24 18:52:51 +09002174 put_device(&hdata->hdmiphy_port->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002175err_ddc:
Inki Dae8fa04aa2014-03-13 16:38:31 +09002176 put_device(&hdata->ddc_adpt->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002177 return ret;
2178}
2179
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002180static int hdmi_remove(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002181{
Inki Daef37cd5e2014-05-09 14:25:20 +09002182 struct hdmi_context *hdata = hdmi_display.ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002183
Daniel Kurtz2b768132014-02-24 18:52:51 +09002184 put_device(&hdata->hdmiphy_port->dev);
Inki Dae8fa04aa2014-03-13 16:38:31 +09002185 put_device(&hdata->ddc_adpt->dev);
Inki Daef37cd5e2014-05-09 14:25:20 +09002186
Sean Paulaf65c802014-01-30 16:19:27 -05002187 pm_runtime_disable(&pdev->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002188
Inki Daef37cd5e2014-05-09 14:25:20 +09002189 exynos_drm_component_del(&pdev->dev, &hdmi_component_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002190 return 0;
2191}
2192
2193struct platform_driver hdmi_driver = {
2194 .probe = hdmi_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002195 .remove = hdmi_remove,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002196 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302197 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002198 .owner = THIS_MODULE,
Sachin Kamat88c49812013-08-28 10:47:57 +05302199 .of_match_table = hdmi_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002200 },
2201};