Subversion Repositories Kolibri OS

Rev

Rev 3243 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3031 serge 1
/*
2
 * Copyright © 2012 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
 * IN THE SOFTWARE.
22
 *
23
 * Authors:
24
 *    Eugeni Dodonov 
25
 *
26
 */
27
 
28
#include "i915_drv.h"
29
#include "intel_drv.h"
30
 
31
/* HDMI/DVI modes ignore everything but the last 2 items. So we share
32
 * them for both DP and FDI transports, allowing those ports to
33
 * automatically adapt to HDMI connections as well
34
 */
35
static const u32 hsw_ddi_translations_dp[] = {
36
	0x00FFFFFF, 0x0006000E,		/* DP parameters */
37
	0x00D75FFF, 0x0005000A,
38
	0x00C30FFF, 0x00040006,
39
	0x80AAAFFF, 0x000B0000,
40
	0x00FFFFFF, 0x0005000A,
41
	0x00D75FFF, 0x000C0004,
42
	0x80C30FFF, 0x000B0000,
43
	0x00FFFFFF, 0x00040006,
44
	0x80D75FFF, 0x000B0000,
45
	0x00FFFFFF, 0x00040006		/* HDMI parameters */
46
};
47
 
48
static const u32 hsw_ddi_translations_fdi[] = {
49
	0x00FFFFFF, 0x0007000E,		/* FDI parameters */
50
	0x00D75FFF, 0x000F000A,
51
	0x00C30FFF, 0x00060006,
52
	0x00AAAFFF, 0x001E0000,
53
	0x00FFFFFF, 0x000F000A,
54
	0x00D75FFF, 0x00160004,
55
	0x00C30FFF, 0x001E0000,
56
	0x00FFFFFF, 0x00060006,
57
	0x00D75FFF, 0x001E0000,
58
	0x00FFFFFF, 0x00040006		/* HDMI parameters */
59
};
60
 
61
/* On Haswell, DDI port buffers must be programmed with correct values
62
 * in advance. The buffer values are different for FDI and DP modes,
63
 * but the HDMI/DVI fields are shared among those. So we program the DDI
64
 * in either FDI or DP modes only, as HDMI connections will work with both
65
 * of those
66
 */
67
void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode)
68
{
69
	struct drm_i915_private *dev_priv = dev->dev_private;
70
	u32 reg;
71
	int i;
72
	const u32 *ddi_translations = ((use_fdi_mode) ?
73
		hsw_ddi_translations_fdi :
74
		hsw_ddi_translations_dp);
75
 
76
	DRM_DEBUG_DRIVER("Initializing DDI buffers for port %c in %s mode\n",
77
			port_name(port),
78
			use_fdi_mode ? "FDI" : "DP");
79
 
80
	WARN((use_fdi_mode && (port != PORT_E)),
81
		"Programming port %c in FDI mode, this probably will not work.\n",
82
		port_name(port));
83
 
84
	for (i=0, reg=DDI_BUF_TRANS(port); i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
85
		I915_WRITE(reg, ddi_translations[i]);
86
		reg += 4;
87
	}
88
}
89
 
90
/* Program DDI buffers translations for DP. By default, program ports A-D in DP
91
 * mode and port E for FDI.
92
 */
93
void intel_prepare_ddi(struct drm_device *dev)
94
{
95
	int port;
96
 
97
	if (IS_HASWELL(dev)) {
98
		for (port = PORT_A; port < PORT_E; port++)
99
			intel_prepare_ddi_buffers(dev, port, false);
100
 
101
		/* DDI E is the suggested one to work in FDI mode, so program is as such by
102
		 * default. It will have to be re-programmed in case a digital DP output
103
		 * will be detected on it
104
		 */
105
		intel_prepare_ddi_buffers(dev, PORT_E, true);
106
	}
107
}
108
 
109
static const long hsw_ddi_buf_ctl_values[] = {
110
	DDI_BUF_EMP_400MV_0DB_HSW,
111
	DDI_BUF_EMP_400MV_3_5DB_HSW,
112
	DDI_BUF_EMP_400MV_6DB_HSW,
113
	DDI_BUF_EMP_400MV_9_5DB_HSW,
114
	DDI_BUF_EMP_600MV_0DB_HSW,
115
	DDI_BUF_EMP_600MV_3_5DB_HSW,
116
	DDI_BUF_EMP_600MV_6DB_HSW,
117
	DDI_BUF_EMP_800MV_0DB_HSW,
118
	DDI_BUF_EMP_800MV_3_5DB_HSW
119
};
120
 
