blob: 256e47252edf678faf0076a5c704de070ca26214 [file] [log] [blame]
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001/*
2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors:
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 *
8 * Based on drivers/media/video/s5p-tv/hdmi_drv.c
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
David Howells760285e2012-10-02 18:01:07 +010017#include <drm/drmP.h>
18#include <drm/drm_edid.h>
19#include <drm/drm_crtc_helper.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090020
21#include "regs-hdmi.h"
22
23#include <linux/kernel.h>
24#include <linux/spinlock.h>
25#include <linux/wait.h>
26#include <linux/i2c.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090027#include <linux/platform_device.h>
28#include <linux/interrupt.h>
29#include <linux/irq.h>
30#include <linux/delay.h>
31#include <linux/pm_runtime.h>
32#include <linux/clk.h>
33#include <linux/regulator/consumer.h>
Rahul Sharma22c4f422012-10-04 20:48:55 +053034#include <linux/io.h>
Sachin Kamat3f1c7812013-08-14 16:38:01 +053035#include <linux/of.h>
Daniel Kurtz2b768132014-02-24 18:52:51 +090036#include <linux/i2c.h>
Rahul Sharma22c4f422012-10-04 20:48:55 +053037#include <linux/of_gpio.h>
Sachin Kamatd34d59b2014-02-04 08:40:18 +053038#include <linux/hdmi.h>
Inki Daef37cd5e2014-05-09 14:25:20 +090039#include <linux/component.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090040
41#include <drm/exynos_drm.h>
42
43#include "exynos_drm_drv.h"
Inki Daef37cd5e2014-05-09 14:25:20 +090044#include "exynos_drm_crtc.h"
Sean Paulf041b252014-01-30 16:19:15 -050045#include "exynos_mixer.h"
Seung-Woo Kimd8408322011-12-21 17:39:39 +090046
Tomasz Stanislawskifca57122012-10-04 20:48:46 +053047#include <linux/gpio.h>
48#include <media/s5p_hdmi.h>
49
Sean Paulf041b252014-01-30 16:19:15 -050050#define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev))
Sean Pauld9716ee2014-01-30 16:19:29 -050051#define ctx_from_connector(c) container_of(c, struct hdmi_context, connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +090052
Sean Paul724fd142014-05-09 15:05:10 +090053#define HOTPLUG_DEBOUNCE_MS 1100
54
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053055/* AVI header and aspect ratio */
56#define HDMI_AVI_VERSION 0x02
57#define HDMI_AVI_LENGTH 0x0D
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053058
59/* AUI header info */
60#define HDMI_AUI_VERSION 0x01
61#define HDMI_AUI_LENGTH 0x0A
Shirish S46154152014-03-13 10:58:28 +053062#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
63#define AVI_4_3_CENTER_RATIO 0x9
64#define AVI_16_9_CENTER_RATIO 0xa
Rahul Sharmaa144c2e2012-11-26 10:52:57 +053065
Rahul Sharma5a325072012-10-04 20:48:54 +053066enum hdmi_type {
67 HDMI_TYPE13,
68 HDMI_TYPE14,
69};
70
Inki Daebfe4e842014-03-06 14:18:17 +090071struct hdmi_driver_data {
72 unsigned int type;
73 unsigned int is_apb_phy:1;
74};
75
Joonyoung Shim590f4182012-03-16 18:47:14 +090076struct hdmi_resources {
77 struct clk *hdmi;
78 struct clk *sclk_hdmi;
79 struct clk *sclk_pixel;
80 struct clk *sclk_hdmiphy;
81 struct clk *hdmiphy;
Rahul Sharma59956d32013-06-11 12:24:03 +053082 struct clk *mout_hdmi;
Joonyoung Shim590f4182012-03-16 18:47:14 +090083 struct regulator_bulk_data *regul_bulk;
84 int regul_count;
85};
86
Sean Paul2f7e2ed2013-01-15 08:11:08 -050087struct hdmi_tg_regs {
88 u8 cmd[1];
89 u8 h_fsz[2];
90 u8 hact_st[2];
91 u8 hact_sz[2];
92 u8 v_fsz[2];
93 u8 vsync[2];
94 u8 vsync2[2];
95 u8 vact_st[2];
96 u8 vact_sz[2];
97 u8 field_chg[2];
98 u8 vact_st2[2];
99 u8 vact_st3[2];
100 u8 vact_st4[2];
101 u8 vsync_top_hdmi[2];
102 u8 vsync_bot_hdmi[2];
103 u8 field_top_hdmi[2];
104 u8 field_bot_hdmi[2];
105 u8 tg_3d[1];
106};
107
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900108struct hdmi_v13_core_regs {
109 u8 h_blank[2];
110 u8 v_blank[3];
111 u8 h_v_line[3];
112 u8 vsync_pol[1];
113 u8 int_pro_mode[1];
114 u8 v_blank_f[3];
115 u8 h_sync_gen[3];
116 u8 v_sync_gen1[3];
117 u8 v_sync_gen2[3];
118 u8 v_sync_gen3[3];
119};
120
121struct hdmi_v14_core_regs {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500122 u8 h_blank[2];
123 u8 v2_blank[2];
124 u8 v1_blank[2];
125 u8 v_line[2];
126 u8 h_line[2];
127 u8 hsync_pol[1];
128 u8 vsync_pol[1];
129 u8 int_pro_mode[1];
130 u8 v_blank_f0[2];
131 u8 v_blank_f1[2];
132 u8 h_sync_start[2];
133 u8 h_sync_end[2];
134 u8 v_sync_line_bef_2[2];
135 u8 v_sync_line_bef_1[2];
136 u8 v_sync_line_aft_2[2];
137 u8 v_sync_line_aft_1[2];
138 u8 v_sync_line_aft_pxl_2[2];
139 u8 v_sync_line_aft_pxl_1[2];
140 u8 v_blank_f2[2]; /* for 3D mode */
141 u8 v_blank_f3[2]; /* for 3D mode */
142 u8 v_blank_f4[2]; /* for 3D mode */
143 u8 v_blank_f5[2]; /* for 3D mode */
144 u8 v_sync_line_aft_3[2];
145 u8 v_sync_line_aft_4[2];
146 u8 v_sync_line_aft_5[2];
147 u8 v_sync_line_aft_6[2];
148 u8 v_sync_line_aft_pxl_3[2];
149 u8 v_sync_line_aft_pxl_4[2];
150 u8 v_sync_line_aft_pxl_5[2];
151 u8 v_sync_line_aft_pxl_6[2];
152 u8 vact_space_1[2];
153 u8 vact_space_2[2];
154 u8 vact_space_3[2];
155 u8 vact_space_4[2];
156 u8 vact_space_5[2];
157 u8 vact_space_6[2];
158};
159
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900160struct hdmi_v13_conf {
161 struct hdmi_v13_core_regs core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500162 struct hdmi_tg_regs tg;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900163};
164
165struct hdmi_v14_conf {
166 struct hdmi_v14_core_regs core;
167 struct hdmi_tg_regs tg;
168};
169
170struct hdmi_conf_regs {
171 int pixel_clock;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500172 int cea_video_id;
Shirish S46154152014-03-13 10:58:28 +0530173 enum hdmi_picture_aspect aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900174 union {
175 struct hdmi_v13_conf v13_conf;
176 struct hdmi_v14_conf v14_conf;
177 } conf;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500178};
179
Joonyoung Shim590f4182012-03-16 18:47:14 +0900180struct hdmi_context {
181 struct device *dev;
182 struct drm_device *drm_dev;
Sean Pauld9716ee2014-01-30 16:19:29 -0500183 struct drm_connector connector;
184 struct drm_encoder *encoder;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900185 bool hpd;
186 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +0900187 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +0900188 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900189
Joonyoung Shim590f4182012-03-16 18:47:14 +0900190 void __iomem *regs;
Sean Paul77006a72013-01-16 10:17:20 -0500191 int irq;
Sean Paul724fd142014-05-09 15:05:10 +0900192 struct delayed_work hotplug_work;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900193
Inki Dae8fa04aa2014-03-13 16:38:31 +0900194 struct i2c_adapter *ddc_adpt;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900195 struct i2c_client *hdmiphy_port;
196
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900197 /* current hdmiphy conf regs */
Rahul Sharmabfa48422014-04-03 20:41:04 +0530198 struct drm_display_mode current_mode;
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900199 struct hdmi_conf_regs mode_conf;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900200
201 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +0900202
Tomasz Stanislawskifca57122012-10-04 20:48:46 +0530203 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +0530204
205 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +0900206};
207
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500208struct hdmiphy_config {
209 int pixel_clock;
210 u8 conf[32];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900211};
212
Jingoo Han153df692014-04-17 19:07:42 +0900213static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
Inki Daebfe4e842014-03-06 14:18:17 +0900214 .type = HDMI_TYPE14,
215};
216
Jingoo Han153df692014-04-17 19:07:42 +0900217static struct hdmi_driver_data exynos5_hdmi_driver_data = {
Inki Daebfe4e842014-03-06 14:18:17 +0900218 .type = HDMI_TYPE14,
219};
220
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900221/* list of phy config settings */
222static const struct hdmiphy_config hdmiphy_v13_configs[] = {
223 {
224 .pixel_clock = 27000000,
225 .conf = {
226 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
227 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
228 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
229 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
230 },
231 },
232 {
233 .pixel_clock = 27027000,
234 .conf = {
235 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
236 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
237 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
238 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
239 },
240 },
241 {
242 .pixel_clock = 74176000,
243 .conf = {
244 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
245 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
246 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
247 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
248 },
249 },
250 {
251 .pixel_clock = 74250000,
252 .conf = {
253 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
254 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
255 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
256 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
257 },
258 },
259 {
260 .pixel_clock = 148500000,
261 .conf = {
262 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
263 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
264 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
265 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
266 },
267 },
268};
269
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500270static const struct hdmiphy_config hdmiphy_v14_configs[] = {
271 {
272 .pixel_clock = 25200000,
273 .conf = {
274 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08,
275 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80,
276 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
277 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
278 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900279 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500280 {
281 .pixel_clock = 27000000,
282 .conf = {
283 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20,
284 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80,
285 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
286 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
287 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900288 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500289 {
290 .pixel_clock = 27027000,
291 .conf = {
292 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
293 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
294 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
295 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
296 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900297 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500298 {
299 .pixel_clock = 36000000,
300 .conf = {
301 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08,
302 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
303 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
304 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
305 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900306 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500307 {
308 .pixel_clock = 40000000,
309 .conf = {
310 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08,
311 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80,
312 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
313 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
314 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900315 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500316 {
317 .pixel_clock = 65000000,
318 .conf = {
319 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08,
320 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80,
321 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
322 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
323 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900324 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500325 {
Shirish Se1d883c2014-03-13 14:28:27 +0900326 .pixel_clock = 71000000,
327 .conf = {
Shirish S96d26532014-05-05 10:27:51 +0530328 0x01, 0xd1, 0x3b, 0x35, 0x40, 0x0c, 0x04, 0x08,
329 0x85, 0xa0, 0x63, 0xd9, 0x45, 0xa0, 0xac, 0x80,
330 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
Shirish Se1d883c2014-03-13 14:28:27 +0900331 0x54, 0xad, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
332 },
333 },
334 {
335 .pixel_clock = 73250000,
336 .conf = {
Shirish S96d26532014-05-05 10:27:51 +0530337 0x01, 0xd1, 0x3d, 0x35, 0x40, 0x18, 0x02, 0x08,
338 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
339 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
Shirish Se1d883c2014-03-13 14:28:27 +0900340 0x54, 0xa8, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
341 },
342 },
343 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500344 .pixel_clock = 74176000,
345 .conf = {
346 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08,
347 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80,
348 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
349 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
350 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900351 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500352 {
353 .pixel_clock = 74250000,
354 .conf = {
355 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
356 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
357 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
358 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
359 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900360 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500361 {
362 .pixel_clock = 83500000,
363 .conf = {
364 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08,
365 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80,
366 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
367 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
368 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900369 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500370 {
371 .pixel_clock = 106500000,
372 .conf = {
373 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08,
374 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
375 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
376 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
377 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900378 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500379 {
380 .pixel_clock = 108000000,
381 .conf = {
382 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08,
383 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
384 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
385 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
386 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900387 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500388 {
Shirish Se1d883c2014-03-13 14:28:27 +0900389 .pixel_clock = 115500000,
390 .conf = {
Shirish S96d26532014-05-05 10:27:51 +0530391 0x01, 0xd1, 0x30, 0x12, 0x40, 0x40, 0x10, 0x08,
392 0x80, 0x80, 0x21, 0xd9, 0x45, 0xa0, 0xac, 0x80,
393 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
Shirish Se1d883c2014-03-13 14:28:27 +0900394 0x54, 0xaa, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
395 },
396 },
397 {
398 .pixel_clock = 119000000,
399 .conf = {
Shirish S96d26532014-05-05 10:27:51 +0530400 0x01, 0xd1, 0x32, 0x1a, 0x40, 0x30, 0xd8, 0x08,
401 0x04, 0xa0, 0x2a, 0xd9, 0x45, 0xa0, 0xac, 0x80,
402 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
Shirish Se1d883c2014-03-13 14:28:27 +0900403 0x54, 0x9d, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
404 },
405 },
406 {
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500407 .pixel_clock = 146250000,
408 .conf = {
409 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08,
410 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
411 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
412 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
413 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900414 },
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500415 {
416 .pixel_clock = 148500000,
417 .conf = {
418 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
419 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
420 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
421 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
422 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900423 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900424};
425
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900426static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
427{
428 return readl(hdata->regs + reg_id);
429}
430
431static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
432 u32 reg_id, u8 value)
433{
434 writeb(value, hdata->regs + reg_id);
435}
436
437static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
438 u32 reg_id, u32 value, u32 mask)
439{
440 u32 old = readl(hdata->regs + reg_id);
441 value = (value & mask) | (old & ~mask);
442 writel(value, hdata->regs + reg_id);
443}
444
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900445static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900446{
447#define DUMPREG(reg_id) \
448 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
449 readl(hdata->regs + reg_id))
450 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
451 DUMPREG(HDMI_INTC_FLAG);
452 DUMPREG(HDMI_INTC_CON);
453 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900454 DUMPREG(HDMI_V13_PHY_RSTOUT);
455 DUMPREG(HDMI_V13_PHY_VPLL);
456 DUMPREG(HDMI_V13_PHY_CMU);
457 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900458
459 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
460 DUMPREG(HDMI_CON_0);
461 DUMPREG(HDMI_CON_1);
462 DUMPREG(HDMI_CON_2);
463 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900464 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900465 DUMPREG(HDMI_STATUS_EN);
466 DUMPREG(HDMI_HPD);
467 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900468 DUMPREG(HDMI_V13_HPD_GEN);
469 DUMPREG(HDMI_V13_DC_CONTROL);
470 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900471
472 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
473 DUMPREG(HDMI_H_BLANK_0);
474 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900475 DUMPREG(HDMI_V13_V_BLANK_0);
476 DUMPREG(HDMI_V13_V_BLANK_1);
477 DUMPREG(HDMI_V13_V_BLANK_2);
478 DUMPREG(HDMI_V13_H_V_LINE_0);
479 DUMPREG(HDMI_V13_H_V_LINE_1);
480 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900481 DUMPREG(HDMI_VSYNC_POL);
482 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900483 DUMPREG(HDMI_V13_V_BLANK_F_0);
484 DUMPREG(HDMI_V13_V_BLANK_F_1);
485 DUMPREG(HDMI_V13_V_BLANK_F_2);
486 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
487 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
488 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
489 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
490 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
491 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
492 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
493 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
494 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
495 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
496 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
497 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900498
499 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
500 DUMPREG(HDMI_TG_CMD);
501 DUMPREG(HDMI_TG_H_FSZ_L);
502 DUMPREG(HDMI_TG_H_FSZ_H);
503 DUMPREG(HDMI_TG_HACT_ST_L);
504 DUMPREG(HDMI_TG_HACT_ST_H);
505 DUMPREG(HDMI_TG_HACT_SZ_L);
506 DUMPREG(HDMI_TG_HACT_SZ_H);
507 DUMPREG(HDMI_TG_V_FSZ_L);
508 DUMPREG(HDMI_TG_V_FSZ_H);
509 DUMPREG(HDMI_TG_VSYNC_L);
510 DUMPREG(HDMI_TG_VSYNC_H);
511 DUMPREG(HDMI_TG_VSYNC2_L);
512 DUMPREG(HDMI_TG_VSYNC2_H);
513 DUMPREG(HDMI_TG_VACT_ST_L);
514 DUMPREG(HDMI_TG_VACT_ST_H);
515 DUMPREG(HDMI_TG_VACT_SZ_L);
516 DUMPREG(HDMI_TG_VACT_SZ_H);
517 DUMPREG(HDMI_TG_FIELD_CHG_L);
518 DUMPREG(HDMI_TG_FIELD_CHG_H);
519 DUMPREG(HDMI_TG_VACT_ST2_L);
520 DUMPREG(HDMI_TG_VACT_ST2_H);
521 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
522 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
523 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
524 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
525 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
526 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
527 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
528 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
529#undef DUMPREG
530}
531
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900532static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
533{
534 int i;
535
536#define DUMPREG(reg_id) \
537 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
538 readl(hdata->regs + reg_id))
539
540 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
541 DUMPREG(HDMI_INTC_CON);
542 DUMPREG(HDMI_INTC_FLAG);
543 DUMPREG(HDMI_HPD_STATUS);
544 DUMPREG(HDMI_INTC_CON_1);
545 DUMPREG(HDMI_INTC_FLAG_1);
546 DUMPREG(HDMI_PHY_STATUS_0);
547 DUMPREG(HDMI_PHY_STATUS_PLL);
548 DUMPREG(HDMI_PHY_CON_0);
549 DUMPREG(HDMI_PHY_RSTOUT);
550 DUMPREG(HDMI_PHY_VPLL);
551 DUMPREG(HDMI_PHY_CMU);
552 DUMPREG(HDMI_CORE_RSTOUT);
553
554 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
555 DUMPREG(HDMI_CON_0);
556 DUMPREG(HDMI_CON_1);
557 DUMPREG(HDMI_CON_2);
558 DUMPREG(HDMI_SYS_STATUS);
559 DUMPREG(HDMI_PHY_STATUS_0);
560 DUMPREG(HDMI_STATUS_EN);
561 DUMPREG(HDMI_HPD);
562 DUMPREG(HDMI_MODE_SEL);
563 DUMPREG(HDMI_ENC_EN);
564 DUMPREG(HDMI_DC_CONTROL);
565 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
566
567 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
568 DUMPREG(HDMI_H_BLANK_0);
569 DUMPREG(HDMI_H_BLANK_1);
570 DUMPREG(HDMI_V2_BLANK_0);
571 DUMPREG(HDMI_V2_BLANK_1);
572 DUMPREG(HDMI_V1_BLANK_0);
573 DUMPREG(HDMI_V1_BLANK_1);
574 DUMPREG(HDMI_V_LINE_0);
575 DUMPREG(HDMI_V_LINE_1);
576 DUMPREG(HDMI_H_LINE_0);
577 DUMPREG(HDMI_H_LINE_1);
578 DUMPREG(HDMI_HSYNC_POL);
579
580 DUMPREG(HDMI_VSYNC_POL);
581 DUMPREG(HDMI_INT_PRO_MODE);
582 DUMPREG(HDMI_V_BLANK_F0_0);
583 DUMPREG(HDMI_V_BLANK_F0_1);
584 DUMPREG(HDMI_V_BLANK_F1_0);
585 DUMPREG(HDMI_V_BLANK_F1_1);
586
587 DUMPREG(HDMI_H_SYNC_START_0);
588 DUMPREG(HDMI_H_SYNC_START_1);
589 DUMPREG(HDMI_H_SYNC_END_0);
590 DUMPREG(HDMI_H_SYNC_END_1);
591
592 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
593 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
594 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
595 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
596
597 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
598 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
599 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
600 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
601
602 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
603 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
604 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
605 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
606
607 DUMPREG(HDMI_V_BLANK_F2_0);
608 DUMPREG(HDMI_V_BLANK_F2_1);
609 DUMPREG(HDMI_V_BLANK_F3_0);
610 DUMPREG(HDMI_V_BLANK_F3_1);
611 DUMPREG(HDMI_V_BLANK_F4_0);
612 DUMPREG(HDMI_V_BLANK_F4_1);
613 DUMPREG(HDMI_V_BLANK_F5_0);
614 DUMPREG(HDMI_V_BLANK_F5_1);
615
616 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
617 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
618 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
619 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
620 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
621 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
622 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
623 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
624
625 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
626 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
627 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
628 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
629 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
630 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
631 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
632 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
633
634 DUMPREG(HDMI_VACT_SPACE_1_0);
635 DUMPREG(HDMI_VACT_SPACE_1_1);
636 DUMPREG(HDMI_VACT_SPACE_2_0);
637 DUMPREG(HDMI_VACT_SPACE_2_1);
638 DUMPREG(HDMI_VACT_SPACE_3_0);
639 DUMPREG(HDMI_VACT_SPACE_3_1);
640 DUMPREG(HDMI_VACT_SPACE_4_0);
641 DUMPREG(HDMI_VACT_SPACE_4_1);
642 DUMPREG(HDMI_VACT_SPACE_5_0);
643 DUMPREG(HDMI_VACT_SPACE_5_1);
644 DUMPREG(HDMI_VACT_SPACE_6_0);
645 DUMPREG(HDMI_VACT_SPACE_6_1);
646
647 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
648 DUMPREG(HDMI_TG_CMD);
649 DUMPREG(HDMI_TG_H_FSZ_L);
650 DUMPREG(HDMI_TG_H_FSZ_H);
651 DUMPREG(HDMI_TG_HACT_ST_L);
652 DUMPREG(HDMI_TG_HACT_ST_H);
653 DUMPREG(HDMI_TG_HACT_SZ_L);
654 DUMPREG(HDMI_TG_HACT_SZ_H);
655 DUMPREG(HDMI_TG_V_FSZ_L);
656 DUMPREG(HDMI_TG_V_FSZ_H);
657 DUMPREG(HDMI_TG_VSYNC_L);
658 DUMPREG(HDMI_TG_VSYNC_H);
659 DUMPREG(HDMI_TG_VSYNC2_L);
660 DUMPREG(HDMI_TG_VSYNC2_H);
661 DUMPREG(HDMI_TG_VACT_ST_L);
662 DUMPREG(HDMI_TG_VACT_ST_H);
663 DUMPREG(HDMI_TG_VACT_SZ_L);
664 DUMPREG(HDMI_TG_VACT_SZ_H);
665 DUMPREG(HDMI_TG_FIELD_CHG_L);
666 DUMPREG(HDMI_TG_FIELD_CHG_H);
667 DUMPREG(HDMI_TG_VACT_ST2_L);
668 DUMPREG(HDMI_TG_VACT_ST2_H);
669 DUMPREG(HDMI_TG_VACT_ST3_L);
670 DUMPREG(HDMI_TG_VACT_ST3_H);
671 DUMPREG(HDMI_TG_VACT_ST4_L);
672 DUMPREG(HDMI_TG_VACT_ST4_H);
673 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
674 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
675 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
676 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
677 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
678 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
679 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
680 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
681 DUMPREG(HDMI_TG_3D);
682
683 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
684 DUMPREG(HDMI_AVI_CON);
685 DUMPREG(HDMI_AVI_HEADER0);
686 DUMPREG(HDMI_AVI_HEADER1);
687 DUMPREG(HDMI_AVI_HEADER2);
688 DUMPREG(HDMI_AVI_CHECK_SUM);
689 DUMPREG(HDMI_VSI_CON);
690 DUMPREG(HDMI_VSI_HEADER0);
691 DUMPREG(HDMI_VSI_HEADER1);
692 DUMPREG(HDMI_VSI_HEADER2);
693 for (i = 0; i < 7; ++i)
694 DUMPREG(HDMI_VSI_DATA(i));
695
696#undef DUMPREG
697}
698
699static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
700{
Rahul Sharma5a325072012-10-04 20:48:54 +0530701 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900702 hdmi_v13_regs_dump(hdata, prefix);
703 else
704 hdmi_v14_regs_dump(hdata, prefix);
705}
706
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530707static u8 hdmi_chksum(struct hdmi_context *hdata,
708 u32 start, u8 len, u32 hdr_sum)
709{
710 int i;
711
712 /* hdr_sum : header0 + header1 + header2
713 * start : start address of packet byte1
714 * len : packet bytes - 1 */
715 for (i = 0; i < len; ++i)
716 hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
717
718 /* return 2's complement of 8 bit hdr_sum */
719 return (u8)(~(hdr_sum & 0xff) + 1);
720}
721
722static void hdmi_reg_infoframe(struct hdmi_context *hdata,
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530723 union hdmi_infoframe *infoframe)
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530724{
725 u32 hdr_sum;
726 u8 chksum;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530727 u32 mod;
728 u32 vic;
729
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530730 mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
731 if (hdata->dvi_mode) {
732 hdmi_reg_writeb(hdata, HDMI_VSI_CON,
733 HDMI_VSI_CON_DO_NOT_TRANSMIT);
734 hdmi_reg_writeb(hdata, HDMI_AVI_CON,
735 HDMI_AVI_CON_DO_NOT_TRANSMIT);
736 hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
737 return;
738 }
739
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530740 switch (infoframe->any.type) {
741 case HDMI_INFOFRAME_TYPE_AVI:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530742 hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530743 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
744 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
745 infoframe->any.version);
746 hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
747 hdr_sum = infoframe->any.type + infoframe->any.version +
748 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530749
750 /* Output format zero hardcoded ,RGB YBCR selection */
751 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
752 AVI_ACTIVE_FORMAT_VALID |
753 AVI_UNDERSCANNED_DISPLAY_VALID);
754
Shirish S46154152014-03-13 10:58:28 +0530755 /*
756 * Set the aspect ratio as per the mode, mentioned in
757 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
758 */
759 switch (hdata->mode_conf.aspect_ratio) {
760 case HDMI_PICTURE_ASPECT_4_3:
761 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
762 hdata->mode_conf.aspect_ratio |
763 AVI_4_3_CENTER_RATIO);
764 break;
765 case HDMI_PICTURE_ASPECT_16_9:
766 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
767 hdata->mode_conf.aspect_ratio |
768 AVI_16_9_CENTER_RATIO);
769 break;
770 case HDMI_PICTURE_ASPECT_NONE:
771 default:
772 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2),
773 hdata->mode_conf.aspect_ratio |
774 AVI_SAME_AS_PIC_ASPECT_RATIO);
775 break;
776 }
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530777
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900778 vic = hdata->mode_conf.cea_video_id;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530779 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic);
780
781 chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530782 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530783 DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
784 hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
785 break;
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530786 case HDMI_INFOFRAME_TYPE_AUDIO:
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530787 hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530788 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
789 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
790 infoframe->any.version);
791 hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
792 hdr_sum = infoframe->any.type + infoframe->any.version +
793 infoframe->any.length;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530794 chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
Sachin Kamatd34d59b2014-02-04 08:40:18 +0530795 infoframe->any.length, hdr_sum);
Rahul Sharmaa144c2e2012-11-26 10:52:57 +0530796 DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
797 hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
798 break;
799 default:
800 break;
801 }
802}
803
Sean Pauld9716ee2014-01-30 16:19:29 -0500804static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
805 bool force)
Sean Paul45517892014-01-30 16:19:05 -0500806{
Sean Pauld9716ee2014-01-30 16:19:29 -0500807 struct hdmi_context *hdata = ctx_from_connector(connector);
Sean Paul45517892014-01-30 16:19:05 -0500808
Sean Paul5137c8c2014-04-03 20:41:03 +0530809 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
810
Sean Pauld9716ee2014-01-30 16:19:29 -0500811 return hdata->hpd ? connector_status_connected :
812 connector_status_disconnected;
Sean Paul45517892014-01-30 16:19:05 -0500813}
814
Sean Pauld9716ee2014-01-30 16:19:29 -0500815static void hdmi_connector_destroy(struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900816{
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900817}
818
Sean Pauld9716ee2014-01-30 16:19:29 -0500819static struct drm_connector_funcs hdmi_connector_funcs = {
820 .dpms = drm_helper_connector_dpms,
821 .fill_modes = drm_helper_probe_single_connector_modes,
822 .detect = hdmi_detect,
823 .destroy = hdmi_connector_destroy,
824};
825
826static int hdmi_get_modes(struct drm_connector *connector)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900827{
Sean Pauld9716ee2014-01-30 16:19:29 -0500828 struct hdmi_context *hdata = ctx_from_connector(connector);
829 struct edid *edid;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900830
Inki Dae8fa04aa2014-03-13 16:38:31 +0900831 if (!hdata->ddc_adpt)
Sean Pauld9716ee2014-01-30 16:19:29 -0500832 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900833
Inki Dae8fa04aa2014-03-13 16:38:31 +0900834 edid = drm_get_edid(connector, hdata->ddc_adpt);
Sean Pauld9716ee2014-01-30 16:19:29 -0500835 if (!edid)
836 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900837
Sean Pauld9716ee2014-01-30 16:19:29 -0500838 hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500839 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
840 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
Sean Pauld9716ee2014-01-30 16:19:29 -0500841 edid->width_cm, edid->height_cm);
Rahul Sharma9c08e4b2013-01-04 07:59:11 -0500842
Sean Pauld9716ee2014-01-30 16:19:29 -0500843 drm_mode_connector_update_edid_property(connector, edid);
844
845 return drm_add_edid_modes(connector, edid);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900846}
847
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900848static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900849{
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900850 const struct hdmiphy_config *confs;
851 int count, i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900852
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900853 if (hdata->type == HDMI_TYPE13) {
854 confs = hdmiphy_v13_configs;
855 count = ARRAY_SIZE(hdmiphy_v13_configs);
856 } else if (hdata->type == HDMI_TYPE14) {
857 confs = hdmiphy_v14_configs;
858 count = ARRAY_SIZE(hdmiphy_v14_configs);
859 } else
860 return -EINVAL;
Inki Dae1de425b2012-03-16 18:47:04 +0900861
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900862 for (i = 0; i < count; i++)
863 if (confs[i].pixel_clock == pixel_clock)
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500864 return i;
Sean Paul2f7e2ed2013-01-15 08:11:08 -0500865
866 DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
867 return -EINVAL;
868}
869
Sean Pauld9716ee2014-01-30 16:19:29 -0500870static int hdmi_mode_valid(struct drm_connector *connector,
Sean Paulf041b252014-01-30 16:19:15 -0500871 struct drm_display_mode *mode)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900872{
Sean Pauld9716ee2014-01-30 16:19:29 -0500873 struct hdmi_context *hdata = ctx_from_connector(connector);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900874 int ret;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900875
Rahul Sharma16844fb2013-06-10 14:50:00 +0530876 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
877 mode->hdisplay, mode->vdisplay, mode->vrefresh,
878 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
879 false, mode->clock * 1000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900880
Sean Paulf041b252014-01-30 16:19:15 -0500881 ret = mixer_check_mode(mode);
882 if (ret)
Sean Pauld9716ee2014-01-30 16:19:29 -0500883 return MODE_BAD;
Sean Paulf041b252014-01-30 16:19:15 -0500884
Rahul Sharma16844fb2013-06-10 14:50:00 +0530885 ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900886 if (ret < 0)
Sean Pauld9716ee2014-01-30 16:19:29 -0500887 return MODE_BAD;
888
889 return MODE_OK;
890}
891
892static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
893{
894 struct hdmi_context *hdata = ctx_from_connector(connector);
895
896 return hdata->encoder;
897}
898
899static struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
900 .get_modes = hdmi_get_modes,
901 .mode_valid = hdmi_mode_valid,
902 .best_encoder = hdmi_best_encoder,
903};
904
905static int hdmi_create_connector(struct exynos_drm_display *display,
906 struct drm_encoder *encoder)
907{
908 struct hdmi_context *hdata = display->ctx;
909 struct drm_connector *connector = &hdata->connector;
910 int ret;
911
912 hdata->encoder = encoder;
913 connector->interlace_allowed = true;
914 connector->polled = DRM_CONNECTOR_POLL_HPD;
915
916 ret = drm_connector_init(hdata->drm_dev, connector,
917 &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
918 if (ret) {
919 DRM_ERROR("Failed to initialize connector with drm\n");
Rahul Sharma6b986ed2013-03-06 17:33:29 +0900920 return ret;
Sean Pauld9716ee2014-01-30 16:19:29 -0500921 }
922
923 drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
924 drm_sysfs_connector_add(connector);
925 drm_mode_connector_attach_encoder(connector, encoder);
926
927 return 0;
928}
929
Sean Paulf041b252014-01-30 16:19:15 -0500930static void hdmi_mode_fixup(struct exynos_drm_display *display,
931 struct drm_connector *connector,
932 const struct drm_display_mode *mode,
933 struct drm_display_mode *adjusted_mode)
934{
935 struct drm_display_mode *m;
936 int mode_ok;
937
938 DRM_DEBUG_KMS("%s\n", __FILE__);
939
940 drm_mode_set_crtcinfo(adjusted_mode, 0);
941
Sean Pauld9716ee2014-01-30 16:19:29 -0500942 mode_ok = hdmi_mode_valid(connector, adjusted_mode);
Sean Paulf041b252014-01-30 16:19:15 -0500943
944 /* just return if user desired mode exists. */
Sean Pauld9716ee2014-01-30 16:19:29 -0500945 if (mode_ok == MODE_OK)
Sean Paulf041b252014-01-30 16:19:15 -0500946 return;
947
948 /*
949 * otherwise, find the most suitable mode among modes and change it
950 * to adjusted_mode.
951 */
952 list_for_each_entry(m, &connector->modes, head) {
Sean Pauld9716ee2014-01-30 16:19:29 -0500953 mode_ok = hdmi_mode_valid(connector, m);
Sean Paulf041b252014-01-30 16:19:15 -0500954
Sean Pauld9716ee2014-01-30 16:19:29 -0500955 if (mode_ok == MODE_OK) {
Sean Paulf041b252014-01-30 16:19:15 -0500956 DRM_INFO("desired mode doesn't exist so\n");
957 DRM_INFO("use the most suitable mode among modes.\n");
958
959 DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n",
960 m->hdisplay, m->vdisplay, m->vrefresh);
961
Sean Paul75626852014-01-30 16:19:16 -0500962 drm_mode_copy(adjusted_mode, m);
Sean Paulf041b252014-01-30 16:19:15 -0500963 break;
964 }
965 }
966}
967
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +0900968static void hdmi_set_acr(u32 freq, u8 *acr)
969{
970 u32 n, cts;
971
972 switch (freq) {
973 case 32000:
974 n = 4096;
975 cts = 27000;
976 break;
977 case 44100:
978 n = 6272;
979 cts = 30000;
980 break;
981 case 88200:
982 n = 12544;
983 cts = 30000;
984 break;
985 case 176400:
986 n = 25088;
987 cts = 30000;
988 break;
989 case 48000:
990 n = 6144;
991 cts = 27000;
992 break;
993 case 96000:
994 n = 12288;
995 cts = 27000;
996 break;
997 case 192000:
998 n = 24576;
999 cts = 27000;
1000 break;
1001 default:
1002 n = 0;
1003 cts = 0;
1004 break;
1005 }
1006
1007 acr[1] = cts >> 16;
1008 acr[2] = cts >> 8 & 0xff;
1009 acr[3] = cts & 0xff;
1010
1011 acr[4] = n >> 16;
1012 acr[5] = n >> 8 & 0xff;
1013 acr[6] = n & 0xff;
1014}
1015
1016static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1017{
1018 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1019 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1020 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1021 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1022 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1023 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1024 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1025 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1026 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1027
Rahul Sharma5a325072012-10-04 20:48:54 +05301028 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001029 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1030 else
1031 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1032}
1033
1034static void hdmi_audio_init(struct hdmi_context *hdata)
1035{
1036 u32 sample_rate, bits_per_sample, frame_size_code;
1037 u32 data_num, bit_ch, sample_frq;
1038 u32 val;
1039 u8 acr[7];
1040
1041 sample_rate = 44100;
1042 bits_per_sample = 16;
1043 frame_size_code = 0;
1044
1045 switch (bits_per_sample) {
1046 case 20:
1047 data_num = 2;
1048 bit_ch = 1;
1049 break;
1050 case 24:
1051 data_num = 3;
1052 bit_ch = 1;
1053 break;
1054 default:
1055 data_num = 1;
1056 bit_ch = 0;
1057 break;
1058 }
1059
1060 hdmi_set_acr(sample_rate, acr);
1061 hdmi_reg_acr(hdata, acr);
1062
1063 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1064 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1065 | HDMI_I2S_MUX_ENABLE);
1066
1067 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1068 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1069
1070 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1071
1072 sample_frq = (sample_rate == 44100) ? 0 :
1073 (sample_rate == 48000) ? 2 :
1074 (sample_rate == 32000) ? 3 :
1075 (sample_rate == 96000) ? 0xa : 0x0;
1076
1077 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1078 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1079
1080 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1081 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1082
1083 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1084 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1085 | HDMI_I2S_SEL_LRCK(6));
1086 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1087 | HDMI_I2S_SEL_SDATA2(4));
1088 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1089 | HDMI_I2S_SEL_SDATA2(2));
1090 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1091
1092 /* I2S_CON_1 & 2 */
1093 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1094 | HDMI_I2S_L_CH_LOW_POL);
1095 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1096 | HDMI_I2S_SET_BIT_CH(bit_ch)
1097 | HDMI_I2S_SET_SDATA_BIT(data_num)
1098 | HDMI_I2S_BASIC_FORMAT);
1099
1100 /* Configure register related to CUV information */
1101 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1102 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1103 | HDMI_I2S_COPYRIGHT
1104 | HDMI_I2S_LINEAR_PCM
1105 | HDMI_I2S_CONSUMER_FORMAT);
1106 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1107 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1108 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1109 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1110 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1111 HDMI_I2S_ORG_SMP_FREQ_44_1
1112 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1113 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1114
1115 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1116}
1117
1118static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1119{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001120 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001121 return;
1122
1123 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1124 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1125 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1126}
1127
Rahul Sharmabfa48422014-04-03 20:41:04 +05301128static void hdmi_start(struct hdmi_context *hdata, bool start)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001129{
Rahul Sharmabfa48422014-04-03 20:41:04 +05301130 u32 val = start ? HDMI_TG_EN : 0;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001131
Rahul Sharmabfa48422014-04-03 20:41:04 +05301132 if (hdata->current_mode.flags & DRM_MODE_FLAG_INTERLACE)
1133 val |= HDMI_FIELD_EN;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001134
Rahul Sharmabfa48422014-04-03 20:41:04 +05301135 hdmi_reg_writemask(hdata, HDMI_CON_0, val, HDMI_EN);
1136 hdmi_reg_writemask(hdata, HDMI_TG_CMD, val, HDMI_TG_EN | HDMI_FIELD_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001137}
1138
1139static void hdmi_conf_init(struct hdmi_context *hdata)
1140{
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301141 union hdmi_infoframe infoframe;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301142
Sean Paul77006a72013-01-16 10:17:20 -05001143 /* disable HPD interrupts from HDMI IP block, use GPIO instead */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001144 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1145 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001146
1147 /* choose HDMI mode */
1148 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1149 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1150 /* disable bluescreen */
1151 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001152
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001153 if (hdata->dvi_mode) {
1154 /* choose DVI mode */
1155 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1156 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1157 hdmi_reg_writeb(hdata, HDMI_CON_2,
1158 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1159 }
1160
Rahul Sharma5a325072012-10-04 20:48:54 +05301161 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001162 /* choose bluescreen (fecal) color */
1163 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1164 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1165 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1166
1167 /* enable AVI packet every vsync, fixes purple line problem */
1168 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1169 /* force RGB, look to CEA-861-D, table 7 for more detail */
1170 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1171 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1172
1173 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1174 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1175 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1176 } else {
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301177 infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
1178 infoframe.any.version = HDMI_AVI_VERSION;
1179 infoframe.any.length = HDMI_AVI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301180 hdmi_reg_infoframe(hdata, &infoframe);
1181
Sachin Kamatd34d59b2014-02-04 08:40:18 +05301182 infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
1183 infoframe.any.version = HDMI_AUI_VERSION;
1184 infoframe.any.length = HDMI_AUI_LENGTH;
Rahul Sharmaa144c2e2012-11-26 10:52:57 +05301185 hdmi_reg_infoframe(hdata, &infoframe);
1186
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001187 /* enable AVI packet every vsync, fixes purple line problem */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001188 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1189 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001190}
1191
Rahul Sharma16844fb2013-06-10 14:50:00 +05301192static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001193{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001194 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1195 const struct hdmi_v13_core_regs *core =
1196 &hdata->mode_conf.conf.v13_conf.core;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001197 int tries;
1198
1199 /* setting core registers */
1200 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1201 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001202 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1203 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1204 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1205 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1206 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1207 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001208 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1209 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001210 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1211 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1212 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1213 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1214 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1215 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1216 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1217 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1218 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1219 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1220 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1221 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1222 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1223 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1224 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001225 /* Timing generator registers */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001226 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1227 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1228 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1229 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1230 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1231 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1232 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1233 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1234 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1235 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1236 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1237 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1238 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1239 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1240 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1241 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1242 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1243 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1244 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1245 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1246 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1247 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1248 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1249 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1250 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1251 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1252 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1253 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001254
1255 /* waiting for HDMIPHY's PLL to get to steady state */
1256 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001257 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001258 if (val & HDMI_PHY_STATUS_READY)
1259 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001260 usleep_range(1000, 2000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001261 }
1262 /* steady state not achieved */
1263 if (tries == 0) {
1264 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1265 hdmi_regs_dump(hdata, "timing apply");
1266 }
1267
Sean Paul0bfb1f82013-06-11 12:24:02 +05301268 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301269 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301270 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001271
1272 /* enable HDMI and timing generator */
Rahul Sharmabfa48422014-04-03 20:41:04 +05301273 hdmi_start(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001274}
1275
Rahul Sharma16844fb2013-06-10 14:50:00 +05301276static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001277{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001278 const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1279 const struct hdmi_v14_core_regs *core =
1280 &hdata->mode_conf.conf.v14_conf.core;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001281 int tries;
1282
1283 /* setting core registers */
1284 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1285 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1286 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1287 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1288 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1289 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1290 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1291 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1292 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1293 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1294 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1295 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1296 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1297 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1298 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1299 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1300 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1301 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1302 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1303 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1304 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1305 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1306 core->v_sync_line_bef_2[0]);
1307 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1308 core->v_sync_line_bef_2[1]);
1309 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1310 core->v_sync_line_bef_1[0]);
1311 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1312 core->v_sync_line_bef_1[1]);
1313 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1314 core->v_sync_line_aft_2[0]);
1315 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1316 core->v_sync_line_aft_2[1]);
1317 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1318 core->v_sync_line_aft_1[0]);
1319 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1320 core->v_sync_line_aft_1[1]);
1321 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1322 core->v_sync_line_aft_pxl_2[0]);
1323 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1324 core->v_sync_line_aft_pxl_2[1]);
1325 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1326 core->v_sync_line_aft_pxl_1[0]);
1327 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1328 core->v_sync_line_aft_pxl_1[1]);
1329 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1330 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1331 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1332 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1333 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1334 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1335 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1336 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1337 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1338 core->v_sync_line_aft_3[0]);
1339 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1340 core->v_sync_line_aft_3[1]);
1341 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1342 core->v_sync_line_aft_4[0]);
1343 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1344 core->v_sync_line_aft_4[1]);
1345 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1346 core->v_sync_line_aft_5[0]);
1347 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1348 core->v_sync_line_aft_5[1]);
1349 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1350 core->v_sync_line_aft_6[0]);
1351 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1352 core->v_sync_line_aft_6[1]);
1353 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1354 core->v_sync_line_aft_pxl_3[0]);
1355 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1356 core->v_sync_line_aft_pxl_3[1]);
1357 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1358 core->v_sync_line_aft_pxl_4[0]);
1359 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1360 core->v_sync_line_aft_pxl_4[1]);
1361 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1362 core->v_sync_line_aft_pxl_5[0]);
1363 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1364 core->v_sync_line_aft_pxl_5[1]);
1365 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1366 core->v_sync_line_aft_pxl_6[0]);
1367 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1368 core->v_sync_line_aft_pxl_6[1]);
1369 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1370 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1371 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1372 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1373 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1374 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1375 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1376 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1377 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1378 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1379 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1380 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1381
1382 /* Timing generator registers */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001383 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]);
1384 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]);
1385 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]);
1386 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]);
1387 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]);
1388 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]);
1389 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]);
1390 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]);
1391 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]);
1392 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]);
1393 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]);
1394 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]);
1395 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]);
1396 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]);
1397 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]);
1398 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]);
1399 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]);
1400 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]);
1401 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]);
1402 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]);
1403 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]);
1404 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]);
1405 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]);
1406 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]);
1407 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]);
1408 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]);
1409 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]);
1410 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]);
1411 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]);
1412 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]);
1413 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]);
1414 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]);
1415 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001416
1417 /* waiting for HDMIPHY's PLL to get to steady state */
1418 for (tries = 100; tries; --tries) {
1419 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1420 if (val & HDMI_PHY_STATUS_READY)
1421 break;
Sean Paul09760ea2013-01-14 17:03:20 -05001422 usleep_range(1000, 2000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001423 }
1424 /* steady state not achieved */
1425 if (tries == 0) {
1426 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1427 hdmi_regs_dump(hdata, "timing apply");
1428 }
1429
Sean Paul0bfb1f82013-06-11 12:24:02 +05301430 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301431 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301432 clk_prepare_enable(hdata->res.sclk_hdmi);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001433
1434 /* enable HDMI and timing generator */
Rahul Sharmabfa48422014-04-03 20:41:04 +05301435 hdmi_start(hdata, true);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001436}
1437
Rahul Sharma16844fb2013-06-10 14:50:00 +05301438static void hdmi_mode_apply(struct hdmi_context *hdata)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001439{
Rahul Sharma5a325072012-10-04 20:48:54 +05301440 if (hdata->type == HDMI_TYPE13)
Rahul Sharma16844fb2013-06-10 14:50:00 +05301441 hdmi_v13_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001442 else
Rahul Sharma16844fb2013-06-10 14:50:00 +05301443 hdmi_v14_mode_apply(hdata);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001444}
1445
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001446static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1447{
1448 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001449 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001450
Sean Paul0bfb1f82013-06-11 12:24:02 +05301451 clk_disable_unprepare(hdata->res.sclk_hdmi);
Rahul Sharma59956d32013-06-11 12:24:03 +05301452 clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
Sean Paul0bfb1f82013-06-11 12:24:02 +05301453 clk_prepare_enable(hdata->res.sclk_hdmi);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001454
1455 /* operation mode */
1456 buffer[0] = 0x1f;
1457 buffer[1] = 0x00;
1458
1459 if (hdata->hdmiphy_port)
1460 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1461
Rahul Sharma5a325072012-10-04 20:48:54 +05301462 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001463 reg = HDMI_V13_PHY_RSTOUT;
1464 else
1465 reg = HDMI_PHY_RSTOUT;
1466
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001467 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001468 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001469 usleep_range(10000, 12000);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001470 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Sean Paul09760ea2013-01-14 17:03:20 -05001471 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001472}
1473
Rahul Sharmaa5562252012-11-28 11:30:25 +05301474static void hdmiphy_poweron(struct hdmi_context *hdata)
1475{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301476 if (hdata->type == HDMI_TYPE14)
1477 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
1478 HDMI_PHY_POWER_OFF_EN);
1479}
1480
1481static void hdmiphy_poweroff(struct hdmi_context *hdata)
1482{
Rahul Sharmaa5562252012-11-28 11:30:25 +05301483 if (hdata->type == HDMI_TYPE14)
1484 hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
1485 HDMI_PHY_POWER_OFF_EN);
1486}
1487
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001488static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1489{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001490 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001491 u8 buffer[32];
1492 u8 operation[2];
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001493 int ret;
1494 int i;
1495
1496 if (!hdata->hdmiphy_port) {
1497 DRM_ERROR("hdmiphy is not attached\n");
1498 return;
1499 }
1500
1501 /* pixel clock */
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001502 i = hdmi_find_phy_conf(hdata, hdata->mode_conf.pixel_clock);
1503 if (i < 0) {
1504 DRM_ERROR("failed to find hdmiphy conf\n");
1505 return;
1506 }
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001507
Sachin Kamat5f46c332013-04-26 11:29:00 +05301508 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001509 hdmiphy_data = hdmiphy_v13_configs[i].conf;
Sachin Kamat5f46c332013-04-26 11:29:00 +05301510 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001511 hdmiphy_data = hdmiphy_v14_configs[i].conf;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001512
1513 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001514 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1515 if (ret != 32) {
1516 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1517 return;
1518 }
1519
Sean Paul09760ea2013-01-14 17:03:20 -05001520 usleep_range(10000, 12000);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001521
1522 /* operation mode */
1523 operation[0] = 0x1f;
1524 operation[1] = 0x80;
1525
1526 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1527 if (ret != 2) {
1528 DRM_ERROR("failed to enable hdmiphy\n");
1529 return;
1530 }
1531
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001532}
1533
1534static void hdmi_conf_apply(struct hdmi_context *hdata)
1535{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001536 hdmiphy_conf_reset(hdata);
1537 hdmiphy_conf_apply(hdata);
1538
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001539 mutex_lock(&hdata->hdmi_mutex);
Rahul Sharmabfa48422014-04-03 20:41:04 +05301540 hdmi_start(hdata, false);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001541 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001542 mutex_unlock(&hdata->hdmi_mutex);
1543
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001544 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001545
1546 /* setting core registers */
Rahul Sharma16844fb2013-06-10 14:50:00 +05301547 hdmi_mode_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001548 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001549
1550 hdmi_regs_dump(hdata, "start");
1551}
1552
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001553static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value)
1554{
1555 int i;
1556 BUG_ON(num_bytes > 4);
1557 for (i = 0; i < num_bytes; i++)
1558 reg_pair[i] = (value >> (8 * i)) & 0xff;
1559}
1560
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001561static void hdmi_v13_mode_set(struct hdmi_context *hdata,
1562 struct drm_display_mode *m)
1563{
1564 struct hdmi_v13_core_regs *core = &hdata->mode_conf.conf.v13_conf.core;
1565 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
1566 unsigned int val;
1567
1568 hdata->mode_conf.cea_video_id =
1569 drm_match_cea_mode((struct drm_display_mode *)m);
1570 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301571 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001572
1573 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1574 hdmi_set_reg(core->h_v_line, 3, (m->htotal << 12) | m->vtotal);
1575
1576 val = (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0;
1577 hdmi_set_reg(core->vsync_pol, 1, val);
1578
1579 val = (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0;
1580 hdmi_set_reg(core->int_pro_mode, 1, val);
1581
1582 val = (m->hsync_start - m->hdisplay - 2);
1583 val |= ((m->hsync_end - m->hdisplay - 2) << 10);
1584 val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
1585 hdmi_set_reg(core->h_sync_gen, 3, val);
1586
1587 /*
1588 * Quirk requirement for exynos HDMI IP design,
1589 * 2 pixels less than the actual calculation for hsync_start
1590 * and end.
1591 */
1592
1593 /* Following values & calculations differ for different type of modes */
1594 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1595 /* Interlaced Mode */
1596 val = ((m->vsync_end - m->vdisplay) / 2);
1597 val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
1598 hdmi_set_reg(core->v_sync_gen1, 3, val);
1599
1600 val = m->vtotal / 2;
1601 val |= ((m->vtotal - m->vdisplay) / 2) << 11;
1602 hdmi_set_reg(core->v_blank, 3, val);
1603
1604 val = (m->vtotal +
1605 ((m->vsync_end - m->vsync_start) * 4) + 5) / 2;
1606 val |= m->vtotal << 11;
1607 hdmi_set_reg(core->v_blank_f, 3, val);
1608
1609 val = ((m->vtotal / 2) + 7);
1610 val |= ((m->vtotal / 2) + 2) << 12;
1611 hdmi_set_reg(core->v_sync_gen2, 3, val);
1612
1613 val = ((m->htotal / 2) + (m->hsync_start - m->hdisplay));
1614 val |= ((m->htotal / 2) +
1615 (m->hsync_start - m->hdisplay)) << 12;
1616 hdmi_set_reg(core->v_sync_gen3, 3, val);
1617
1618 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1619 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
1620
1621 hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
1622 } else {
1623 /* Progressive Mode */
1624
1625 val = m->vtotal;
1626 val |= (m->vtotal - m->vdisplay) << 11;
1627 hdmi_set_reg(core->v_blank, 3, val);
1628
1629 hdmi_set_reg(core->v_blank_f, 3, 0);
1630
1631 val = (m->vsync_end - m->vdisplay);
1632 val |= ((m->vsync_start - m->vdisplay) << 12);
1633 hdmi_set_reg(core->v_sync_gen1, 3, val);
1634
1635 hdmi_set_reg(core->v_sync_gen2, 3, 0x1001);/* Reset value */
1636 hdmi_set_reg(core->v_sync_gen3, 3, 0x1001);/* Reset value */
1637 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1638 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1639 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1640 }
1641
1642 /* Timing generator registers */
1643 hdmi_set_reg(tg->cmd, 1, 0x0);
1644 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1645 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1646 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1647 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1648 hdmi_set_reg(tg->vsync, 2, 0x1);
1649 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1650 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1651 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
1652 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1653 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
1654 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
1655 hdmi_set_reg(tg->tg_3d, 1, 0x0); /* Not used */
1656}
1657
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001658static void hdmi_v14_mode_set(struct hdmi_context *hdata,
1659 struct drm_display_mode *m)
1660{
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001661 struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
1662 struct hdmi_v14_core_regs *core =
1663 &hdata->mode_conf.conf.v14_conf.core;
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001664
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001665 hdata->mode_conf.cea_video_id =
1666 drm_match_cea_mode((struct drm_display_mode *)m);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001667 hdata->mode_conf.pixel_clock = m->clock * 1000;
Shirish S46154152014-03-13 10:58:28 +05301668 hdata->mode_conf.aspect_ratio = m->picture_aspect_ratio;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001669
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001670 hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay);
1671 hdmi_set_reg(core->v_line, 2, m->vtotal);
1672 hdmi_set_reg(core->h_line, 2, m->htotal);
1673 hdmi_set_reg(core->hsync_pol, 1,
1674 (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
1675 hdmi_set_reg(core->vsync_pol, 1,
1676 (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
1677 hdmi_set_reg(core->int_pro_mode, 1,
1678 (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
1679
1680 /*
1681 * Quirk requirement for exynos 5 HDMI IP design,
1682 * 2 pixels less than the actual calculation for hsync_start
1683 * and end.
1684 */
1685
1686 /* Following values & calculations differ for different type of modes */
1687 if (m->flags & DRM_MODE_FLAG_INTERLACE) {
1688 /* Interlaced Mode */
1689 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1690 (m->vsync_end - m->vdisplay) / 2);
1691 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1692 (m->vsync_start - m->vdisplay) / 2);
1693 hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
1694 hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301695 hdmi_set_reg(core->v_blank_f0, 2, m->vtotal - m->vdisplay / 2);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001696 hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
1697 hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
1698 hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
1699 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2,
1700 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1701 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2,
1702 (m->htotal / 2) + (m->hsync_start - m->hdisplay));
1703 hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
1704 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
Rahul Sharma14829952013-06-18 18:19:37 +05301705 hdmi_set_reg(tg->vact_st2, 2, m->vtotal - m->vdisplay / 2);
1706 hdmi_set_reg(tg->vsync2, 2, (m->vtotal / 2) + 1);
1707 hdmi_set_reg(tg->vsync_bot_hdmi, 2, (m->vtotal / 2) + 1);
1708 hdmi_set_reg(tg->field_bot_hdmi, 2, (m->vtotal / 2) + 1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001709 hdmi_set_reg(tg->vact_st3, 2, 0x0);
1710 hdmi_set_reg(tg->vact_st4, 2, 0x0);
1711 } else {
1712 /* Progressive Mode */
1713 hdmi_set_reg(core->v_sync_line_bef_2, 2,
1714 m->vsync_end - m->vdisplay);
1715 hdmi_set_reg(core->v_sync_line_bef_1, 2,
1716 m->vsync_start - m->vdisplay);
1717 hdmi_set_reg(core->v2_blank, 2, m->vtotal);
1718 hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay);
1719 hdmi_set_reg(core->v_blank_f0, 2, 0xffff);
1720 hdmi_set_reg(core->v_blank_f1, 2, 0xffff);
1721 hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff);
1722 hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff);
1723 hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff);
1724 hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff);
1725 hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay);
1726 hdmi_set_reg(tg->vact_sz, 2, m->vdisplay);
1727 hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
1728 hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
1729 hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
Rahul Sharma14829952013-06-18 18:19:37 +05301730 hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
1731 hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
1732 hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001733 }
1734
1735 /* Following values & calculations are same irrespective of mode type */
1736 hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2);
1737 hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2);
1738 hdmi_set_reg(core->vact_space_1, 2, 0xffff);
1739 hdmi_set_reg(core->vact_space_2, 2, 0xffff);
1740 hdmi_set_reg(core->vact_space_3, 2, 0xffff);
1741 hdmi_set_reg(core->vact_space_4, 2, 0xffff);
1742 hdmi_set_reg(core->vact_space_5, 2, 0xffff);
1743 hdmi_set_reg(core->vact_space_6, 2, 0xffff);
1744 hdmi_set_reg(core->v_blank_f2, 2, 0xffff);
1745 hdmi_set_reg(core->v_blank_f3, 2, 0xffff);
1746 hdmi_set_reg(core->v_blank_f4, 2, 0xffff);
1747 hdmi_set_reg(core->v_blank_f5, 2, 0xffff);
1748 hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff);
1749 hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff);
1750 hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff);
1751 hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff);
1752 hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff);
1753 hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff);
1754 hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff);
1755 hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff);
1756
1757 /* Timing generator registers */
1758 hdmi_set_reg(tg->cmd, 1, 0x0);
1759 hdmi_set_reg(tg->h_fsz, 2, m->htotal);
1760 hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay);
1761 hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
1762 hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
1763 hdmi_set_reg(tg->vsync, 2, 0x1);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001764 hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
1765 hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001766 hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001767 hdmi_set_reg(tg->tg_3d, 1, 0x0);
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001768}
1769
Sean Paulf041b252014-01-30 16:19:15 -05001770static void hdmi_mode_set(struct exynos_drm_display *display,
1771 struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001772{
Sean Paulf041b252014-01-30 16:19:15 -05001773 struct hdmi_context *hdata = display->ctx;
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001774 struct drm_display_mode *m = mode;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001775
YoungJun Chocbc4c332013-06-12 10:44:40 +09001776 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
1777 m->hdisplay, m->vdisplay,
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001778 m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
1779 "INTERLACED" : "PROGERESSIVE");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001780
Rahul Sharmabfa48422014-04-03 20:41:04 +05301781 /* preserve mode information for later use. */
1782 drm_mode_copy(&hdata->current_mode, mode);
1783
Sachin Kamat5f46c332013-04-26 11:29:00 +05301784 if (hdata->type == HDMI_TYPE13)
Rahul Sharma6b986ed2013-03-06 17:33:29 +09001785 hdmi_v13_mode_set(hdata, mode);
Sachin Kamat5f46c332013-04-26 11:29:00 +05301786 else
Sean Paul2f7e2ed2013-01-15 08:11:08 -05001787 hdmi_v14_mode_set(hdata, mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001788}
1789
Sean Paulf041b252014-01-30 16:19:15 -05001790static void hdmi_commit(struct exynos_drm_display *display)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001791{
Sean Paulf041b252014-01-30 16:19:15 -05001792 struct hdmi_context *hdata = display->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001793
Shirish Sdda90122013-01-23 22:03:18 -05001794 mutex_lock(&hdata->hdmi_mutex);
1795 if (!hdata->powered) {
1796 mutex_unlock(&hdata->hdmi_mutex);
1797 return;
1798 }
1799 mutex_unlock(&hdata->hdmi_mutex);
1800
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001801 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001802}
1803
Sean Paulf041b252014-01-30 16:19:15 -05001804static void hdmi_poweron(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001805{
Sean Paulf041b252014-01-30 16:19:15 -05001806 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001807 struct hdmi_resources *res = &hdata->res;
1808
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001809 mutex_lock(&hdata->hdmi_mutex);
1810 if (hdata->powered) {
1811 mutex_unlock(&hdata->hdmi_mutex);
1812 return;
1813 }
1814
1815 hdata->powered = true;
1816
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001817 mutex_unlock(&hdata->hdmi_mutex);
1818
Sean Paulaf65c802014-01-30 16:19:27 -05001819 pm_runtime_get_sync(hdata->dev);
1820
Seung-Woo Kimad079452013-06-05 14:34:38 +09001821 if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
1822 DRM_DEBUG_KMS("failed to enable regulator bulk\n");
1823
Sean Paul0bfb1f82013-06-11 12:24:02 +05301824 clk_prepare_enable(res->hdmiphy);
1825 clk_prepare_enable(res->hdmi);
1826 clk_prepare_enable(res->sclk_hdmi);
Rahul Sharmaa5562252012-11-28 11:30:25 +05301827
1828 hdmiphy_poweron(hdata);
Sean Paulf041b252014-01-30 16:19:15 -05001829 hdmi_commit(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001830}
1831
Sean Paulf041b252014-01-30 16:19:15 -05001832static void hdmi_poweroff(struct exynos_drm_display *display)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001833{
Sean Paulf041b252014-01-30 16:19:15 -05001834 struct hdmi_context *hdata = display->ctx;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001835 struct hdmi_resources *res = &hdata->res;
1836
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001837 mutex_lock(&hdata->hdmi_mutex);
1838 if (!hdata->powered)
1839 goto out;
1840 mutex_unlock(&hdata->hdmi_mutex);
1841
Rahul Sharmabfa48422014-04-03 20:41:04 +05301842 /* HDMI System Disable */
1843 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
1844
Rahul Sharmaa5562252012-11-28 11:30:25 +05301845 hdmiphy_poweroff(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001846
Sean Paul724fd142014-05-09 15:05:10 +09001847 cancel_delayed_work(&hdata->hotplug_work);
1848
Sean Paul0bfb1f82013-06-11 12:24:02 +05301849 clk_disable_unprepare(res->sclk_hdmi);
1850 clk_disable_unprepare(res->hdmi);
1851 clk_disable_unprepare(res->hdmiphy);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001852 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1853
Sean Paulaf65c802014-01-30 16:19:27 -05001854 pm_runtime_put_sync(hdata->dev);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001855
Sean Paulaf65c802014-01-30 16:19:27 -05001856 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001857 hdata->powered = false;
1858
1859out:
1860 mutex_unlock(&hdata->hdmi_mutex);
1861}
1862
Sean Paulf041b252014-01-30 16:19:15 -05001863static void hdmi_dpms(struct exynos_drm_display *display, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001864{
YoungJun Chocbc4c332013-06-12 10:44:40 +09001865 DRM_DEBUG_KMS("mode %d\n", mode);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001866
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001867 switch (mode) {
1868 case DRM_MODE_DPMS_ON:
Sean Paulaf65c802014-01-30 16:19:27 -05001869 hdmi_poweron(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001870 break;
1871 case DRM_MODE_DPMS_STANDBY:
1872 case DRM_MODE_DPMS_SUSPEND:
1873 case DRM_MODE_DPMS_OFF:
Sean Paulaf65c802014-01-30 16:19:27 -05001874 hdmi_poweroff(display);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001875 break;
1876 default:
1877 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
1878 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001879 }
1880}
1881
Sean Paulf041b252014-01-30 16:19:15 -05001882static struct exynos_drm_display_ops hdmi_display_ops = {
Sean Pauld9716ee2014-01-30 16:19:29 -05001883 .create_connector = hdmi_create_connector,
Sean Paulf041b252014-01-30 16:19:15 -05001884 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001885 .mode_set = hdmi_mode_set,
Sean Paulf041b252014-01-30 16:19:15 -05001886 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001887 .commit = hdmi_commit,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001888};
1889
Sean Paulf041b252014-01-30 16:19:15 -05001890static struct exynos_drm_display hdmi_display = {
1891 .type = EXYNOS_DISPLAY_TYPE_HDMI,
1892 .ops = &hdmi_display_ops,
1893};
1894
Sean Paul724fd142014-05-09 15:05:10 +09001895static void hdmi_hotplug_work_func(struct work_struct *work)
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001896{
Sean Paul724fd142014-05-09 15:05:10 +09001897 struct hdmi_context *hdata;
1898
1899 hdata = container_of(work, struct hdmi_context, hotplug_work.work);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001900
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001901 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05301902 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001903 mutex_unlock(&hdata->hdmi_mutex);
1904
Sean Paul45517892014-01-30 16:19:05 -05001905 if (hdata->drm_dev)
1906 drm_helper_hpd_irq_event(hdata->drm_dev);
Sean Paul724fd142014-05-09 15:05:10 +09001907}
1908
1909static irqreturn_t hdmi_irq_thread(int irq, void *arg)
1910{
1911 struct hdmi_context *hdata = arg;
1912
1913 mod_delayed_work(system_wq, &hdata->hotplug_work,
1914 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001915
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001916 return IRQ_HANDLED;
1917}
1918
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08001919static int hdmi_resources_init(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001920{
1921 struct device *dev = hdata->dev;
1922 struct hdmi_resources *res = &hdata->res;
1923 static char *supply[] = {
1924 "hdmi-en",
1925 "vdd",
1926 "vdd_osc",
1927 "vdd_pll",
1928 };
1929 int i, ret;
1930
1931 DRM_DEBUG_KMS("HDMI resource init\n");
1932
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001933 /* get clocks, power */
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301934 res->hdmi = devm_clk_get(dev, "hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301935 if (IS_ERR(res->hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001936 DRM_ERROR("failed to get clock 'hdmi'\n");
1937 goto fail;
1938 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301939 res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301940 if (IS_ERR(res->sclk_hdmi)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001941 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
1942 goto fail;
1943 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301944 res->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301945 if (IS_ERR(res->sclk_pixel)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001946 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1947 goto fail;
1948 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301949 res->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301950 if (IS_ERR(res->sclk_hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001951 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
1952 goto fail;
1953 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301954 res->hdmiphy = devm_clk_get(dev, "hdmiphy");
Sachin Kamatee7cbaf2013-03-21 15:33:57 +05301955 if (IS_ERR(res->hdmiphy)) {
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001956 DRM_ERROR("failed to get clock 'hdmiphy'\n");
1957 goto fail;
1958 }
Rahul Sharma59956d32013-06-11 12:24:03 +05301959 res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
1960 if (IS_ERR(res->mout_hdmi)) {
1961 DRM_ERROR("failed to get clock 'mout_hdmi'\n");
1962 goto fail;
1963 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001964
Rahul Sharma59956d32013-06-11 12:24:03 +05301965 clk_set_parent(res->mout_hdmi, res->sclk_pixel);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001966
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301967 res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05301968 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09001969 if (!res->regul_bulk)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001970 goto fail;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001971 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
1972 res->regul_bulk[i].supply = supply[i];
1973 res->regul_bulk[i].consumer = NULL;
1974 }
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05301975 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001976 if (ret) {
1977 DRM_ERROR("failed to get regulators\n");
1978 goto fail;
1979 }
1980 res->regul_count = ARRAY_SIZE(supply);
1981
1982 return 0;
1983fail:
1984 DRM_ERROR("HDMI resource init - failed\n");
1985 return -ENODEV;
1986}
1987
Rahul Sharma22c4f422012-10-04 20:48:55 +05301988static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
1989 (struct device *dev)
1990{
1991 struct device_node *np = dev->of_node;
1992 struct s5p_hdmi_platform_data *pd;
Rahul Sharma22c4f422012-10-04 20:48:55 +05301993 u32 value;
1994
1995 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09001996 if (!pd)
Rahul Sharma22c4f422012-10-04 20:48:55 +05301997 goto err_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05301998
1999 if (!of_find_property(np, "hpd-gpio", &value)) {
2000 DRM_ERROR("no hpd gpio property found\n");
2001 goto err_data;
2002 }
2003
Rahul Sharma5f916e22013-06-11 19:41:29 +05302004 pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302005
2006 return pd;
2007
2008err_data:
2009 return NULL;
2010}
Rahul Sharma22c4f422012-10-04 20:48:55 +05302011
Rahul Sharma22c4f422012-10-04 20:48:55 +05302012static struct of_device_id hdmi_match_types[] = {
2013 {
2014 .compatible = "samsung,exynos5-hdmi",
Inki Daebfe4e842014-03-06 14:18:17 +09002015 .data = &exynos5_hdmi_driver_data,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302016 }, {
Rahul Sharmacc57caf2013-06-19 18:21:07 +05302017 .compatible = "samsung,exynos4212-hdmi",
Inki Daebfe4e842014-03-06 14:18:17 +09002018 .data = &exynos4212_hdmi_driver_data,
Rahul Sharmacc57caf2013-06-19 18:21:07 +05302019 }, {
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302020 /* end node */
2021 }
2022};
2023
Inki Daef37cd5e2014-05-09 14:25:20 +09002024static int hdmi_bind(struct device *dev, struct device *master, void *data)
2025{
2026 struct drm_device *drm_dev = data;
2027 struct hdmi_context *hdata;
2028
2029 hdata = hdmi_display.ctx;
2030 hdata->drm_dev = drm_dev;
2031
2032 return exynos_drm_create_enc_conn(drm_dev, &hdmi_display);
2033}
2034
2035static void hdmi_unbind(struct device *dev, struct device *master, void *data)
2036{
2037 struct exynos_drm_display *display = get_hdmi_display(dev);
2038 struct drm_encoder *encoder = display->encoder;
2039 struct hdmi_context *hdata = display->ctx;
2040
2041 encoder->funcs->destroy(encoder);
2042 drm_connector_cleanup(&hdata->connector);
2043}
2044
2045static const struct component_ops hdmi_component_ops = {
2046 .bind = hdmi_bind,
2047 .unbind = hdmi_unbind,
2048};
2049
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002050static int hdmi_probe(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002051{
Inki Daef37cd5e2014-05-09 14:25:20 +09002052 struct device_node *ddc_node, *phy_node;
2053 struct s5p_hdmi_platform_data *pdata;
2054 struct hdmi_driver_data *drv_data;
2055 const struct of_device_id *match;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002056 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002057 struct hdmi_context *hdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002058 struct resource *res;
2059 int ret;
2060
Inki Daef37cd5e2014-05-09 14:25:20 +09002061 if (!dev->of_node)
Sachin Kamat88c49812013-08-28 10:47:57 +05302062 return -ENODEV;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302063
Sachin Kamat88c49812013-08-28 10:47:57 +05302064 pdata = drm_hdmi_dt_parse_pdata(dev);
2065 if (!pdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002066 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002067
Sachin Kamat88c49812013-08-28 10:47:57 +05302068 hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL);
Sachin Kamat38bb5252013-08-19 19:04:55 +09002069 if (!hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002070 return -ENOMEM;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002071
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002072 mutex_init(&hdata->hdmi_mutex);
2073
Sean Paulf041b252014-01-30 16:19:15 -05002074 platform_set_drvdata(pdev, &hdmi_display);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002075
Sachin Kamat88c49812013-08-28 10:47:57 +05302076 match = of_match_node(hdmi_match_types, dev->of_node);
2077 if (!match)
2078 return -ENODEV;
Inki Daebfe4e842014-03-06 14:18:17 +09002079
2080 drv_data = (struct hdmi_driver_data *)match->data;
2081 hdata->type = drv_data->type;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302082
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302083 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002084 hdata->dev = dev;
2085
2086 ret = hdmi_resources_init(hdata);
2087 if (ret) {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302088 DRM_ERROR("hdmi_resources_init failed\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302089 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002090 }
2091
2092 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002093 hdata->regs = devm_ioremap_resource(dev, res);
Thierry Redingd4ed6022013-01-21 11:09:02 +01002094 if (IS_ERR(hdata->regs))
2095 return PTR_ERR(hdata->regs);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002096
Seung-Woo Kimd873ab92013-05-22 21:14:14 +09002097 ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302098 if (ret) {
2099 DRM_ERROR("failed to request HPD gpio\n");
Sachin Kamat9f49d9f2012-11-23 14:13:27 +05302100 return ret;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302101 }
2102
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002103 /* DDC i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002104 ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
2105 if (!ddc_node) {
2106 DRM_ERROR("Failed to find ddc node in device tree\n");
2107 return -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002108 }
Inki Dae8fa04aa2014-03-13 16:38:31 +09002109 hdata->ddc_adpt = of_find_i2c_adapter_by_node(ddc_node);
2110 if (!hdata->ddc_adpt) {
2111 DRM_ERROR("Failed to get ddc i2c adapter by node\n");
Daniel Kurtz2b768132014-02-24 18:52:51 +09002112 return -ENODEV;
2113 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002114
Inki Daebfe4e842014-03-06 14:18:17 +09002115 /* Not support APB PHY yet. */
2116 if (drv_data->is_apb_phy)
2117 return -EPERM;
2118
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002119 /* hdmiphy i2c driver */
Daniel Kurtz2b768132014-02-24 18:52:51 +09002120 phy_node = of_parse_phandle(dev->of_node, "phy", 0);
2121 if (!phy_node) {
2122 DRM_ERROR("Failed to find hdmiphy node in device tree\n");
2123 ret = -ENODEV;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002124 goto err_ddc;
2125 }
Daniel Kurtz2b768132014-02-24 18:52:51 +09002126 hdata->hdmiphy_port = of_find_i2c_device_by_node(phy_node);
2127 if (!hdata->hdmiphy_port) {
2128 DRM_ERROR("Failed to get hdmi phy i2c client from node\n");
2129 ret = -ENODEV;
2130 goto err_ddc;
2131 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002132
Sean Paul77006a72013-01-16 10:17:20 -05002133 hdata->irq = gpio_to_irq(hdata->hpd_gpio);
2134 if (hdata->irq < 0) {
2135 DRM_ERROR("failed to get GPIO irq\n");
2136 ret = hdata->irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002137 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002138 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002139
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302140 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2141
Sean Paul724fd142014-05-09 15:05:10 +09002142 INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
2143
Seung-Woo Kimdcb9a7c2013-05-22 21:14:17 +09002144 ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
Sean Paul77006a72013-01-16 10:17:20 -05002145 hdmi_irq_thread, IRQF_TRIGGER_RISING |
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002146 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
Sean Paulf041b252014-01-30 16:19:15 -05002147 "hdmi", hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002148 if (ret) {
Sean Paul77006a72013-01-16 10:17:20 -05002149 DRM_ERROR("failed to register hdmi interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002150 goto err_hdmiphy;
2151 }
2152
Sean Paulaf65c802014-01-30 16:19:27 -05002153 pm_runtime_enable(dev);
Sean Paulf041b252014-01-30 16:19:15 -05002154 hdmi_display.ctx = hdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002155
Inki Daef37cd5e2014-05-09 14:25:20 +09002156 return exynos_drm_component_add(&pdev->dev, &hdmi_component_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002157
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002158err_hdmiphy:
Paul Taysomb21a3bf2014-05-09 15:06:28 +09002159 if (hdata->hdmiphy_port)
2160 put_device(&hdata->hdmiphy_port->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002161err_ddc:
Inki Dae8fa04aa2014-03-13 16:38:31 +09002162 put_device(&hdata->ddc_adpt->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002163 return ret;
2164}
2165
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002166static int hdmi_remove(struct platform_device *pdev)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002167{
Inki Daef37cd5e2014-05-09 14:25:20 +09002168 struct hdmi_context *hdata = hdmi_display.ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002169
Sean Paul724fd142014-05-09 15:05:10 +09002170 cancel_delayed_work_sync(&hdata->hotplug_work);
2171
Daniel Kurtz2b768132014-02-24 18:52:51 +09002172 put_device(&hdata->hdmiphy_port->dev);
Inki Dae8fa04aa2014-03-13 16:38:31 +09002173 put_device(&hdata->ddc_adpt->dev);
Inki Daef37cd5e2014-05-09 14:25:20 +09002174
Sean Paulaf65c802014-01-30 16:19:27 -05002175 pm_runtime_disable(&pdev->dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002176
Inki Daef37cd5e2014-05-09 14:25:20 +09002177 exynos_drm_component_del(&pdev->dev, &hdmi_component_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002178 return 0;
2179}
2180
2181struct platform_driver hdmi_driver = {
2182 .probe = hdmi_probe,
Greg Kroah-Hartman56550d92012-12-21 15:09:25 -08002183 .remove = hdmi_remove,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002184 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302185 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002186 .owner = THIS_MODULE,
Sachin Kamat88c49812013-08-28 10:47:57 +05302187 .of_match_table = hdmi_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002188 },
2189};