blob: 0097032cd350b35a4c6781b908d3d15c434913bb [file] [log] [blame]
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001/*
2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors:
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 *
8 * Based on drivers/media/video/s5p-tv/hdmi_drv.c
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
David Howells760285e2012-10-02 18:01:07 +010017#include <drm/drmP.h>
18#include <drm/drm_edid.h>
19#include <drm/drm_crtc_helper.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090020
21#include "regs-hdmi.h"
22
23#include <linux/kernel.h>
24#include <linux/spinlock.h>
25#include <linux/wait.h>
26#include <linux/i2c.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090027#include <linux/platform_device.h>
28#include <linux/interrupt.h>
29#include <linux/irq.h>
30#include <linux/delay.h>
31#include <linux/pm_runtime.h>
32#include <linux/clk.h>
33#include <linux/regulator/consumer.h>
Rahul Sharma22c4f422012-10-04 20:48:55 +053034#include <linux/io.h>
Sachin Kamat3f1c7812013-08-14 16:38:01 +053035#include <linux/of.h>
Daniel Kurtz2b768132014-02-24 18:52:51 +090036#include <linux/i2c.h>
Rahul Sharma22c4f422012-10-04 20:48:55 +053037#include <linux/of_gpio.h>
Sachin Kamatd34d59b2014-02-04 08:40:18 +053038#include <linux/hdmi.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090039
40#include <drm/exynos_drm.h>
41
42#include "exynos_drm_drv.h"
Sean Paulf041b252014-01-30 16:19:15 -050043#include "exynos_mixer.h"
Seung-Woo Kimd8408322011-12-21 17:39:39 +090044
Tomasz Stanislawskifca57122012-10-04 20:48:46 +053045#include <linux/gpio.h>
46#include <media/s5p_hdmi.h>
47
Sean Paulf041b252014-01-30 16:19:15 -050048#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev))
Sean Pauld9716ee2014-01-30 16:19:29 -050049#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +090050
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053051/* AVI header and aspect ratio */
52#define HDMI_AVI_VERSION 0x02
53#define HDMI_AVI_LENGTH 0x0D
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053054
55/* AUI header info */
56#define HDMI_AUI_VERSION 0x01
57#define HDMI_AUI_LENGTH 0x0A
Shirish S46154152014-03-13 10:58:28 +053058#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
59#define AVI_4_3_CENTER_RATIO 0x9
60#define AVI_16_9_CENTER_RATIO 0xa
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053061
Rahul Sharma5a325072012-10-04 20:48:54 +053062enum hdmi_type {
63 HDMI_TYPE13,
64 HDMI_TYPE14,
65};
66
Joonyoung Shim590f4182012-03-16 18:47:14 +090067struct hdmi_resources {
68 struct clk *hdmi;
69 struct clk *sclk_hdmi;
70 struct clk *sclk_pixel;
71 struct clk *sclk_hdmiphy;
72 struct clk *hdmiphy;
Rahul Sharma59956d32013-06-11 12:24:03 +053073 struct clk *mout_hdmi;
Joonyoung Shim590f4182012-03-16 18:47:14 +090074 struct regulator_bulk_data *regul_bulk;
75 int regul_count;
76};
77
Sean Paul2f7e2ed2013-01-15 08:11:08 -050078struct hdmi_tg_regs {
79 u8 cmd[1];
80 u8 h_fsz[2];
81 u8 hact_st[2];
82 u8 hact_sz[2];
83 u8 v_fsz[2];
84 u8 vsync[2];
85 u8 vsync2[2];
86 u8 vact_st[2];
87 u8 vact_sz[2];
88 u8 field_chg[2];
89 u8 vact_st2[2];
90 u8 vact_st3[2];
91 u8 vact_st4[2];
92 u8 vsync_top_hdmi[2];
93 u8 vsync_bot_hdmi[2];
94 u8 field_top_hdmi[2];
95 u8 field_bot_hdmi[2];
96 u8 tg_3d[1];
97};
98
Rahul Sharma6b986ed2013-03-06 17:33:29 +090099struct hdmi_v13_core_regs {
100 u8 h_blank[2];
101 u8 v_blank[3];
102 u8 h_v_line[3];
103 u8 vsync_pol[1];
104 u8 int_pro_mode[1];
105 u8 v_blank_f[3];
106 u8 h_sync_gen[3];
107 u8 v_sync_gen1[3];
108 u8 v_sync_gen2[3];
109 u8 v_sync_gen3[3];
110};
111
112struct hdmi_v14_core_regs {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500113 u8 h_blank[2];
114 u8 v2_blank[2];
115 u8 v1_blank[2];
116 u8 v_line[2];
117 u8 h_line[2];
118 u8 hsync_pol[1];
119 u8 vsync_pol[1];
120 u8 int_pro_mode[1];
121 u8 v_blank_f0[2];
122 u8 v_blank_f1[2];
123 u8 h_sync_start[2];
124 u8 h_sync_end[2];
125 u8 v_sync_line_bef_2[2];
126 u8 v_sync_line_bef_1[2];
127 u8 v_sync_line_aft_2[2];
128 u8 v_sync_line_aft_1[2];
129 u8 v_sync_line_aft_pxl_2[2];
130 u8 v_sync_line_aft_pxl_1[2];
131 u8 v_blank_f2[2]; /* for 3D mode */
132 u8 v_blank_f3[2]; /* for 3D mode */
133 u8 v_blank_f4[2]; /* for 3D mode */
134 u8 v_blank_f5[2]; /* for 3D mode */
135 u8 v_sync_line_aft_3[2];
136 u8 v_sync_line_aft_4[2];
137 u8 v_sync_line_aft_5[2];
138 u8 v_sync_line_aft_6[2];
139 u8 v_sync_line_aft_pxl_3[2];
140 u8 v_sync_line_aft_pxl_4[2];
141 u8 v_sync_line_aft_pxl_5[2];
142 u8 v_sync_line_aft_pxl_6[2];
143 u8 vact_space_1[2];
144 u8 vact_space_2[2];
145 u8 vact_space_3[2];
146 u8 vact_space_4[2];
147 u8 vact_space_5[2];
148 u8 vact_space_6[2];
149};
150
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900151struct hdmi_v13_conf {
152 struct hdmi_v13_core_regs core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500153 struct hdmi_tg_regs tg;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900154};
155
156struct hdmi_v14_conf {
157 struct hdmi_v14_core_regs core;
158 struct hdmi_tg_regs tg;
159};
160
161struct hdmi_conf_regs {
162 int pixel_clock;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500163 int cea_video_id;
Shirish S46154152014-03-13 10:58:28 +0530164 enum hdmi_picture_aspect aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900165 union {
166 struct hdmi_v13_conf v13_conf;
167 struct hdmi_v14_conf v14_conf;
168 } conf;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500169};
170
Joonyoung Shim590f4182012-03-16 18:47:14 +0900171struct hdmi_context {
172 struct device *dev;
173 struct drm_device *drm_dev;
Sean Pauld9716ee2014-01-30 16:19:29 -0500174 struct drm_connector connector;
175 struct drm_encoder *encoder;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900176 bool hpd;
177 bool powered;
Seung-Woo Kim872d20d2012-04-24 17:39:15 +0900178 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900179 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900180
Joonyoung Shim590f4182012-03-16 18:47:14 +0900181 void __iomem *regs;
Sean Paul77006a72013-01-16 10:17:20 -0500182 int irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900183
184 struct i2c_client *ddc_port;
185 struct i2c_client *hdmiphy_port;
186
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900187 /* current hdmiphy conf regs */
188 struct hdmi_conf_regs mode_conf;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900189
190 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900191
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530192 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530193
194 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900195};
196
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500197struct hdmiphy_config {
198 int pixel_clock;
199 u8 conf[32];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900200};
201
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900202/* list of phy config settings */
203static const struct hdmiphy_config hdmiphy_v13_configs[] = {
204 {
205 .pixel_clock = 27000000,
206 .conf = {
207 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
208 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
209 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
210 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
211 },
212 },
213 {
214 .pixel_clock = 27027000,
215 .conf = {
216 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
217 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
218 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
219 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
220 },
221 },
222 {
223 .pixel_clock = 74176000,
224 .conf = {
225 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
226 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
227 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
228 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
229 },
230 },
231 {
232 .pixel_clock = 74250000,
233 .conf = {
234 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
235 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
236 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
237 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
238 },
239 },
240 {
241 .pixel_clock = 148500000,
242 .conf = {
243 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
244 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
245 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
246 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
247 },
248 },
249};
250
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500251static const struct hdmiphy_config hdmiphy_v14_configs[] = {
252 {
253 .pixel_clock = 25200000,
254 .conf = {
255 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
256 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
257 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
258 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
259 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900260 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500261 {
262 .pixel_clock = 27000000,
263 .conf = {
264 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
265 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
266 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
267 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
268 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900269 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500270 {
271 .pixel_clock = 27027000,
272 .conf = {
273 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
274 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
275 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
276 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
277 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900278 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500279 {
280 .pixel_clock = 36000000,
281 .conf = {
282 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
283 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
284 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
285 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
286 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900287 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500288 {
289 .pixel_clock = 40000000,
290 .conf = {
291 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
292 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
293 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
294 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
295 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900296 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500297 {
298 .pixel_clock = 65000000,
299 .conf = {
300 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
301 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
302 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
303 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
304 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900305 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500306 {
Shirish Se1d883c2014-03-13 14:28:27 +0900307 .pixel_clock = 71000000,
308 .conf = {
309 0x01, 0x91, 0x1e, 0x15, 0x40, 0x3c, 0xce, 0x08,
310 0x04, 0x20, 0xb2, 0xd8, 0x45, 0xa0, 0xac, 0x80,
311 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
312 0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
313 },
314 },
315 {
316 .pixel_clock = 73250000,
317 .conf = {
318 0x01, 0xd1, 0x1f, 0x15, 0x40, 0x18, 0xe9, 0x08,
319 0x02, 0xa0, 0xb7, 0xd8, 0x45, 0xa0, 0xac, 0x80,
320 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
321 0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
322 },
323 },
324 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500325 .pixel_clock = 74176000,
326 .conf = {
327 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
328 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
329 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
330 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
331 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900332 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500333 {
334 .pixel_clock = 74250000,
335 .conf = {
336 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
337 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
338 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
339 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
340 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900341 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500342 {
343 .pixel_clock = 83500000,
344 .conf = {
345 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
346 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
347 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
348 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
349 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900350 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500351 {
Shirish Se1d883c2014-03-13 14:28:27 +0900352 .pixel_clock = 88750000,
353 .conf = {
354 0x01, 0x91, 0x25, 0x17, 0x40, 0x30, 0xfe, 0x08,
355 0x06, 0x20, 0xde, 0xd8, 0x45, 0xa0, 0xac, 0x80,
356 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
357 0x54, 0x8a, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
358 },
359 },
360 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500361 .pixel_clock = 106500000,
362 .conf = {
363 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
364 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
365 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
366 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
367 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900368 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500369 {
370 .pixel_clock = 108000000,
371 .conf = {
372 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
373 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
374 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
375 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
376 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900377 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500378 {
Shirish Se1d883c2014-03-13 14:28:27 +0900379 .pixel_clock = 115500000,
380 .conf = {
381 0x01, 0xd1, 0x30, 0x1a, 0x40, 0x40, 0x10, 0x04,
382 0x04, 0xa0, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
383 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
384 0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
385 },
386 },
387 {
388 .pixel_clock = 119000000,
389 .conf = {
390 0x01, 0x91, 0x32, 0x14, 0x40, 0x60, 0xd8, 0x08,
391 0x06, 0x20, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
392 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
393 0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
394 },
395 },
396 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500397 .pixel_clock = 146250000,
398 .conf = {
399 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
400 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
401 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
402 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
403 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900404 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500405 {
406 .pixel_clock = 148500000,
407 .conf = {
408 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
409 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
410 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
411 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
412 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900413 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900414};
415
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900416static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
417{
418 return readl(hdata->regs + reg_id);
419}
420
421static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
422 u32 reg_id, u8 value)
423{
424 writeb(value, hdata->regs + reg_id);
425}
426
427static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
428 u32 reg_id, u32 value, u32 mask)
429{
430 u32 old = readl(hdata->regs + reg_id);
431 value = (value & mask) | (old & ~mask);
432 writel(value, hdata->regs + reg_id);
433}
434
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900435static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900436{
437#define DUMPREG(reg_id) \
438 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
439 readl(hdata->regs + reg_id))
440 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
441 DUMPREG(HDMI_INTC_FLAG);
442 DUMPREG(HDMI_INTC_CON);
443 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900444 DUMPREG(HDMI_V13_PHY_RSTOUT);
445 DUMPREG(HDMI_V13_PHY_VPLL);
446 DUMPREG(HDMI_V13_PHY_CMU);
447 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900448
449 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
450 DUMPREG(HDMI_CON_0);
451 DUMPREG(HDMI_CON_1);
452 DUMPREG(HDMI_CON_2);
453 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900454 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900455 DUMPREG(HDMI_STATUS_EN);
456 DUMPREG(HDMI_HPD);
457 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900458 DUMPREG(HDMI_V13_HPD_GEN);
459 DUMPREG(HDMI_V13_DC_CONTROL);
460 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900461
462 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
463 DUMPREG(HDMI_H_BLANK_0);
464 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900465 DUMPREG(HDMI_V13_V_BLANK_0);
466 DUMPREG(HDMI_V13_V_BLANK_1);
467 DUMPREG(HDMI_V13_V_BLANK_2);
468 DUMPREG(HDMI_V13_H_V_LINE_0);
469 DUMPREG(HDMI_V13_H_V_LINE_1);
470 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900471 DUMPREG(HDMI_VSYNC_POL);
472 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900473 DUMPREG(HDMI_V13_V_BLANK_F_0);
474 DUMPREG(HDMI_V13_V_BLANK_F_1);
475 DUMPREG(HDMI_V13_V_BLANK_F_2);
476 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
477 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
478 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
479 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
480 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
481 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
482 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
483 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
484 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
485 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
486 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
487 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900488
489 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
490 DUMPREG(HDMI_TG_CMD);
491 DUMPREG(HDMI_TG_H_FSZ_L);
492 DUMPREG(HDMI_TG_H_FSZ_H);
493 DUMPREG(HDMI_TG_HACT_ST_L);
494 DUMPREG(HDMI_TG_HACT_ST_H);
495 DUMPREG(HDMI_TG_HACT_SZ_L);
496 DUMPREG(HDMI_TG_HACT_SZ_H);
497 DUMPREG(HDMI_TG_V_FSZ_L);
498 DUMPREG(HDMI_TG_V_FSZ_H);
499 DUMPREG(HDMI_TG_VSYNC_L);
500 DUMPREG(HDMI_TG_VSYNC_H);
501 DUMPREG(HDMI_TG_VSYNC2_L);
502 DUMPREG(HDMI_TG_VSYNC2_H);
503 DUMPREG(HDMI_TG_VACT_ST_L);
504 DUMPREG(HDMI_TG_VACT_ST_H);
505 DUMPREG(HDMI_TG_VACT_SZ_L);
506 DUMPREG(HDMI_TG_VACT_SZ_H);
507 DUMPREG(HDMI_TG_FIELD_CHG_L);
508 DUMPREG(HDMI_TG_FIELD_CHG_H);
509 DUMPREG(HDMI_TG_VACT_ST2_L);
510 DUMPREG(HDMI_TG_VACT_ST2_H);
511 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
512 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
513 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
514 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
515 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
516 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
517 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
518 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
519#undef DUMPREG
520}
521
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900522static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
523{
524 int i;
525
526#define DUMPREG(reg_id) \
527 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
528 readl(hdata->regs + reg_id))
529
530 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
531 DUMPREG(HDMI_INTC_CON);
532 DUMPREG(HDMI_INTC_FLAG);
533 DUMPREG(HDMI_HPD_STATUS);
534 DUMPREG(HDMI_INTC_CON_1);
535 DUMPREG(HDMI_INTC_FLAG_1);
536 DUMPREG(HDMI_PHY_STATUS_0);
537 DUMPREG(HDMI_PHY_STATUS_PLL);
538 DUMPREG(HDMI_PHY_CON_0);
539 DUMPREG(HDMI_PHY_RSTOUT);
540 DUMPREG(HDMI_PHY_VPLL);
541 DUMPREG(HDMI_PHY_CMU);
542 DUMPREG(HDMI_CORE_RSTOUT);
543
544 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
545 DUMPREG(HDMI_CON_0);
546 DUMPREG(HDMI_CON_1);
547 DUMPREG(HDMI_CON_2);
548 DUMPREG(HDMI_SYS_STATUS);
549 DUMPREG(HDMI_PHY_STATUS_0);
550 DUMPREG(HDMI_STATUS_EN);
551 DUMPREG(HDMI_HPD);
552 DUMPREG(HDMI_MODE_SEL);
553 DUMPREG(HDMI_ENC_EN);
554 DUMPREG(HDMI_DC_CONTROL);
555 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
556
557 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
558 DUMPREG(HDMI_H_BLANK_0);
559 DUMPREG(HDMI_H_BLANK_1);
560 DUMPREG(HDMI_V2_BLANK_0);
561 DUMPREG(HDMI_V2_BLANK_1);
562 DUMPREG(HDMI_V1_BLANK_0);
563 DUMPREG(HDMI_V1_BLANK_1);
564 DUMPREG(HDMI_V_LINE_0);
565 DUMPREG(HDMI_V_LINE_1);
566 DUMPREG(HDMI_H_LINE_0);
567 DUMPREG(HDMI_H_LINE_1);
568 DUMPREG(HDMI_HSYNC_POL);
569
570 DUMPREG(HDMI_VSYNC_POL);
571 DUMPREG(HDMI_INT_PRO_MODE);
572 DUMPREG(HDMI_V_BLANK_F0_0);
573 DUMPREG(HDMI_V_BLANK_F0_1);
574 DUMPREG(HDMI_V_BLANK_F1_0);
575 DUMPREG(HDMI_V_BLANK_F1_1);
576
577 DUMPREG(HDMI_H_SYNC_START_0);
578 DUMPREG(HDMI_H_SYNC_START_1);
579 DUMPREG(HDMI_H_SYNC_END_0);
580 DUMPREG(HDMI_H_SYNC_END_1);
581
582 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
583 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
584 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
585 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
586
587 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
588 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
589 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
590 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
591
592 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
593 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
594 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
595 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
596
597 DUMPREG(HDMI_V_BLANK_F2_0);
598 DUMPREG(HDMI_V_BLANK_F2_1);
599 DUMPREG(HDMI_V_BLANK_F3_0);
600 DUMPREG(HDMI_V_BLANK_F3_1);
601 DUMPREG(HDMI_V_BLANK_F4_0);
602 DUMPREG(HDMI_V_BLANK_F4_1);
603 DUMPREG(HDMI_V_BLANK_F5_0);
604 DUMPREG(HDMI_V_BLANK_F5_1);
605
606 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
607 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
608 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
609 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
610 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
611 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
612 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
613 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
614
615 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
616 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
617 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
618 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
619 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
620 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
621 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
622 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
623
624 DUMPREG(HDMI_VACT_SPACE_1_0);
625 DUMPREG(HDMI_VACT_SPACE_1_1);
626 DUMPREG(HDMI_VACT_SPACE_2_0);
627 DUMPREG(HDMI_VACT_SPACE_2_1);
628 DUMPREG(HDMI_VACT_SPACE_3_0);
629 DUMPREG(HDMI_VACT_SPACE_3_1);
630 DUMPREG(HDMI_VACT_SPACE_4_0);
631 DUMPREG(HDMI_VACT_SPACE_4_1);
632 DUMPREG(HDMI_VACT_SPACE_5_0);
633 DUMPREG(HDMI_VACT_SPACE_5_1);
634 DUMPREG(HDMI_VACT_SPACE_6_0);
635 DUMPREG(HDMI_VACT_SPACE_6_1);
636
637 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
638 DUMPREG(HDMI_TG_CMD);
639 DUMPREG(HDMI_TG_H_FSZ_L);
640 DUMPREG(HDMI_TG_H_FSZ_H);
641 DUMPREG(HDMI_TG_HACT_ST_L);
642 DUMPREG(HDMI_TG_HACT_ST_H);
643 DUMPREG(HDMI_TG_HACT_SZ_L);
644 DUMPREG(HDMI_TG_HACT_SZ_H);
645 DUMPREG(HDMI_TG_V_FSZ_L);
646 DUMPREG(HDMI_TG_V_FSZ_H);
647 DUMPREG(HDMI_TG_VSYNC_L);
648 DUMPREG(HDMI_TG_VSYNC_H);
649 DUMPREG(HDMI_TG_VSYNC2_L);
650 DUMPREG(HDMI_TG_VSYNC2_H);
651 DUMPREG(HDMI_TG_VACT_ST_L);
652 DUMPREG(HDMI_TG_VACT_ST_H);
653 DUMPREG(HDMI_TG_VACT_SZ_L);
654 DUMPREG(HDMI_TG_VACT_SZ_H);
655 DUMPREG(HDMI_TG_FIELD_CHG_L);
656 DUMPREG(HDMI_TG_FIELD_CHG_H);
657 DUMPREG(HDMI_TG_VACT_ST2_L);
658 DUMPREG(HDMI_TG_VACT_ST2_H);
659 DUMPREG(HDMI_TG_VACT_ST3_L);
660 DUMPREG(HDMI_TG_VACT_ST3_H);
661 DUMPREG(HDMI_TG_VACT_ST4_L);
662 DUMPREG(HDMI_TG_VACT_ST4_H);
663 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
664 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
665 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
666 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
667 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
668 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
669 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
670 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
671 DUMPREG(HDMI_TG_3D);
672
673 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
674 DUMPREG(HDMI_AVI_CON);
675 DUMPREG(HDMI_AVI_HEADER0);
676 DUMPREG(HDMI_AVI_HEADER1);
677 DUMPREG(HDMI_AVI_HEADER2);
678 DUMPREG(HDMI_AVI_CHECK_SUM);
679 DUMPREG(HDMI_VSI_CON);
680 DUMPREG(HDMI_VSI_HEADER0);
681 DUMPREG(HDMI_VSI_HEADER1);
682 DUMPREG(HDMI_VSI_HEADER2);
683 for (i = 0; i < 7; ++i)
684 DUMPREG(HDMI_VSI_DATA(i));
685
686#undef DUMPREG
687}
688
689static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
690{
Rahul Sharma5a325072012-10-04 20:48:54 +0530691 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900692 hdmi_v13_regs_dump(hdata, prefix);
693 else
694 hdmi_v14_regs_dump(hdata, prefix);
695}
696
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530697static u8 hdmi_chksum(struct hdmi_context *hdata,
698 u32 start, u8 len, u32 hdr_sum)
699{
700 int i;
701
702 /* hdr_sum : header0 + header1 + header2
703 * start : start address of packet byte1
704 * len : packet bytes - 1 */
705 for (i = 0; i < len; ++i)
706 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
707
708 /* return 2's complement of 8 bit hdr_sum */
709 return (u8)(~(hdr_sum & 0xff) + 1);
710}
711
712static void hdmi_reg_infoframe(struct hdmi_context *hdata,
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530713 union hdmi_infoframe *infoframe)
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530714{
715 u32 hdr_sum;
716 u8 chksum;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530717 u32 mod;
718 u32 vic;
719
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530720 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
721 if (hdata->dvi_mode) {
722 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
723 HDMI_VSI_CON_DO_NOT_TRANSMIT);
724 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
725 HDMI_AVI_CON_DO_NOT_TRANSMIT);
726 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
727 return;
728 }
729
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530730 switch (infoframe->any.type) {
731 case HDMI_INFOFRAME_TYPE_AVI:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530732 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530733 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
734 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
735 infoframe->any.version);
736 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
737 hdr_sum = infoframe->any.type + infoframe->any.version +
738 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530739
740 /* Output format zero hardcoded ,RGB YBCR selection */
741 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
742 AVI_ACTIVE_FORMAT_VALID |
743 AVI_UNDERSCANNED_DISPLAY_VALID);
744
Shirish S46154152014-03-13 10:58:28 +0530745 /*
746 * Set the aspect ratio as per the mode, mentioned in
747 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
748 */
749 switch (hdata->mode_conf.aspect_ratio) {
750 case HDMI_PICTURE_ASPECT_4_3:
751 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
752 hdata->mode_conf.aspect_ratio |
753 AVI_4_3_CENTER_RATIO);
754 break;
755 case HDMI_PICTURE_ASPECT_16_9:
756 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
757 hdata->mode_conf.aspect_ratio |
758 AVI_16_9_CENTER_RATIO);
759 break;
760 case HDMI_PICTURE_ASPECT_NONE:
761 default:
762 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
763 hdata->mode_conf.aspect_ratio |
764 AVI_SAME_AS_PIC_ASPECT_RATIO);
765 break;
766 }
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530767
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900768 vic = hdata->mode_conf.cea_video_id;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530769 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
770
771 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530772 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530773 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
774 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
775 break;
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530776 case HDMI_INFOFRAME_TYPE_AUDIO:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530777 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530778 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
779 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
780 infoframe->any.version);
781 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
782 hdr_sum = infoframe->any.type + infoframe->any.version +
783 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530784 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530785 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530786 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
787 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
788 break;
789 default:
790 break;
791 }
792}
793
Sean Pauld9716ee2014-01-30 16:19:29 -0500794static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
795 bool force)
Sean Paul45517892014-01-30 16:19:05 -0500796{
Sean Pauld9716ee2014-01-30 16:19:29 -0500797 struct hdmi_context *hdata = ctx_from_connector(connector);
Sean Paul45517892014-01-30 16:19:05 -0500798
Sean Pauld9716ee2014-01-30 16:19:29 -0500799 return hdata->hpd ? connector_status_connected :
800 connector_status_disconnected;
Sean Paul45517892014-01-30 16:19:05 -0500801}
802
Sean Pauld9716ee2014-01-30 16:19:29 -0500803static void hdmi_connector_destroy(struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900804{
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900805}
806
Sean Pauld9716ee2014-01-30 16:19:29 -0500807static struct drm_connector_funcs hdmi_connector_funcs = {
808 .dpms = drm_helper_connector_dpms,
809 .fill_modes = drm_helper_probe_single_connector_modes,
810 .detect = hdmi_detect,
811 .destroy = hdmi_connector_destroy,
812};
813
814static int hdmi_get_modes(struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900815{
Sean Pauld9716ee2014-01-30 16:19:29 -0500816 struct hdmi_context *hdata = ctx_from_connector(connector);
817 struct edid *edid;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900818
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900819 if (!hdata->ddc_port)
Sean Pauld9716ee2014-01-30 16:19:29 -0500820 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900821
Sean Pauld9716ee2014-01-30 16:19:29 -0500822 edid = drm_get_edid(connector, hdata->ddc_port->adapter);
823 if (!edid)
824 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900825
Sean Pauld9716ee2014-01-30 16:19:29 -0500826 hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500827 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
828 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
Sean Pauld9716ee2014-01-30 16:19:29 -0500829 edid->width_cm, edid->height_cm);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500830
Sean Pauld9716ee2014-01-30 16:19:29 -0500831 drm_mode_connector_update_edid_property(connector, edid);
832
833 return drm_add_edid_modes(connector, edid);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900834}
835
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900836static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900837{
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900838 const struct hdmiphy_config *confs;
839 int count, i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900840
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900841 if (hdata->type == HDMI_TYPE13) {
842 confs = hdmiphy_v13_configs;
843 count = ARRAY_SIZE(hdmiphy_v13_configs);
844 } else if (hdata->type == HDMI_TYPE14) {
845 confs = hdmiphy_v14_configs;
846 count = ARRAY_SIZE(hdmiphy_v14_configs);
847 } else
848 return -EINVAL;
Inki Dae1de425b2012-03-16 18:47:04 +0900849
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900850 for (i = 0; i < count; i++)
851 if (confs[i].pixel_clock == pixel_clock)
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500852 return i;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500853
854 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
855 return -EINVAL;
856}
857
Sean Pauld9716ee2014-01-30 16:19:29 -0500858static int hdmi_mode_valid(struct drm_connector *connector,
Sean Paulf041b252014-01-30 16:19:15 -0500859 struct drm_display_mode *mode)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900860{
Sean Pauld9716ee2014-01-30 16:19:29 -0500861 struct hdmi_context *hdata = ctx_from_connector(connector);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900862 int ret;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900863
Rahul Sharma16844fb2013-06-10 14:50:00 +0530864 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
865 mode->hdisplay, mode->vdisplay, mode->vrefresh,
866 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
867 false, mode->clock * 1000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900868
Sean Paulf041b252014-01-30 16:19:15 -0500869 ret = mixer_check_mode(mode);
870 if (ret)
Sean Pauld9716ee2014-01-30 16:19:29 -0500871 return MODE_BAD;
Sean Paulf041b252014-01-30 16:19:15 -0500872
Rahul Sharma16844fb2013-06-10 14:50:00 +0530873 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900874 if (ret < 0)
Sean Pauld9716ee2014-01-30 16:19:29 -0500875 return MODE_BAD;
876
877 return MODE_OK;
878}
879
880static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
881{
882 struct hdmi_context *hdata = ctx_from_connector(connector);
883
884 return hdata->encoder;
885}
886
887static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
888 .get_modes = hdmi_get_modes,
889 .mode_valid = hdmi_mode_valid,
890 .best_encoder = hdmi_best_encoder,
891};
892
893static int hdmi_create_connector(struct exynos_drm_display *display,
894 struct drm_encoder *encoder)
895{
896 struct hdmi_context *hdata = display->ctx;
897 struct drm_connector *connector = &hdata->connector;
898 int ret;
899
900 hdata->encoder = encoder;
901 connector->interlace_allowed = true;
902 connector->polled = DRM_CONNECTOR_POLL_HPD;
903
904 ret = drm_connector_init(hdata->drm_dev, connector,
905 &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
906 if (ret) {
907 DRM_ERROR("Failed to initialize connector with drm\n");
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900908 return ret;
Sean Pauld9716ee2014-01-30 16:19:29 -0500909 }
910
911 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
912 drm_sysfs_connector_add(connector);
913 drm_mode_connector_attach_encoder(connector, encoder);
914
915 return 0;
916}
917
918static int hdmi_initialize(struct exynos_drm_display *display,
919 struct drm_device *drm_dev)
920{
921 struct hdmi_context *hdata = display->ctx;
922
923 hdata->drm_dev = drm_dev;
924
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900925 return 0;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900926}
927
Sean Paulf041b252014-01-30 16:19:15 -0500928static void hdmi_mode_fixup(struct exynos_drm_display *display,
929 struct drm_connector *connector,
930 const struct drm_display_mode *mode,
931 struct drm_display_mode *adjusted_mode)
932{
933 struct drm_display_mode *m;
934 int mode_ok;
935
936 DRM_DEBUG_KMS("%s\n", __FILE__);
937
938 drm_mode_set_crtcinfo(adjusted_mode, 0);
939
Sean Pauld9716ee2014-01-30 16:19:29 -0500940 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
Sean Paulf041b252014-01-30 16:19:15 -0500941
942 /* just return if user desired mode exists. */
Sean Pauld9716ee2014-01-30 16:19:29 -0500943 if (mode_ok == MODE_OK)
Sean Paulf041b252014-01-30 16:19:15 -0500944 return;
945
946 /*
947 * otherwise, find the most suitable mode among modes and change it
948 * to adjusted_mode.
949 */
950 list_for_each_entry(m, &connector->modes, head) {
Sean Pauld9716ee2014-01-30 16:19:29 -0500951 mode_ok = hdmi_mode_valid(connector, m);
Sean Paulf041b252014-01-30 16:19:15 -0500952
Sean Pauld9716ee2014-01-30 16:19:29 -0500953 if (mode_ok == MODE_OK) {
Sean Paulf041b252014-01-30 16:19:15 -0500954 DRM_INFO("desired mode doesn't exist so\n");
955 DRM_INFO("use the most suitable mode among modes.\n");
956
957 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
958 m->hdisplay, m->vdisplay, m->vrefresh);
959
Sean Paul75626852014-01-30 16:19:16 -0500960 drm_mode_copy(adjusted_mode, m);
Sean Paulf041b252014-01-30 16:19:15 -0500961 break;
962 }
963 }
964}
965
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900966static void hdmi_set_acr(u32 freq, u8 *acr)
967{
968 u32 n, cts;
969
970 switch (freq) {
971 case 32000:
972 n = 4096;
973 cts = 27000;
974 break;
975 case 44100:
976 n = 6272;
977 cts = 30000;
978 break;
979 case 88200:
980 n = 12544;
981 cts = 30000;
982 break;
983 case 176400:
984 n = 25088;
985 cts = 30000;
986 break;
987 case 48000:
988 n = 6144;
989 cts = 27000;
990 break;
991 case 96000:
992 n = 12288;
993 cts = 27000;
994 break;
995 case 192000:
996 n = 24576;
997 cts = 27000;
998 break;
999 default:
1000 n = 0;
1001 cts = 0;
1002 break;
1003 }
1004
1005 acr[1] = cts >> 16;
1006 acr[2] = cts >> 8 & 0xff;
1007 acr[3] = cts & 0xff;
1008
1009 acr[4] = n >> 16;
1010 acr[5] = n >> 8 & 0xff;
1011 acr[6] = n & 0xff;
1012}
1013
1014static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1015{
1016 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1017 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1018 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1019 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1020 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1021 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1022 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1023 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1024 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1025
Rahul Sharma5a325072012-10-04 20:48:54 +05301026 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001027 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1028 else
1029 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1030}
1031
1032static void hdmi_audio_init(struct hdmi_context *hdata)
1033{
1034 u32 sample_rate, bits_per_sample, frame_size_code;
1035 u32 data_num, bit_ch, sample_frq;
1036 u32 val;
1037 u8 acr[7];
1038
1039 sample_rate = 44100;
1040 bits_per_sample = 16;
1041 frame_size_code = 0;
1042
1043 switch (bits_per_sample) {
1044 case 20:
1045 data_num = 2;
1046 bit_ch = 1;
1047 break;
1048 case 24:
1049 data_num = 3;
1050 bit_ch = 1;
1051 break;
1052 default:
1053 data_num = 1;
1054 bit_ch = 0;
1055 break;
1056 }
1057
1058 hdmi_set_acr(sample_rate, acr);
1059 hdmi_reg_acr(hdata, acr);
1060
1061 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1062 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1063 | HDMI_I2S_MUX_ENABLE);
1064
1065 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1066 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1067
1068 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1069
1070 sample_frq = (sample_rate == 44100) ? 0 :
1071 (sample_rate == 48000) ? 2 :
1072 (sample_rate == 32000) ? 3 :
1073 (sample_rate == 96000) ? 0xa : 0x0;
1074
1075 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1076 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1077
1078 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1079 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1080
1081 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1082 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1083 | HDMI_I2S_SEL_LRCK(6));
1084 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1085 | HDMI_I2S_SEL_SDATA2(4));
1086 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1087 | HDMI_I2S_SEL_SDATA2(2));
1088 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1089
1090 /* I2S_CON_1 & 2 */
1091 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1092 | HDMI_I2S_L_CH_LOW_POL);
1093 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1094 | HDMI_I2S_SET_BIT_CH(bit_ch)
1095 | HDMI_I2S_SET_SDATA_BIT(data_num)
1096 | HDMI_I2S_BASIC_FORMAT);
1097
1098 /* Configure register related to CUV information */
1099 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1100 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1101 | HDMI_I2S_COPYRIGHT
1102 | HDMI_I2S_LINEAR_PCM
1103 | HDMI_I2S_CONSUMER_FORMAT);
1104 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1105 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1106 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1107 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1108 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1109 HDMI_I2S_ORG_SMP_FREQ_44_1
1110 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1111 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1112
1113 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1114}
1115
1116static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1117{
Seung-Woo Kim872d20d2012-04-24 17:39:15 +09001118 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001119 return;
1120
1121 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1122 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1123 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1124}
1125
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001126static void hdmi_conf_reset(struct hdmi_context *hdata)
1127{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001128 u32 reg;
1129
Rahul Sharma5a325072012-10-04 20:48:54 +05301130 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001131 reg = HDMI_V13_CORE_RSTOUT;
1132 else
1133 reg = HDMI_CORE_RSTOUT;
1134
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001135 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001136 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001137 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001138 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001139 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001140}
1141
1142static void hdmi_conf_init(struct hdmi_context *hdata)
1143{
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301144 union hdmi_infoframe infoframe;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301145
Sean Paul77006a72013-01-16 10:17:20 -05001146 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001147 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1148 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001149
1150 /* choose HDMI mode */
1151 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1152 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1153 /* disable bluescreen */
1154 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001155
Seung-Woo Kim872d20d2012-04-24 17:39:15 +09001156 if (hdata->dvi_mode) {
1157 /* choose DVI mode */
1158 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1159 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1160 hdmi_reg_writeb(hdata, HDMI_CON_2,
1161 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1162 }
1163
Rahul Sharma5a325072012-10-04 20:48:54 +05301164 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001165 /* choose bluescreen (fecal) color */
1166 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1167 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1168 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1169
1170 /* enable AVI packet every vsync, fixes purple line problem */
1171 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1172 /* force RGB, look to CEA-861-D, table 7 for more detail */
1173 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1174 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1175
1176 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1177 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1178 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1179 } else {
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301180 infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
1181 infoframe.any.version = HDMI_AVI_VERSION;
1182 infoframe.any.length = HDMI_AVI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301183 hdmi_reg_infoframe(hdata, &infoframe);
1184
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301185 infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
1186 infoframe.any.version = HDMI_AUI_VERSION;
1187 infoframe.any.length = HDMI_AUI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301188 hdmi_reg_infoframe(hdata, &infoframe);
1189
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001190 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001191 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1192 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001193}
1194
Rahul Sharma16844fb2013-06-10 14:50:00 +05301195static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001196{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001197 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1198 const struct hdmi_v13_core_regs *core =
1199 &hdata->mode_conf.conf.v13_conf.core;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001200 int tries;
1201
1202 /* setting core registers */
1203 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1204 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001205 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1206 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1207 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1208 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1209 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1210 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001211 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1212 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001213 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1214 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1215 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1216 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1217 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1218 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1219 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1220 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1221 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1222 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1223 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1224 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1225 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1226 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1227 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001228 /* Timing generator registers */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001229 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1230 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1231 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1232 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1233 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1234 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1235 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1236 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1237 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1238 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1239 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1240 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1241 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1242 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1243 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1244 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1245 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1246 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1247 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1248 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1249 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1250 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1251 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1252 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1253 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1254 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1255 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1256 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001257
1258 /* waiting for HDMIPHY's PLL to get to steady state */
1259 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001260 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001261 if (val & HDMI_PHY_STATUS_READY)
1262 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001263 usleep_range(1000, 2000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001264 }
1265 /* steady state not achieved */
1266 if (tries == 0) {
1267 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1268 hdmi_regs_dump(hdata, "timing apply");
1269 }
1270
Sean Paul0bfb1f82013-06-11 12:24:02 +05301271 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301272 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301273 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001274
1275 /* enable HDMI and timing generator */
1276 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1277 if (core->int_pro_mode[0])
1278 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1279 HDMI_FIELD_EN);
1280 else
1281 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1282}
1283
Rahul Sharma16844fb2013-06-10 14:50:00 +05301284static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001285{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001286 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1287 const struct hdmi_v14_core_regs *core =
1288 &hdata->mode_conf.conf.v14_conf.core;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001289 int tries;
1290
1291 /* setting core registers */
1292 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1293 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1294 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1295 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1296 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1297 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1298 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1299 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1300 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1301 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1302 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1303 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1304 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1305 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1306 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1307 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1308 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1309 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1310 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1311 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1312 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1313 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1314 core->v_sync_line_bef_2[0]);
1315 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1316 core->v_sync_line_bef_2[1]);
1317 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1318 core->v_sync_line_bef_1[0]);
1319 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1320 core->v_sync_line_bef_1[1]);
1321 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1322 core->v_sync_line_aft_2[0]);
1323 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1324 core->v_sync_line_aft_2[1]);
1325 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1326 core->v_sync_line_aft_1[0]);
1327 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1328 core->v_sync_line_aft_1[1]);
1329 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1330 core->v_sync_line_aft_pxl_2[0]);
1331 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1332 core->v_sync_line_aft_pxl_2[1]);
1333 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1334 core->v_sync_line_aft_pxl_1[0]);
1335 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1336 core->v_sync_line_aft_pxl_1[1]);
1337 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1338 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1339 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1340 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1341 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1342 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1343 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1344 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1345 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1346 core->v_sync_line_aft_3[0]);
1347 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1348 core->v_sync_line_aft_3[1]);
1349 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1350 core->v_sync_line_aft_4[0]);
1351 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1352 core->v_sync_line_aft_4[1]);
1353 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1354 core->v_sync_line_aft_5[0]);
1355 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1356 core->v_sync_line_aft_5[1]);
1357 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1358 core->v_sync_line_aft_6[0]);
1359 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1360 core->v_sync_line_aft_6[1]);
1361 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1362 core->v_sync_line_aft_pxl_3[0]);
1363 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1364 core->v_sync_line_aft_pxl_3[1]);
1365 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1366 core->v_sync_line_aft_pxl_4[0]);
1367 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1368 core->v_sync_line_aft_pxl_4[1]);
1369 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1370 core->v_sync_line_aft_pxl_5[0]);
1371 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1372 core->v_sync_line_aft_pxl_5[1]);
1373 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1374 core->v_sync_line_aft_pxl_6[0]);
1375 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1376 core->v_sync_line_aft_pxl_6[1]);
1377 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1378 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1379 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1380 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1381 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1382 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1383 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1384 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1385 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1386 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1387 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1388 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1389
1390 /* Timing generator registers */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001391 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1392 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1393 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1394 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1395 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1396 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1397 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1398 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1399 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1400 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1401 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1402 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1403 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1404 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1405 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1406 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1407 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1408 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1409 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1410 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1411 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
1412 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
1413 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
1414 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
1415 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1416 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1417 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1418 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1419 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1420 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1421 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1422 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1423 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001424
1425 /* waiting for HDMIPHY's PLL to get to steady state */
1426 for (tries = 100; tries; --tries) {
1427 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1428 if (val & HDMI_PHY_STATUS_READY)
1429 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001430 usleep_range(1000, 2000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001431 }
1432 /* steady state not achieved */
1433 if (tries == 0) {
1434 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1435 hdmi_regs_dump(hdata, "timing apply");
1436 }
1437
Sean Paul0bfb1f82013-06-11 12:24:02 +05301438 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301439 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301440 clk_prepare_enable(hdata->res.sclk_hdmi);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001441
1442 /* enable HDMI and timing generator */
1443 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1444 if (core->int_pro_mode[0])
1445 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1446 HDMI_FIELD_EN);
1447 else
1448 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1449}
1450
Rahul Sharma16844fb2013-06-10 14:50:00 +05301451static void hdmi_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001452{
Rahul Sharma5a325072012-10-04 20:48:54 +05301453 if (hdata->type == HDMI_TYPE13)
Rahul Sharma16844fb2013-06-10 14:50:00 +05301454 hdmi_v13_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001455 else
Rahul Sharma16844fb2013-06-10 14:50:00 +05301456 hdmi_v14_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001457}
1458
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001459static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1460{
1461 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001462 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001463
Sean Paul0bfb1f82013-06-11 12:24:02 +05301464 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301465 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301466 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001467
1468 /* operation mode */
1469 buffer[0] = 0x1f;
1470 buffer[1] = 0x00;
1471
1472 if (hdata->hdmiphy_port)
1473 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1474
Rahul Sharma5a325072012-10-04 20:48:54 +05301475 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001476 reg = HDMI_V13_PHY_RSTOUT;
1477 else
1478 reg = HDMI_PHY_RSTOUT;
1479
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001480 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001481 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001482 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001483 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001484 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001485}
1486
Rahul Sharmaa5562252012-11-28 11:30:25 +05301487static void hdmiphy_poweron(struct hdmi_context *hdata)
1488{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301489 if (hdata->type == HDMI_TYPE14)
1490 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
1491 HDMI_PHY_POWER_OFF_EN);
1492}
1493
1494static void hdmiphy_poweroff(struct hdmi_context *hdata)
1495{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301496 if (hdata->type == HDMI_TYPE14)
1497 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
1498 HDMI_PHY_POWER_OFF_EN);
1499}
1500
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001501static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1502{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001503 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001504 u8 buffer[32];
1505 u8 operation[2];
1506 u8 read_buffer[32] = {0, };
1507 int ret;
1508 int i;
1509
1510 if (!hdata->hdmiphy_port) {
1511 DRM_ERROR("hdmiphy is not attached\n");
1512 return;
1513 }
1514
1515 /* pixel clock */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001516 i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);
1517 if (i < 0) {
1518 DRM_ERROR("failed to find hdmiphy conf\n");
1519 return;
1520 }
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001521
Sachin Kamat5f46c332013-04-26 11:29:00 +05301522 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001523 hdmiphy_data = hdmiphy_v13_configs[i].conf;
Sachin Kamat5f46c332013-04-26 11:29:00 +05301524 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001525 hdmiphy_data = hdmiphy_v14_configs[i].conf;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001526
1527 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001528 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1529 if (ret != 32) {
1530 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1531 return;
1532 }
1533
Sean Paul09760ea2013-01-14 17:03:20 -05001534 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001535
1536 /* operation mode */
1537 operation[0] = 0x1f;
1538 operation[1] = 0x80;
1539
1540 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1541 if (ret != 2) {
1542 DRM_ERROR("failed to enable hdmiphy\n");
1543 return;
1544 }
1545
1546 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1547 if (ret < 0) {
1548 DRM_ERROR("failed to read hdmiphy config\n");
1549 return;
1550 }
1551
1552 for (i = 0; i < ret; i++)
1553 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1554 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1555}
1556
1557static void hdmi_conf_apply(struct hdmi_context *hdata)
1558{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001559 hdmiphy_conf_reset(hdata);
1560 hdmiphy_conf_apply(hdata);
1561
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001562 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001563 hdmi_conf_reset(hdata);
1564 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001565 mutex_unlock(&hdata->hdmi_mutex);
1566
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001567 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001568
1569 /* setting core registers */
Rahul Sharma16844fb2013-06-10 14:50:00 +05301570 hdmi_mode_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001571 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001572
1573 hdmi_regs_dump(hdata, "start");
1574}
1575
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001576static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1577{
1578 int i;
1579 BUG_ON(num_bytes > 4);
1580 for (i = 0; i < num_bytes; i++)
1581 reg_pair[i] = (value >> (8 * i)) & 0xff;
1582}
1583
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001584static void hdmi_v13_mode_set(struct hdmi_context *hdata,
1585 struct drm_display_mode *m)
1586{
1587 struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core;
1588 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1589 unsigned int val;
1590
1591 hdata->mode_conf.cea_video_id =
1592 drm_match_cea_mode((struct drm_display_mode *)m);
1593 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301594 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001595
1596 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1597 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
1598
1599 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1600 hdmi_set_reg(core->vsync_pol, 1, val);
1601
1602 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1603 hdmi_set_reg(core->int_pro_mode, 1, val);
1604
1605 val = (m->hsync_start - m->hdisplay - 2);
1606 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1607 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1608 hdmi_set_reg(core->h_sync_gen, 3, val);
1609
1610 /*
1611 * Quirk requirement for exynos HDMI IP design,
1612 * 2 pixels less than the actual calculation for hsync_start
1613 * and end.
1614 */
1615
1616 /* Following values & calculations differ for different type of modes */
1617 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1618 /* Interlaced Mode */
1619 val = ((m->vsync_end - m->vdisplay) / 2);
1620 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1621 hdmi_set_reg(core->v_sync_gen1, 3, val);
1622
1623 val = m->vtotal / 2;
1624 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1625 hdmi_set_reg(core->v_blank, 3, val);
1626
1627 val = (m->vtotal +
1628 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1629 val |= m->vtotal << 11;
1630 hdmi_set_reg(core->v_blank_f, 3, val);
1631
1632 val = ((m->vtotal / 2) + 7);
1633 val |= ((m->vtotal / 2) + 2) << 12;
1634 hdmi_set_reg(core->v_sync_gen2, 3, val);
1635
1636 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1637 val |= ((m->htotal / 2) +
1638 (m->hsync_start - m->hdisplay)) << 12;
1639 hdmi_set_reg(core->v_sync_gen3, 3, val);
1640
1641 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1642 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1643
1644 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1645 } else {
1646 /* Progressive Mode */
1647
1648 val = m->vtotal;
1649 val |= (m->vtotal - m->vdisplay) << 11;
1650 hdmi_set_reg(core->v_blank, 3, val);
1651
1652 hdmi_set_reg(core->v_blank_f, 3, 0);
1653
1654 val = (m->vsync_end - m->vdisplay);
1655 val |= ((m->vsync_start - m->vdisplay) << 12);
1656 hdmi_set_reg(core->v_sync_gen1, 3, val);
1657
1658 hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value */
1659 hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value */
1660 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1661 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1662 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1663 }
1664
1665 /* Timing generator registers */
1666 hdmi_set_reg(tg->cmd, 1, 0x0);
1667 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1668 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1669 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1670 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1671 hdmi_set_reg(tg->vsync, 2, 0x1);
1672 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1673 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1674 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1675 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1676 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1677 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1678 hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */
1679}
1680
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001681static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1682 struct drm_display_mode *m)
1683{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001684 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1685 struct hdmi_v14_core_regs *core =
1686 &hdata->mode_conf.conf.v14_conf.core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001687
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001688 hdata->mode_conf.cea_video_id =
1689 drm_match_cea_mode((struct drm_display_mode *)m);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001690 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301691 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001692
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001693 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1694 hdmi_set_reg(core->v_line, 2, m->vtotal);
1695 hdmi_set_reg(core->h_line, 2, m->htotal);
1696 hdmi_set_reg(core->hsync_pol, 1,
1697 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1698 hdmi_set_reg(core->vsync_pol, 1,
1699 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1700 hdmi_set_reg(core->int_pro_mode, 1,
1701 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1702
1703 /*
1704 * Quirk requirement for exynos 5 HDMI IP design,
1705 * 2 pixels less than the actual calculation for hsync_start
1706 * and end.
1707 */
1708
1709 /* Following values & calculations differ for different type of modes */
1710 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1711 /* Interlaced Mode */
1712 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1713 (m->vsync_end - m->vdisplay) / 2);
1714 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1715 (m->vsync_start - m->vdisplay) / 2);
1716 hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
1717 hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301718 hdmi_set_reg(core->v_blank_f0, 2, m->vtotal - m->vdisplay / 2);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001719 hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
1720 hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
1721 hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
1722 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
1723 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1724 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
1725 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1726 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1727 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301728 hdmi_set_reg(tg->vact_st2, 2, m->vtotal - m->vdisplay / 2);
1729 hdmi_set_reg(tg->vsync2, 2, (m->vtotal / 2) + 1);
1730 hdmi_set_reg(tg->vsync_bot_hdmi, 2, (m->vtotal / 2) + 1);
1731 hdmi_set_reg(tg->field_bot_hdmi, 2, (m->vtotal / 2) + 1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001732 hdmi_set_reg(tg->vact_st3, 2, 0x0);
1733 hdmi_set_reg(tg->vact_st4, 2, 0x0);
1734 } else {
1735 /* Progressive Mode */
1736 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1737 m->vsync_end - m->vdisplay);
1738 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1739 m->vsync_start - m->vdisplay);
1740 hdmi_set_reg(core->v2_blank, 2, m->vtotal);
1741 hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
1742 hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
1743 hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
1744 hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
1745 hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
1746 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
1747 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
1748 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1749 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1750 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1751 hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
1752 hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
Rahul Sharma14829952013-06-18 18:19:37 +05301753 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1754 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1755 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001756 }
1757
1758 /* Following values & calculations are same irrespective of mode type */
1759 hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
1760 hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
1761 hdmi_set_reg(core->vact_space_1, 2, 0xffff);
1762 hdmi_set_reg(core->vact_space_2, 2, 0xffff);
1763 hdmi_set_reg(core->vact_space_3, 2, 0xffff);
1764 hdmi_set_reg(core->vact_space_4, 2, 0xffff);
1765 hdmi_set_reg(core->vact_space_5, 2, 0xffff);
1766 hdmi_set_reg(core->vact_space_6, 2, 0xffff);
1767 hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
1768 hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
1769 hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
1770 hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
1771 hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
1772 hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
1773 hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
1774 hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
1775 hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
1776 hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
1777 hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
1778 hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
1779
1780 /* Timing generator registers */
1781 hdmi_set_reg(tg->cmd, 1, 0x0);
1782 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1783 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1784 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1785 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1786 hdmi_set_reg(tg->vsync, 2, 0x1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001787 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1788 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001789 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001790 hdmi_set_reg(tg->tg_3d, 1, 0x0);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001791}
1792
Sean Paulf041b252014-01-30 16:19:15 -05001793static void hdmi_mode_set(struct exynos_drm_display *display,
1794 struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001795{
Sean Paulf041b252014-01-30 16:19:15 -05001796 struct hdmi_context *hdata = display->ctx;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001797 struct drm_display_mode *m = mode;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001798
YoungJun Chocbc4c332013-06-12 10:44:40 +09001799 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1800 m->hdisplay, m->vdisplay,
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001801 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1802 "INTERLACED" : "PROGERESSIVE");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001803
Sachin Kamat5f46c332013-04-26 11:29:00 +05301804 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001805 hdmi_v13_mode_set(hdata, mode);
Sachin Kamat5f46c332013-04-26 11:29:00 +05301806 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001807 hdmi_v14_mode_set(hdata, mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001808}
1809
Sean Paulf041b252014-01-30 16:19:15 -05001810static void hdmi_commit(struct exynos_drm_display *display)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001811{
Sean Paulf041b252014-01-30 16:19:15 -05001812 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001813
Shirish Sdda90122013-01-23 22:03:18 -05001814 mutex_lock(&hdata->hdmi_mutex);
1815 if (!hdata->powered) {
1816 mutex_unlock(&hdata->hdmi_mutex);
1817 return;
1818 }
1819 mutex_unlock(&hdata->hdmi_mutex);
1820
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001821 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001822}
1823
Sean Paulf041b252014-01-30 16:19:15 -05001824static void hdmi_poweron(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001825{
Sean Paulf041b252014-01-30 16:19:15 -05001826 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001827 struct hdmi_resources *res = &hdata->res;
1828
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001829 mutex_lock(&hdata->hdmi_mutex);
1830 if (hdata->powered) {
1831 mutex_unlock(&hdata->hdmi_mutex);
1832 return;
1833 }
1834
1835 hdata->powered = true;
1836
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001837 mutex_unlock(&hdata->hdmi_mutex);
1838
Sean Paulaf65c802014-01-30 16:19:27 -05001839 pm_runtime_get_sync(hdata->dev);
1840
Seung-Woo Kimad079452013-06-05 14:34:38 +09001841 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1842 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1843
Sean Paul0bfb1f82013-06-11 12:24:02 +05301844 clk_prepare_enable(res->hdmiphy);
1845 clk_prepare_enable(res->hdmi);
1846 clk_prepare_enable(res->sclk_hdmi);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301847
1848 hdmiphy_poweron(hdata);
Sean Paulf041b252014-01-30 16:19:15 -05001849 hdmi_commit(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001850}
1851
Sean Paulf041b252014-01-30 16:19:15 -05001852static void hdmi_poweroff(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001853{
Sean Paulf041b252014-01-30 16:19:15 -05001854 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001855 struct hdmi_resources *res = &hdata->res;
1856
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001857 mutex_lock(&hdata->hdmi_mutex);
1858 if (!hdata->powered)
1859 goto out;
1860 mutex_unlock(&hdata->hdmi_mutex);
1861
1862 /*
1863 * The TV power domain needs any condition of hdmiphy to turn off and
1864 * its reset state seems to meet the condition.
1865 */
1866 hdmiphy_conf_reset(hdata);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301867 hdmiphy_poweroff(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001868
Sean Paul0bfb1f82013-06-11 12:24:02 +05301869 clk_disable_unprepare(res->sclk_hdmi);
1870 clk_disable_unprepare(res->hdmi);
1871 clk_disable_unprepare(res->hdmiphy);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001872 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1873
Sean Paulaf65c802014-01-30 16:19:27 -05001874 pm_runtime_put_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001875
Sean Paulaf65c802014-01-30 16:19:27 -05001876 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001877 hdata->powered = false;
1878
1879out:
1880 mutex_unlock(&hdata->hdmi_mutex);
1881}
1882
Sean Paulf041b252014-01-30 16:19:15 -05001883static void hdmi_dpms(struct exynos_drm_display *display, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001884{
YoungJun Chocbc4c332013-06-12 10:44:40 +09001885 DRM_DEBUG_KMS("mode %d\n", mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001886
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001887 switch (mode) {
1888 case DRM_MODE_DPMS_ON:
Sean Paulaf65c802014-01-30 16:19:27 -05001889 hdmi_poweron(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001890 break;
1891 case DRM_MODE_DPMS_STANDBY:
1892 case DRM_MODE_DPMS_SUSPEND:
1893 case DRM_MODE_DPMS_OFF:
Sean Paulaf65c802014-01-30 16:19:27 -05001894 hdmi_poweroff(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001895 break;
1896 default:
1897 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1898 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001899 }
1900}
1901
Sean Paulf041b252014-01-30 16:19:15 -05001902static struct exynos_drm_display_ops hdmi_display_ops = {
Sean Paul45517892014-01-30 16:19:05 -05001903 .initialize = hdmi_initialize,
Sean Pauld9716ee2014-01-30 16:19:29 -05001904 .create_connector = hdmi_create_connector,
Sean Paulf041b252014-01-30 16:19:15 -05001905 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001906 .mode_set = hdmi_mode_set,
Sean Paulf041b252014-01-30 16:19:15 -05001907 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001908 .commit = hdmi_commit,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001909};
1910
Sean Paulf041b252014-01-30 16:19:15 -05001911static struct exynos_drm_display hdmi_display = {
1912 .type = EXYNOS_DISPLAY_TYPE_HDMI,
1913 .ops = &hdmi_display_ops,
1914};
1915
Sean Paul77006a72013-01-16 10:17:20 -05001916static irqreturn_t hdmi_irq_thread(int irq, void *arg)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001917{
Sean Paulf041b252014-01-30 16:19:15 -05001918 struct hdmi_context *hdata = arg;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001919
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001920 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301921 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001922 mutex_unlock(&hdata->hdmi_mutex);
1923
Sean Paul45517892014-01-30 16:19:05 -05001924 if (hdata->drm_dev)
1925 drm_helper_hpd_irq_event(hdata->drm_dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001926
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001927 return IRQ_HANDLED;
1928}
1929
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001930static int hdmi_resources_init(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001931{
1932 struct device *dev = hdata->dev;
1933 struct hdmi_resources *res = &hdata->res;
1934 static char *supply[] = {
1935 "hdmi-en",
1936 "vdd",
1937 "vdd_osc",
1938 "vdd_pll",
1939 };
1940 int i, ret;
1941
1942 DRM_DEBUG_KMS("HDMI resource init\n");
1943
Sachin Kamatadc837a2012-08-31 15:50:47 +05301944 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001945
1946 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301947 res->hdmi = devm_clk_get(dev, "hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301948 if (IS_ERR(res->hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001949 DRM_ERROR("failed to get clock 'hdmi'\n");
1950 goto fail;
1951 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301952 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301953 if (IS_ERR(res->sclk_hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001954 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
1955 goto fail;
1956 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301957 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301958 if (IS_ERR(res->sclk_pixel)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001959 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1960 goto fail;
1961 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301962 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301963 if (IS_ERR(res->sclk_hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001964 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
1965 goto fail;
1966 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301967 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301968 if (IS_ERR(res->hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001969 DRM_ERROR("failed to get clock 'hdmiphy'\n");
1970 goto fail;
1971 }
Rahul Sharma59956d32013-06-11 12:24:03 +05301972 res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
1973 if (IS_ERR(res->mout_hdmi)) {
1974 DRM_ERROR("failed to get clock 'mout_hdmi'\n");
1975 goto fail;
1976 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001977
Rahul Sharma59956d32013-06-11 12:24:03 +05301978 clk_set_parent(res->mout_hdmi, res->sclk_pixel);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001979
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301980 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05301981 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09001982 if (!res->regul_bulk)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001983 goto fail;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001984 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
1985 res->regul_bulk[i].supply = supply[i];
1986 res->regul_bulk[i].consumer = NULL;
1987 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301988 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001989 if (ret) {
1990 DRM_ERROR("failed to get regulators\n");
1991 goto fail;
1992 }
1993 res->regul_count = ARRAY_SIZE(supply);
1994
1995 return 0;
1996fail:
1997 DRM_ERROR("HDMI resource init - failed\n");
1998 return -ENODEV;
1999}
2000
Rahul Sharma22c4f422012-10-04 20:48:55 +05302001static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2002 (struct device *dev)
2003{
2004 struct device_node *np = dev->of_node;
2005 struct s5p_hdmi_platform_data *pd;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302006 u32 value;
2007
2008 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09002009 if (!pd)
Rahul Sharma22c4f422012-10-04 20:48:55 +05302010 goto err_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302011
2012 if (!of_find_property(np, "hpd-gpio", &value)) {
2013 DRM_ERROR("no hpd gpio property found\n");
2014 goto err_data;
2015 }
2016
Rahul Sharma5f916e22013-06-11 19:41:29 +05302017 pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302018
2019 return pd;
2020
2021err_data:
2022 return NULL;
2023}
Rahul Sharma22c4f422012-10-04 20:48:55 +05302024
Rahul Sharma22c4f422012-10-04 20:48:55 +05302025static struct of_device_id hdmi_match_types[] = {
2026 {
2027 .compatible = "samsung,exynos5-hdmi",
2028 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302029 }, {
Rahul Sharmacc57caf2013-06-19 18:21:07 +05302030 .compatible = "samsung,exynos4212-hdmi",
2031 .data = (void *)HDMI_TYPE14,
2032 }, {
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302033 /* end node */
2034 }
2035};
2036
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002037static int hdmi_probe(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002038{
2039 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002040 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302041 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002042 struct resource *res;
Sachin Kamat88c49812013-08-28 10:47:57 +05302043 const struct of_device_id *match;
Daniel Kurtz2b768132014-02-24 18:52:51 +09002044 struct device_node *ddc_node, *phy_node;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002045 int ret;
2046
Sachin Kamat88c49812013-08-28 10:47:57 +05302047 if (!dev->of_node)
2048 return -ENODEV;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302049
Sachin Kamat88c49812013-08-28 10:47:57 +05302050 pdata = drm_hdmi_dt_parse_pdata(dev);
2051 if (!pdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002052 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002053
Sachin Kamat88c49812013-08-28 10:47:57 +05302054 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09002055 if (!hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002056 return -ENOMEM;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002057
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002058 mutex_init(&hdata->hdmi_mutex);
2059
Sean Paulf041b252014-01-30 16:19:15 -05002060 platform_set_drvdata(pdev, &hdmi_display);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002061
Sachin Kamat88c49812013-08-28 10:47:57 +05302062 match = of_match_node(hdmi_match_types, dev->of_node);
2063 if (!match)
2064 return -ENODEV;
2065 hdata->type = (enum hdmi_type)match->data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302066
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302067 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002068 hdata->dev = dev;
2069
2070 ret = hdmi_resources_init(hdata);
2071 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302072 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302073 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002074 }
2075
2076 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002077 hdata->regs = devm_ioremap_resource(dev, res);
Thierry Redingd4ed6022013-01-21 11:09:02 +01002078 if (IS_ERR(hdata->regs))
2079 return PTR_ERR(hdata->regs);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002080
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002081 ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302082 if (ret) {
2083 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302084 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302085 }
2086
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002087 /* DDC i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002088 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
2089 if (!ddc_node) {
2090 DRM_ERROR("Failed to find ddc node in device tree\n");
2091 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002092 }
Daniel Kurtz2b768132014-02-24 18:52:51 +09002093 hdata->ddc_port = of_find_i2c_device_by_node(ddc_node);
2094 if (!hdata->ddc_port) {
2095 DRM_ERROR("Failed to get ddc i2c client by node\n");
2096 return -ENODEV;
2097 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002098
2099 /* hdmiphy i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002100 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
2101 if (!phy_node) {
2102 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
2103 ret = -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002104 goto err_ddc;
2105 }
Daniel Kurtz2b768132014-02-24 18:52:51 +09002106 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
2107 if (!hdata->hdmiphy_port) {
2108 DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
2109 ret = -ENODEV;
2110 goto err_ddc;
2111 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002112
Sean Paul77006a72013-01-16 10:17:20 -05002113 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
2114 if (hdata->irq < 0) {
2115 DRM_ERROR("failed to get GPIO irq\n");
2116 ret = hdata->irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002117 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002118 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002119
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302120 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2121
Seung-Woo Kimdcb9a7c2013-05-22 21:14:17 +09002122 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
Sean Paul77006a72013-01-16 10:17:20 -05002123 hdmi_irq_thread, IRQF_TRIGGER_RISING |
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002124 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sean Paulf041b252014-01-30 16:19:15 -05002125 "hdmi", hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002126 if (ret) {
Sean Paul77006a72013-01-16 10:17:20 -05002127 DRM_ERROR("failed to register hdmi interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002128 goto err_hdmiphy;
2129 }
2130
Sean Paulaf65c802014-01-30 16:19:27 -05002131 pm_runtime_enable(dev);
2132
Sean Paulf041b252014-01-30 16:19:15 -05002133 hdmi_display.ctx = hdata;
2134 exynos_drm_display_register(&hdmi_display);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002135
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002136 return 0;
2137
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002138err_hdmiphy:
Daniel Kurtz2b768132014-02-24 18:52:51 +09002139 put_device(&hdata->hdmiphy_port->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002140err_ddc:
Daniel Kurtz2b768132014-02-24 18:52:51 +09002141 put_device(&hdata->ddc_port->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002142 return ret;
2143}
2144
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002145static int hdmi_remove(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002146{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002147 struct device *dev = &pdev->dev;
Sean Paulf041b252014-01-30 16:19:15 -05002148 struct exynos_drm_display *display = get_hdmi_display(dev);
2149 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002150
Daniel Kurtz2b768132014-02-24 18:52:51 +09002151 put_device(&hdata->hdmiphy_port->dev);
2152 put_device(&hdata->ddc_port->dev);
Sean Paulaf65c802014-01-30 16:19:27 -05002153 pm_runtime_disable(&pdev->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002154
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002155 return 0;
2156}
2157
2158struct platform_driver hdmi_driver = {
2159 .probe = hdmi_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002160 .remove = hdmi_remove,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002161 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302162 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002163 .owner = THIS_MODULE,
Sachin Kamat88c49812013-08-28 10:47:57 +05302164 .of_match_table = hdmi_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002165 },
2166};