121
 
122
/* Starting with Haswell, different DDI ports can work in FDI mode for
123
 * connection to the PCH-located connectors. For this, it is necessary to train
124
 * both the DDI port and PCH receiver for the desired DDI buffer settings.
125
 *
126
 * The recommended port to work in FDI mode is DDI E, which we use here. Also,
127
 * please note that when FDI mode is active on DDI E, it shares 2 lines with
128
 * DDI A (which is used for eDP)
129
 */
130
 
131
void hsw_fdi_link_train(struct drm_crtc *crtc)
132
{
133
	struct drm_device *dev = crtc->dev;
134
	struct drm_i915_private *dev_priv = dev->dev_private;
135
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
136
	int pipe = intel_crtc->pipe;
137
	u32 reg, temp, i;
138
 
139
	/* Configure CPU PLL, wait for warmup */
140
	I915_WRITE(SPLL_CTL,
141
			SPLL_PLL_ENABLE |
142
			SPLL_PLL_FREQ_1350MHz |
143
			SPLL_PLL_SCC);
144
 
145
	/* Use SPLL to drive the output when in FDI mode */
146
	I915_WRITE(PORT_CLK_SEL(PORT_E),
147
			PORT_CLK_SEL_SPLL);
148
	I915_WRITE(PIPE_CLK_SEL(pipe),
149
			PIPE_CLK_SEL_PORT(PORT_E));
150
 
151
	udelay(20);
152
 
153
	/* Start the training iterating through available voltages and emphasis */
154
	for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) {
155
		/* Configure DP_TP_CTL with auto-training */
156
		I915_WRITE(DP_TP_CTL(PORT_E),
157
					DP_TP_CTL_FDI_AUTOTRAIN |
158
					DP_TP_CTL_ENHANCED_FRAME_ENABLE |
159
					DP_TP_CTL_LINK_TRAIN_PAT1 |
160
					DP_TP_CTL_ENABLE);
161
 
162
		/* Configure and enable DDI_BUF_CTL for DDI E with next voltage */
163
		temp = I915_READ(DDI_BUF_CTL(PORT_E));
164
		temp = (temp & ~DDI_BUF_EMP_MASK);
165
		I915_WRITE(DDI_BUF_CTL(PORT_E),
166
				temp |
167
				DDI_BUF_CTL_ENABLE |
168
				DDI_PORT_WIDTH_X2 |
169
				hsw_ddi_buf_ctl_values[i]);
170
 
171
		udelay(600);
172
 
173
		/* We need to program FDI_RX_MISC with the default TP1 to TP2
174
		 * values before enabling the receiver, and configure the delay
175
		 * for the FDI timing generator to 90h. Luckily, all the other
176
		 * bits are supposed to be zeroed, so we can write those values
177
		 * directly.
178
		 */
179
		I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 |
180
				FDI_RX_FDI_DELAY_90);
181
 
182
		/* Enable CPU FDI Receiver with auto-training */
183
		reg = FDI_RX_CTL(pipe);
184
		I915_WRITE(reg,
185
				I915_READ(reg) |
186
					FDI_LINK_TRAIN_AUTO |
187
					FDI_RX_ENABLE |
188
					FDI_LINK_TRAIN_PATTERN_1_CPT |
189
					FDI_RX_ENHANCE_FRAME_ENABLE |
190
					FDI_PORT_WIDTH_2X_LPT |
191
					FDI_RX_PLL_ENABLE);
192
		POSTING_READ(reg);
193
		udelay(100);
194
 
195
		temp = I915_READ(DP_TP_STATUS(PORT_E));
196
		if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
197
			DRM_DEBUG_DRIVER("BUF_CTL training done on %d step\n", i);
198
 
199
			/* Enable normal pixel sending for FDI */
200
			I915_WRITE(DP_TP_CTL(PORT_E),
201
						DP_TP_CTL_FDI_AUTOTRAIN |
202
						DP_TP_CTL_LINK_TRAIN_NORMAL |
203
						DP_TP_CTL_ENHANCED_FRAME_ENABLE |
204
						DP_TP_CTL_ENABLE);
205
 
206
			/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */
207
			temp = I915_READ(DDI_FUNC_CTL(pipe));
208
			temp &= ~PIPE_DDI_PORT_MASK;
209
			temp |= PIPE_DDI_SELECT_PORT(PORT_E) |
210
					PIPE_DDI_MODE_SELECT_FDI |
211
					PIPE_DDI_FUNC_ENABLE |
212
					PIPE_DDI_PORT_WIDTH_X2;
213
			I915_WRITE(DDI_FUNC_CTL(pipe),
214
					temp);
215
			break;
216
		} else {
217
			DRM_ERROR("Error training BUF_CTL %d\n", i);
218
 
219
			/* Disable DP_TP_CTL and FDI_RX_CTL) and retry */
220
			I915_WRITE(DP_TP_CTL(PORT_E),
221
					I915_READ(DP_TP_CTL(PORT_E)) &
222
						~DP_TP_CTL_ENABLE);
223
			I915_WRITE(FDI_RX_CTL(pipe),
224
					I915_READ(FDI_RX_CTL(pipe)) &
225
						~FDI_RX_PLL_ENABLE);
226
			continue;
227
		}
228
	}
229
 
230
	DRM_DEBUG_KMS("FDI train done.\n");
231
}
232
 
233
/* For DDI connections, it is possible to support different outputs over the
234
 * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by
235
 * the time the output is detected what exactly is on the other end of it. This
236
 * function aims at providing support for this detection and proper output
237
 * configuration.
238
 */
239
void intel_ddi_init(struct drm_device *dev, enum port port)
240
{
241
	/* For now, we don't do any proper output detection and assume that we
242
	 * handle HDMI only */
243
 
244
	switch(port){
245
	case PORT_A:
246
		/* We don't handle eDP and DP yet */
247
		DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
248
		break;
249
	/* Assume that the  ports B, C and D are working in HDMI mode for now */
250
	case PORT_B:
251
	case PORT_C:
252
	case PORT_D:
253
		intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
254
		break;
255
	default:
256
		DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
257
				port);
258
		break;
259
	}
260
}
261
 
262
/* WRPLL clock dividers */
263
struct wrpll_tmds_clock {
264
	u32 clock;
265
	u16 p;		/* Post divider */
266
	u16 n2;		/* Feedback divider */
267
	u16 r2;		/* Reference divider */
268
};
269
 
270
/* Table of matching values for WRPLL clocks programming for each frequency.
271
 * The code assumes this table is sorted. */
272
static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
273
	{19750,	38,	25,	18},
274
	{20000,	48,	32,	18},
275
	{21000,	36,	21,	15},
276
	{21912,	42,	29,	17},
277
	{22000,	36,	22,	15},
278
	{23000,	36,	23,	15},
279
	{23500,	40,	40,	23},
280
	{23750,	26,	16,	14},
281
	{24000,	36,	24,	15},
282
	{25000,	36,	25,	15},
283
	{25175,	26,	40,	33},
284
	{25200,	30,	21,	15},
285
	{26000,	36,	26,	15},
286
	{27000,	30,	21,	14},
287
	{27027,	18,	100,	111},
288
	{27500,	30,	29,	19},
289
	{28000,	34,	30,	17},
290
	{28320,	26,	30,	22},
291
	{28322,	32,	42,	25},
292
	{28750,	24,	23,	18},
293
	{29000,	30,	29,	18},
294
	{29750,	32,	30,	17},
295
	{30000,	30,	25,	15},
296
	{30750,	30,	41,	24},
297
	{31000,	30,	31,	18},
298
	{31500,	30,	28,	16},
299
	{32000,	30,	32,	18},
300
	{32500,	28,	32,	19},
301
	{33000,	24,	22,	15},
302
	{34000,	28,	30,	17},
303
	{35000,	26,	32,	19},
304
	{35500,	24,	30,	19},
305
	{36000,	26,	26,	15},
306
	{36750,	26,	46,	26},
307
	{37000,	24,	23,	14},
308
	{37762,	22,	40,	26},
309
	{37800,	20,	21,	15},
310
	{38000,	24,	27,	16},
311
	{38250,	24,	34,	20},
312
	{39000,	24,	26,	15},
313
	{40000,	24,	32,	18},
314
	{40500,	20,	21,	14},
315
	{40541,	22,	147,	89},
316
	{40750,	18,	19,	14},
317
	{41000,	16,	17,	14},
318
	{41500,	22,	44,	26},
319
	{41540,	22,	44,	26},
320
	{42000,	18,	21,	15},
321
	{42500,	22,	45,	26},
322
	{43000,	20,	43,	27},
323
	{43163,	20,	24,	15},
324
	{44000,	18,	22,	15},
325
	{44900,	20,	108,	65},
326
	{45000,	20,	25,	15},
327
	{45250,	20,	52,	31},
328
	{46000,	18,	23,	15},
329
	{46750,	20,	45,	26},
330
	{47000,	20,	40,	23},
331
	{48000,	18,	24,	15},
332
	{49000,	18,	49,	30},
333
	{49500,	16,	22,	15},
334
	{50000,	18,	25,	15},
335
	{50500,	18,	32,	19},
336
	{51000,	18,	34,	20},
337
	{52000,	18,	26,	15},
338
	{52406,	14,	34,	25},
339
	{53000,	16,	22,	14},
340
	{54000,	16,	24,	15},
341
	{54054,	16,	173,	108},
342
	{54500,	14,	24,	17},
343
	{55000,	12,	22,	18},
344
	{56000,	14,	45,	31},
345
	{56250,	16,	25,	15},
346
	{56750,	14,	25,	17},
347
	{57000,	16,	27,	16},
348
	{58000,	16,	43,	25},
349
	{58250,	16,	38,	22},
350
	{58750,	16,	40,	23},
351
	{59000,	14,	26,	17},
352
	{59341,	14,	40,	26},
353
	{59400,	16,	44,	25},
354
	{60000,	16,	32,	18},
355
	{60500,	12,	39,	29},
356
	{61000,	14,	49,	31},
357
	{62000,	14,	37,	23},
358
	{62250,	14,	42,	26},
359
	{63000,	12,	21,	15},
360
	{63500,	14,	28,	17},
361
	{64000,	12,	27,	19},
362
	{65000,	14,	32,	19},
363
	{65250,	12,	29,	20},
364
	{65500,	12,	32,	22},
365
	{66000,	12,	22,	15},
366
	{66667,	14,	38,	22},
367
	{66750,	10,	21,	17},
368
	{67000,	14,	33,	19},
369
	{67750,	14,	58,	33},
370
	{68000,	14,	30,	17},
371
	{68179,	14,	46,	26},
372
	{68250,	14,	46,	26},
373
	{69000,	12,	23,	15},
374
	{70000,	12,	28,	18},
375
	{71000,	12,	30,	19},
376
	{72000,	12,	24,	15},
377
	{73000,	10,	23,	17},
378
	{74000,	12,	23,	14},
379
	{74176,	8,	100,	91},
380
	{74250,	10,	22,	16},
381
	{74481,	12,	43,	26},
382
	{74500,	10,	29,	21},
383
	{75000,	12,	25,	15},
384
	{75250,	10,	39,	28},
385
	{76000,	12,	27,	16},
386
	{77000,	12,	53,	31},
387
	{78000,	12,	26,	15},
388
	{78750,	12,	28,	16},
389
	{79000,	10,	38,	26},
390
	{79500,	10,	28,	19},
391
	{80000,	12,	32,	18},
392
	{81000,	10,	21,	14},
393
	{81081,	6,	100,	111},
394
	{81624,	8,	29,	24},
395
	{82000,	8,	17,	14},
396
	{83000,	10,	40,	26},
397
	{83950,	10,	28,	18},
398
	{84000,	10,	28,	18},
399
	{84750,	6,	16,	17},
400
	{85000,	6,	17,	18},
401
	{85250,	10,	30,	19},
402
	{85750,	10,	27,	17},
403
	{86000,	10,	43,	27},
404
	{87000,	10,	29,	18},
405
	{88000,	10,	44,	27},
406
	{88500,	10,	41,	25},
407
	{89000,	10,	28,	17},
408
	{89012,	6,	90,	91},
409
	{89100,	10,	33,	20},
410
	{90000,	10,	25,	15},
411
	{91000,	10,	32,	19},
412
	{92000,	10,	46,	27},
413
	{93000,	10,	31,	18},
414
	{94000,	10,	40,	23},
415
	{94500,	10,	28,	16},
416
	{95000,	10,	44,	25},
417
	{95654,	10,	39,	22},
418
	{95750,	10,	39,	22},
419
	{96000,	10,	32,	18},
420
	{97000,	8,	23,	16},
421
	{97750,	8,	42,	29},
422
	{98000,	8,	45,	31},
423
	{99000,	8,	22,	15},
424
	{99750,	8,	34,	23},
425
	{100000,	6,	20,	18},
426
	{100500,	6,	19,	17},
427
	{101000,	6,	37,	33},
428
	{101250,	8,	21,	14},
429
	{102000,	6,	17,	15},
430
	{102250,	6,	25,	22},
431
	{103000,	8,	29,	19},
432
	{104000,	8,	37,	24},
433
	{105000,	8,	28,	18},
434
	{106000,	8,	22,	14},
435
	{107000,	8,	46,	29},
436
	{107214,	8,	27,	17},
437
	{108000,	8,	24,	15},
438
	{108108,	8,	173,	108},
439
	{109000,	6,	23,	19},
440
	{110000,	6,	22,	18},
441
	{110013,	6,	22,	18},
442
	{110250,	8,	49,	30},
443
	{110500,	8,	36,	22},
444
	{111000,	8,	23,	14},
445
	{111264,	8,	150,	91},
446
	{111375,	8,	33,	20},
447
	{112000,	8,	63,	38},
448
	{112500,	8,	25,	15},
449
	{113100,	8,	57,	34},
450
	{113309,	8,	42,	25},
451
	{114000,	8,	27,	16},
452
	{115000,	6,	23,	18},
453
	{116000,	8,	43,	25},
454
	{117000,	8,	26,	15},
455
	{117500,	8,	40,	23},
456
	{118000,	6,	38,	29},
457
	{119000,	8,	30,	17},
458
	{119500,	8,	46,	26},
459
	{119651,	8,	39,	22},
460
	{120000,	8,	32,	18},
461
	{121000,	6,	39,	29},
462
	{121250,	6,	31,	23},
463
	{121750,	6,	23,	17},
464
	{122000,	6,	42,	31},
465
	{122614,	6,	30,	22},
466
	{123000,	6,	41,	30},
467
	{123379,	6,	37,	27},
468
	{124000,	6,	51,	37},
469
	{125000,	6,	25,	18},
470
	{125250,	4,	13,	14},
471
	{125750,	4,	27,	29},
472
	{126000,	6,	21,	15},
473
	{127000,	6,	24,	17},
474
	{127250,	6,	41,	29},
475
	{128000,	6,	27,	19},
476
	{129000,	6,	43,	30},
477
	{129859,	4,	25,	26},
478
	{130000,	6,	26,	18},
479
	{130250,	6,	42,	29},
480
	{131000,	6,	32,	22},
481
	{131500,	6,	38,	26},
482
	{131850,	6,	41,	28},
483
	{132000,	6,	22,	15},
484
	{132750,	6,	28,	19},
485
	{133000,	6,	34,	23},
486
	{133330,	6,	37,	25},
487
	{134000,	6,	61,	41},
488
	{135000,	6,	21,	14},
489
	{135250,	6,	167,	111},
490
	{136000,	6,	62,	41},
491
	{137000,	6,	35,	23},
492
	{138000,	6,	23,	15},
493
	{138500,	6,	40,	26},
494
	{138750,	6,	37,	24},
495
	{139000,	6,	34,	22},
496
	{139050,	6,	34,	22},
497
	{139054,	6,	34,	22},
498
	{140000,	6,	28,	18},
499
	{141000,	6,	36,	23},
500
	{141500,	6,	22,	14},
501
	{142000,	6,	30,	19},
502
	{143000,	6,	27,	17},
503
	{143472,	4,	17,	16},
504
	{144000,	6,	24,	15},
505
	{145000,	6,	29,	18},
506
	{146000,	6,	47,	29},
507
	{146250,	6,	26,	16},
508
	{147000,	6,	49,	30},
509
	{147891,	6,	23,	14},
510
	{148000,	6,	23,	14},
511
	{148250,	6,	28,	17},
512
	{148352,	4,	100,	91},
513
	{148500,	6,	33,	20},
514
	{149000,	6,	48,	29},
515
	{150000,	6,	25,	15},
516
	{151000,	4,	19,	17},
517
	{152000,	6,	27,	16},
518
	{152280,	6,	44,	26},
519
	{153000,	6,	34,	20},
520
	{154000,	6,	53,	31},
521
	{155000,	6,	31,	18},
522
	{155250,	6,	50,	29},
523
	{155750,	6,	45,	26},
524
	{156000,	6,	26,	15},
525
	{157000,	6,	61,	35},
526
	{157500,	6,	28,	16},
527
	{158000,	6,	65,	37},
528
	{158250,	6,	44,	25},
529
	{159000,	6,	53,	30},
530
	{159500,	6,	39,	22},
531
	{160000,	6,	32,	18},
532
	{161000,	4,	31,	26},
533
	{162000,	4,	18,	15},
534
	{162162,	4,	131,	109},
535
	{162500,	4,	53,	44},
536
	{163000,	4,	29,	24},
537
	{164000,	4,	17,	14},
538
	{165000,	4,	22,	18},
539
	{166000,	4,	32,	26},
540
	{167000,	4,	26,	21},
541
	{168000,	4,	46,	37},
542
	{169000,	4,	104,	83},
543
	{169128,	4,	64,	51},
544
	{169500,	4,	39,	31},
545
	{170000,	4,	34,	27},
546
	{171000,	4,	19,	15},
547
	{172000,	4,	51,	40},
548
	{172750,	4,	32,	25},
549
	{172800,	4,	32,	25},
550
	{173000,	4,	41,	32},
551
	{174000,	4,	49,	38},
552
	{174787,	4,	22,	17},
553
	{175000,	4,	35,	27},
554
	{176000,	4,	30,	23},
555
	{177000,	4,	38,	29},
556
	{178000,	4,	29,	22},
557
	{178500,	4,	37,	28},
558
	{179000,	4,	53,	40},
559
	{179500,	4,	73,	55},
560
	{180000,	4,	20,	15},
561
	{181000,	4,	55,	41},
562
	{182000,	4,	31,	23},
563
	{183000,	4,	42,	31},
564
	{184000,	4,	30,	22},
565
	{184750,	4,	26,	19},
566
	{185000,	4,	37,	27},
567
	{186000,	4,	51,	37},
568
	{187000,	4,	36,	26},
569
	{188000,	4,	32,	23},
570
	{189000,	4,	21,	15},
571
	{190000,	4,	38,	27},
572
	{190960,	4,	41,	29},
573
	{191000,	4,	41,	29},
574
	{192000,	4,	27,	19},
575
	{192250,	4,	37,	26},
576
	{193000,	4,	20,	14},
577
	{193250,	4,	53,	37},
578
	{194000,	4,	23,	16},
579
	{194208,	4,	23,	16},
580
	{195000,	4,	26,	18},
581
	{196000,	4,	45,	31},
582
	{197000,	4,	35,	24},
583
	{197750,	4,	41,	28},
584
	{198000,	4,	22,	15},
585
	{198500,	4,	25,	17},
586
	{199000,	4,	28,	19},
587
	{200000,	4,	37,	25},
588
	{201000,	4,	61,	41},
589
	{202000,	4,	112,	75},
590
	{202500,	4,	21,	14},
591
	{203000,	4,	146,	97},
592
	{204000,	4,	62,	41},
593
	{204750,	4,	44,	29},
594
	{205000,	4,	38,	25},
595
	{206000,	4,	29,	19},
596
	{207000,	4,	23,	15},
597
	{207500,	4,	40,	26},
598
	{208000,	4,	37,	24},
599
	{208900,	4,	48,	31},
600
	{209000,	4,	48,	31},
601
	{209250,	4,	31,	20},
602
	{210000,	4,	28,	18},
603
	{211000,	4,	25,	16},
604
	{212000,	4,	22,	14},
605
	{213000,	4,	30,	19},
606
	{213750,	4,	38,	24},
607
	{214000,	4,	46,	29},
608
	{214750,	4,	35,	22},
609
	{215000,	4,	43,	27},
610
	{216000,	4,	24,	15},
611
	{217000,	4,	37,	23},
612
	{218000,	4,	42,	26},
613
	{218250,	4,	42,	26},
614
	{218750,	4,	34,	21},
615
	{219000,	4,	47,	29},
616
	{220000,	4,	44,	27},
617
	{220640,	4,	49,	30},
618
	{220750,	4,	36,	22},
619
	{221000,	4,	36,	22},
620
	{222000,	4,	23,	14},
621
	{222525,	4,	28,	17},
622
	{222750,	4,	33,	20},
623
	{227000,	4,	37,	22},
624
	{230250,	4,	29,	17},
625
	{233500,	4,	38,	22},
626
	{235000,	4,	40,	23},
627
	{238000,	4,	30,	17},
628
	{241500,	2,	17,	19},
629
	{245250,	2,	20,	22},
630
	{247750,	2,	22,	24},
631
	{253250,	2,	15,	16},
632
	{256250,	2,	18,	19},
633
	{262500,	2,	31,	32},
634
	{267250,	2,	66,	67},
635
	{268500,	2,	94,	95},
636
	{270000,	2,	14,	14},
637
	{272500,	2,	77,	76},
638
	{273750,	2,	57,	56},
639
	{280750,	2,	24,	23},
640
	{281250,	2,	23,	22},
641
	{286000,	2,	17,	16},
642
	{291750,	2,	26,	24},
643
	{296703,	2,	56,	51},
644
	{297000,	2,	22,	20},
645
	{298000,	2,	21,	19},
646
};
647
 
648
void intel_ddi_mode_set(struct drm_encoder *encoder,
649
				struct drm_display_mode *mode,
650
				struct drm_display_mode *adjusted_mode)
651
{
652
	struct drm_device *dev = encoder->dev;
653
	struct drm_i915_private *dev_priv = dev->dev_private;
654
	struct drm_crtc *crtc = encoder->crtc;
655
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
656
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
657
	int port = intel_hdmi->ddi_port;
658
	int pipe = intel_crtc->pipe;
659
	int p, n2, r2;
660
	u32 temp, i;
661
 
662
	/* On Haswell, we need to enable the clocks and prepare DDI function to
663
	 * work in HDMI mode for this pipe.
664
	 */
665
	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
666
 
667
	for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
668
		if (crtc->mode.clock <= wrpll_tmds_clock_table[i].clock)
669
			break;
670
 
671
	if (i == ARRAY_SIZE(wrpll_tmds_clock_table))
672
		i--;
673
 
674
	p = wrpll_tmds_clock_table[i].p;
675
	n2 = wrpll_tmds_clock_table[i].n2;
676
	r2 = wrpll_tmds_clock_table[i].r2;
677
 
678
	if (wrpll_tmds_clock_table[i].clock != crtc->mode.clock)
679
		DRM_INFO("WR PLL: using settings for %dKHz on %dKHz mode\n",
680
			 wrpll_tmds_clock_table[i].clock, crtc->mode.clock);
681
 
682
	DRM_DEBUG_KMS("WR PLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
683
		      crtc->mode.clock, p, n2, r2);
684
 
685
	/* Enable LCPLL if disabled */
686
	temp = I915_READ(LCPLL_CTL);
687
	if (temp & LCPLL_PLL_DISABLE)
688
		I915_WRITE(LCPLL_CTL,
689
				temp & ~LCPLL_PLL_DISABLE);
690
 
691
	/* Configure WR PLL 1, program the correct divider values for
692
	 * the desired frequency and wait for warmup */
693
	I915_WRITE(WRPLL_CTL1,
694
			WRPLL_PLL_ENABLE |
695
			WRPLL_PLL_SELECT_LCPLL_2700 |
696
			WRPLL_DIVIDER_REFERENCE(r2) |
697
			WRPLL_DIVIDER_FEEDBACK(n2) |
698
			WRPLL_DIVIDER_POST(p));
699
 
700
	udelay(20);
701
 
702
	/* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
703
	 * this port for connection.
704
	 */
705
	I915_WRITE(PORT_CLK_SEL(port),
706
			PORT_CLK_SEL_WRPLL1);
707
	I915_WRITE(PIPE_CLK_SEL(pipe),
708
			PIPE_CLK_SEL_PORT(port));
709
 
710
	udelay(20);
711
 
712
	if (intel_hdmi->has_audio) {
713
		/* Proper support for digital audio needs a new logic and a new set
714
		 * of registers, so we leave it for future patch bombing.
715
		 */
716
		DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
717
				 pipe_name(intel_crtc->pipe));
718
 
719
		/* write eld */
720
		DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
721
		intel_write_eld(encoder, adjusted_mode);
722
	}
723
 
724
	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
725
	temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
726
 
727
	switch (intel_crtc->bpp) {
728
	case 18:
729
		temp |= PIPE_DDI_BPC_6;
730
		break;
731
	case 24:
732
		temp |= PIPE_DDI_BPC_8;
733
		break;
734
	case 30:
735
		temp |= PIPE_DDI_BPC_10;
736
		break;
737
	case 36:
738
		temp |= PIPE_DDI_BPC_12;
739
		break;
740
	default:
741
		WARN(1, "%d bpp unsupported by pipe DDI function\n",
742
		     intel_crtc->bpp);
743
	}
744
 
745
	if (intel_hdmi->has_hdmi_sink)
746
		temp |= PIPE_DDI_MODE_SELECT_HDMI;
747
	else
748
		temp |= PIPE_DDI_MODE_SELECT_DVI;
749
 
750
	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
751
		temp |= PIPE_DDI_PVSYNC;
752
	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
753
		temp |= PIPE_DDI_PHSYNC;
754
 
755
	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
756
 
757
	intel_hdmi->set_infoframes(encoder, adjusted_mode);
758
}
759
 
760
bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
761
			    enum pipe *pipe)
762
{
763
	struct drm_device *dev = encoder->base.dev;
764
	struct drm_i915_private *dev_priv = dev->dev_private;
765
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
766
	u32 tmp;
767
	int i;
768
 
769
	tmp = I915_READ(DDI_BUF_CTL(intel_hdmi->ddi_port));
770
 
771
	if (!(tmp & DDI_BUF_CTL_ENABLE))
772
		return false;
773
 
774
	for_each_pipe(i) {
775
		tmp = I915_READ(DDI_FUNC_CTL(i));
776
 
777
		if ((tmp & PIPE_DDI_PORT_MASK)
778
		    == PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port)) {
779
			*pipe = i;
780
			return true;
781
		}
782
	}
783
 
784
	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", intel_hdmi->ddi_port);
785
 
786
	return true;
787
}
788
 
789
void intel_enable_ddi(struct intel_encoder *encoder)
790
{
791
	struct drm_device *dev = encoder->base.dev;
792
	struct drm_i915_private *dev_priv = dev->dev_private;
793
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
794
	int port = intel_hdmi->ddi_port;
795
	u32 temp;
796
 
797
	temp = I915_READ(DDI_BUF_CTL(port));
798
	temp |= DDI_BUF_CTL_ENABLE;
799
 
800
	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
801
	 * and swing/emphasis values are ignored so nothing special needs
802
	 * to be done besides enabling the port.
803
	 */
804
	I915_WRITE(DDI_BUF_CTL(port), temp);
805
}
806
 
807
void intel_disable_ddi(struct intel_encoder *encoder)
808
{
809
	struct drm_device *dev = encoder->base.dev;
810
	struct drm_i915_private *dev_priv = dev->dev_private;
811
	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
812
	int port = intel_hdmi->ddi_port;
813
	u32 temp;
814
 
815
	temp = I915_READ(DDI_BUF_CTL(port));
816
	temp &= ~DDI_BUF_CTL_ENABLE;
817
 
818
	I915_WRITE(DDI_BUF_CTL(port), temp);
819
}