Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 <eugeni.dodonov@intel.com>
 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 */
 35static 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
 48static 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 */
 67void 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 */
 93void 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
109static 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
131void 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		/* Enable CPU FDI Receiver with auto-training */
174		reg = FDI_RX_CTL(pipe);
175		I915_WRITE(reg,
176				I915_READ(reg) |
177					FDI_LINK_TRAIN_AUTO |
178					FDI_RX_ENABLE |
179					FDI_LINK_TRAIN_PATTERN_1_CPT |
180					FDI_RX_ENHANCE_FRAME_ENABLE |
181					FDI_PORT_WIDTH_2X_LPT |
182					FDI_RX_PLL_ENABLE);
183		POSTING_READ(reg);
184		udelay(100);
185
186		temp = I915_READ(DP_TP_STATUS(PORT_E));
187		if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
188			DRM_DEBUG_DRIVER("BUF_CTL training done on %d step\n", i);
189
190			/* Enable normal pixel sending for FDI */
191			I915_WRITE(DP_TP_CTL(PORT_E),
192						DP_TP_CTL_FDI_AUTOTRAIN |
193						DP_TP_CTL_LINK_TRAIN_NORMAL |
194						DP_TP_CTL_ENHANCED_FRAME_ENABLE |
195						DP_TP_CTL_ENABLE);
196
197			/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in FDI mode */
198			temp = I915_READ(DDI_FUNC_CTL(pipe));
199			temp &= ~PIPE_DDI_PORT_MASK;
200			temp |= PIPE_DDI_SELECT_PORT(PORT_E) |
201					PIPE_DDI_MODE_SELECT_FDI |
202					PIPE_DDI_FUNC_ENABLE |
203					PIPE_DDI_PORT_WIDTH_X2;
204			I915_WRITE(DDI_FUNC_CTL(pipe),
205					temp);
206			break;
207		} else {
208			DRM_ERROR("Error training BUF_CTL %d\n", i);
209
210			/* Disable DP_TP_CTL and FDI_RX_CTL) and retry */
211			I915_WRITE(DP_TP_CTL(PORT_E),
212					I915_READ(DP_TP_CTL(PORT_E)) &
213						~DP_TP_CTL_ENABLE);
214			I915_WRITE(FDI_RX_CTL(pipe),
215					I915_READ(FDI_RX_CTL(pipe)) &
216						~FDI_RX_PLL_ENABLE);
217			continue;
218		}
219	}
220
221	DRM_DEBUG_KMS("FDI train done.\n");
222}
223
224/* For DDI connections, it is possible to support different outputs over the
225 * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by
226 * the time the output is detected what exactly is on the other end of it. This
227 * function aims at providing support for this detection and proper output
228 * configuration.
229 */
230void intel_ddi_init(struct drm_device *dev, enum port port)
231{
232	/* For now, we don't do any proper output detection and assume that we
233	 * handle HDMI only */
234
235	switch(port){
236	case PORT_A:
237		/* We don't handle eDP and DP yet */
238		DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
239		break;
240	/* Assume that the  ports B, C and D are working in HDMI mode for now */
241	case PORT_B:
242	case PORT_C:
243	case PORT_D:
244		intel_hdmi_init(dev, DDI_BUF_CTL(port));
245		break;
246	default:
247		DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
248				port);
249		break;
250	}
251}
252
253/* WRPLL clock dividers */
254struct wrpll_tmds_clock {
255	u32 clock;
256	u16 p;		/* Post divider */
257	u16 n2;		/* Feedback divider */
258	u16 r2;		/* Reference divider */
259};
260
261/* Table of matching values for WRPLL clocks programming for each frequency */
262static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
263	{19750,	38,	25,	18},
264	{20000,	48,	32,	18},
265	{21000,	36,	21,	15},
266	{21912,	42,	29,	17},
267	{22000,	36,	22,	15},
268	{23000,	36,	23,	15},
269	{23500,	40,	40,	23},
270	{23750,	26,	16,	14},
271	{23750,	26,	16,	14},
272	{24000,	36,	24,	15},
273	{25000,	36,	25,	15},
274	{25175,	26,	40,	33},
275	{25200,	30,	21,	15},
276	{26000,	36,	26,	15},
277	{27000,	30,	21,	14},
278	{27027,	18,	100,	111},
279	{27500,	30,	29,	19},
280	{28000,	34,	30,	17},
281	{28320,	26,	30,	22},
282	{28322,	32,	42,	25},
283	{28750,	24,	23,	18},
284	{29000,	30,	29,	18},
285	{29750,	32,	30,	17},
286	{30000,	30,	25,	15},
287	{30750,	30,	41,	24},
288	{31000,	30,	31,	18},
289	{31500,	30,	28,	16},
290	{32000,	30,	32,	18},
291	{32500,	28,	32,	19},
292	{33000,	24,	22,	15},
293	{34000,	28,	30,	17},
294	{35000,	26,	32,	19},
295	{35500,	24,	30,	19},
296	{36000,	26,	26,	15},
297	{36750,	26,	46,	26},
298	{37000,	24,	23,	14},
299	{37762,	22,	40,	26},
300	{37800,	20,	21,	15},
301	{38000,	24,	27,	16},
302	{38250,	24,	34,	20},
303	{39000,	24,	26,	15},
304	{40000,	24,	32,	18},
305	{40500,	20,	21,	14},
306	{40541,	22,	147,	89},
307	{40750,	18,	19,	14},
308	{41000,	16,	17,	14},
309	{41500,	22,	44,	26},
310	{41540,	22,	44,	26},
311	{42000,	18,	21,	15},
312	{42500,	22,	45,	26},
313	{43000,	20,	43,	27},
314	{43163,	20,	24,	15},
315	{44000,	18,	22,	15},
316	{44900,	20,	108,	65},
317	{45000,	20,	25,	15},
318	{45250,	20,	52,	31},
319	{46000,	18,	23,	15},
320	{46750,	20,	45,	26},
321	{47000,	20,	40,	23},
322	{48000,	18,	24,	15},
323	{49000,	18,	49,	30},
324	{49500,	16,	22,	15},
325	{50000,	18,	25,	15},
326	{50500,	18,	32,	19},
327	{51000,	18,	34,	20},
328	{52000,	18,	26,	15},
329	{52406,	14,	34,	25},
330	{53000,	16,	22,	14},
331	{54000,	16,	24,	15},
332	{54054,	16,	173,	108},
333	{54500,	14,	24,	17},
334	{55000,	12,	22,	18},
335	{56000,	14,	45,	31},
336	{56250,	16,	25,	15},
337	{56750,	14,	25,	17},
338	{57000,	16,	27,	16},
339	{58000,	16,	43,	25},
340	{58250,	16,	38,	22},
341	{58750,	16,	40,	23},
342	{59000,	14,	26,	17},
343	{59341,	14,	40,	26},
344	{59400,	16,	44,	25},
345	{60000,	16,	32,	18},
346	{60500,	12,	39,	29},
347	{61000,	14,	49,	31},
348	{62000,	14,	37,	23},
349	{62250,	14,	42,	26},
350	{63000,	12,	21,	15},
351	{63500,	14,	28,	17},
352	{64000,	12,	27,	19},
353	{65000,	14,	32,	19},
354	{65250,	12,	29,	20},
355	{65500,	12,	32,	22},
356	{66000,	12,	22,	15},
357	{66667,	14,	38,	22},
358	{66750,	10,	21,	17},
359	{67000,	14,	33,	19},
360	{67750,	14,	58,	33},
361	{68000,	14,	30,	17},
362	{68179,	14,	46,	26},
363	{68250,	14,	46,	26},
364	{69000,	12,	23,	15},
365	{70000,	12,	28,	18},
366	{71000,	12,	30,	19},
367	{72000,	12,	24,	15},
368	{73000,	10,	23,	17},
369	{74000,	12,	23,	14},
370	{74176,	8,	100,	91},
371	{74250,	10,	22,	16},
372	{74481,	12,	43,	26},
373	{74500,	10,	29,	21},
374	{75000,	12,	25,	15},
375	{75250,	10,	39,	28},
376	{76000,	12,	27,	16},
377	{77000,	12,	53,	31},
378	{78000,	12,	26,	15},
379	{78750,	12,	28,	16},
380	{79000,	10,	38,	26},
381	{79500,	10,	28,	19},
382	{80000,	12,	32,	18},
383	{81000,	10,	21,	14},
384	{81081,	6,	100,	111},
385	{81624,	8,	29,	24},
386	{82000,	8,	17,	14},
387	{83000,	10,	40,	26},
388	{83950,	10,	28,	18},
389	{84000,	10,	28,	18},
390	{84750,	6,	16,	17},
391	{85000,	6,	17,	18},
392	{85250,	10,	30,	19},
393	{85750,	10,	27,	17},
394	{86000,	10,	43,	27},
395	{87000,	10,	29,	18},
396	{88000,	10,	44,	27},
397	{88500,	10,	41,	25},
398	{89000,	10,	28,	17},
399	{89012,	6,	90,	91},
400	{89100,	10,	33,	20},
401	{90000,	10,	25,	15},
402	{91000,	10,	32,	19},
403	{92000,	10,	46,	27},
404	{93000,	10,	31,	18},
405	{94000,	10,	40,	23},
406	{94500,	10,	28,	16},
407	{95000,	10,	44,	25},
408	{95654,	10,	39,	22},
409	{95750,	10,	39,	22},
410	{96000,	10,	32,	18},
411	{97000,	8,	23,	16},
412	{97750,	8,	42,	29},
413	{98000,	8,	45,	31},
414	{99000,	8,	22,	15},
415	{99750,	8,	34,	23},
416	{100000,	6,	20,	18},
417	{100500,	6,	19,	17},
418	{101000,	6,	37,	33},
419	{101250,	8,	21,	14},
420	{102000,	6,	17,	15},
421	{102250,	6,	25,	22},
422	{103000,	8,	29,	19},
423	{104000,	8,	37,	24},
424	{105000,	8,	28,	18},
425	{106000,	8,	22,	14},
426	{107000,	8,	46,	29},
427	{107214,	8,	27,	17},
428	{108000,	8,	24,	15},
429	{108108,	8,	173,	108},
430	{109000,	6,	23,	19},
431	{109000,	6,	23,	19},
432	{110000,	6,	22,	18},
433	{110013,	6,	22,	18},
434	{110250,	8,	49,	30},
435	{110500,	8,	36,	22},
436	{111000,	8,	23,	14},
437	{111264,	8,	150,	91},
438	{111375,	8,	33,	20},
439	{112000,	8,	63,	38},
440	{112500,	8,	25,	15},
441	{113100,	8,	57,	34},
442	{113309,	8,	42,	25},
443	{114000,	8,	27,	16},
444	{115000,	6,	23,	18},
445	{116000,	8,	43,	25},
446	{117000,	8,	26,	15},
447	{117500,	8,	40,	23},
448	{118000,	6,	38,	29},
449	{119000,	8,	30,	17},
450	{119500,	8,	46,	26},
451	{119651,	8,	39,	22},
452	{120000,	8,	32,	18},
453	{121000,	6,	39,	29},
454	{121250,	6,	31,	23},
455	{121750,	6,	23,	17},
456	{122000,	6,	42,	31},
457	{122614,	6,	30,	22},
458	{123000,	6,	41,	30},
459	{123379,	6,	37,	27},
460	{124000,	6,	51,	37},
461	{125000,	6,	25,	18},
462	{125250,	4,	13,	14},
463	{125750,	4,	27,	29},
464	{126000,	6,	21,	15},
465	{127000,	6,	24,	17},
466	{127250,	6,	41,	29},
467	{128000,	6,	27,	19},
468	{129000,	6,	43,	30},
469	{129859,	4,	25,	26},
470	{130000,	6,	26,	18},
471	{130250,	6,	42,	29},
472	{131000,	6,	32,	22},
473	{131500,	6,	38,	26},
474	{131850,	6,	41,	28},
475	{132000,	6,	22,	15},
476	{132750,	6,	28,	19},
477	{133000,	6,	34,	23},
478	{133330,	6,	37,	25},
479	{134000,	6,	61,	41},
480	{135000,	6,	21,	14},
481	{135250,	6,	167,	111},
482	{136000,	6,	62,	41},
483	{137000,	6,	35,	23},
484	{138000,	6,	23,	15},
485	{138500,	6,	40,	26},
486	{138750,	6,	37,	24},
487	{139000,	6,	34,	22},
488	{139050,	6,	34,	22},
489	{139054,	6,	34,	22},
490	{140000,	6,	28,	18},
491	{141000,	6,	36,	23},
492	{141500,	6,	22,	14},
493	{142000,	6,	30,	19},
494	{143000,	6,	27,	17},
495	{143472,	4,	17,	16},
496	{144000,	6,	24,	15},
497	{145000,	6,	29,	18},
498	{146000,	6,	47,	29},
499	{146250,	6,	26,	16},
500	{147000,	6,	49,	30},
501	{147891,	6,	23,	14},
502	{148000,	6,	23,	14},
503	{148250,	6,	28,	17},
504	{148352,	4,	100,	91},
505	{148500,	6,	33,	20},
506	{149000,	6,	48,	29},
507	{150000,	6,	25,	15},
508	{151000,	4,	19,	17},
509	{152000,	6,	27,	16},
510	{152280,	6,	44,	26},
511	{153000,	6,	34,	20},
512	{154000,	6,	53,	31},
513	{155000,	6,	31,	18},
514	{155250,	6,	50,	29},
515	{155750,	6,	45,	26},
516	{156000,	6,	26,	15},
517	{157000,	6,	61,	35},
518	{157500,	6,	28,	16},
519	{158000,	6,	65,	37},
520	{158250,	6,	44,	25},
521	{159000,	6,	53,	30},
522	{159500,	6,	39,	22},
523	{160000,	6,	32,	18},
524	{161000,	4,	31,	26},
525	{162000,	4,	18,	15},
526	{162162,	4,	131,	109},
527	{162500,	4,	53,	44},
528	{163000,	4,	29,	24},
529	{164000,	4,	17,	14},
530	{165000,	4,	22,	18},
531	{166000,	4,	32,	26},
532	{167000,	4,	26,	21},
533	{168000,	4,	46,	37},
534	{169000,	4,	104,	83},
535	{169128,	4,	64,	51},
536	{169500,	4,	39,	31},
537	{170000,	4,	34,	27},
538	{171000,	4,	19,	15},
539	{172000,	4,	51,	40},
540	{172750,	4,	32,	25},
541	{172800,	4,	32,	25},
542	{173000,	4,	41,	32},
543	{174000,	4,	49,	38},
544	{174787,	4,	22,	17},
545	{175000,	4,	35,	27},
546	{176000,	4,	30,	23},
547	{177000,	4,	38,	29},
548	{178000,	4,	29,	22},
549	{178500,	4,	37,	28},
550	{179000,	4,	53,	40},
551	{179500,	4,	73,	55},
552	{180000,	4,	20,	15},
553	{181000,	4,	55,	41},
554	{182000,	4,	31,	23},
555	{183000,	4,	42,	31},
556	{184000,	4,	30,	22},
557	{184750,	4,	26,	19},
558	{185000,	4,	37,	27},
559	{186000,	4,	51,	37},
560	{187000,	4,	36,	26},
561	{188000,	4,	32,	23},
562	{189000,	4,	21,	15},
563	{190000,	4,	38,	27},
564	{190960,	4,	41,	29},
565	{191000,	4,	41,	29},
566	{192000,	4,	27,	19},
567	{192250,	4,	37,	26},
568	{193000,	4,	20,	14},
569	{193250,	4,	53,	37},
570	{194000,	4,	23,	16},
571	{194208,	4,	23,	16},
572	{195000,	4,	26,	18},
573	{196000,	4,	45,	31},
574	{197000,	4,	35,	24},
575	{197750,	4,	41,	28},
576	{198000,	4,	22,	15},
577	{198500,	4,	25,	17},
578	{199000,	4,	28,	19},
579	{200000,	4,	37,	25},
580	{201000,	4,	61,	41},
581	{202000,	4,	112,	75},
582	{202500,	4,	21,	14},
583	{203000,	4,	146,	97},
584	{204000,	4,	62,	41},
585	{204750,	4,	44,	29},
586	{205000,	4,	38,	25},
587	{206000,	4,	29,	19},
588	{207000,	4,	23,	15},
589	{207500,	4,	40,	26},
590	{208000,	4,	37,	24},
591	{208900,	4,	48,	31},
592	{209000,	4,	48,	31},
593	{209250,	4,	31,	20},
594	{210000,	4,	28,	18},
595	{211000,	4,	25,	16},
596	{212000,	4,	22,	14},
597	{213000,	4,	30,	19},
598	{213750,	4,	38,	24},
599	{214000,	4,	46,	29},
600	{214750,	4,	35,	22},
601	{215000,	4,	43,	27},
602	{216000,	4,	24,	15},
603	{217000,	4,	37,	23},
604	{218000,	4,	42,	26},
605	{218250,	4,	42,	26},
606	{218750,	4,	34,	21},
607	{219000,	4,	47,	29},
608	{219000,	4,	47,	29},
609	{220000,	4,	44,	27},
610	{220640,	4,	49,	30},
611	{220750,	4,	36,	22},
612	{221000,	4,	36,	22},
613	{222000,	4,	23,	14},
614	{222525,	4,	28,	17},
615	{222750,	4,	33,	20},
616	{227000,	4,	37,	22},
617	{230250,	4,	29,	17},
618	{233500,	4,	38,	22},
619	{235000,	4,	40,	23},
620	{238000,	4,	30,	17},
621	{241500,	2,	17,	19},
622	{245250,	2,	20,	22},
623	{247750,	2,	22,	24},
624	{253250,	2,	15,	16},
625	{256250,	2,	18,	19},
626	{262500,	2,	31,	32},
627	{267250,	2,	66,	67},
628	{268500,	2,	94,	95},
629	{270000,	2,	14,	14},
630	{272500,	2,	77,	76},
631	{273750,	2,	57,	56},
632	{280750,	2,	24,	23},
633	{281250,	2,	23,	22},
634	{286000,	2,	17,	16},
635	{291750,	2,	26,	24},
636	{296703,	2,	56,	51},
637	{297000,	2,	22,	20},
638	{298000,	2,	21,	19},
639};
640
641void intel_ddi_mode_set(struct drm_encoder *encoder,
642				struct drm_display_mode *mode,
643				struct drm_display_mode *adjusted_mode)
644{
645	struct drm_device *dev = encoder->dev;
646	struct drm_i915_private *dev_priv = dev->dev_private;
647	struct drm_crtc *crtc = encoder->crtc;
648	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
649	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
650	int port = intel_hdmi->ddi_port;
651	int pipe = intel_crtc->pipe;
652	int p, n2, r2, valid=0;
653	u32 temp, i;
654
655	/* On Haswell, we need to enable the clocks and prepare DDI function to
656	 * work in HDMI mode for this pipe.
657	 */
658	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
659
660	for (i=0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) {
661		if (crtc->mode.clock == wrpll_tmds_clock_table[i].clock) {
662			p = wrpll_tmds_clock_table[i].p;
663			n2 = wrpll_tmds_clock_table[i].n2;
664			r2 = wrpll_tmds_clock_table[i].r2;
665
666			DRM_DEBUG_KMS("WR PLL clock: found settings for %dKHz refresh rate: p=%d, n2=%d, r2=%d\n",
667					crtc->mode.clock,
668					p, n2, r2);
669
670			valid = 1;
671			break;
672		}
673	}
674
675	if (!valid) {
676		DRM_ERROR("Unable to find WR PLL clock settings for %dKHz refresh rate\n",
677				crtc->mode.clock);
678		return;
679	}
680
681	/* Enable LCPLL if disabled */
682	temp = I915_READ(LCPLL_CTL);
683	if (temp & LCPLL_PLL_DISABLE)
684		I915_WRITE(LCPLL_CTL,
685				temp & ~LCPLL_PLL_DISABLE);
686
687	/* Configure WR PLL 1, program the correct divider values for
688	 * the desired frequency and wait for warmup */
689	I915_WRITE(WRPLL_CTL1,
690			WRPLL_PLL_ENABLE |
691			WRPLL_PLL_SELECT_LCPLL_2700 |
692			WRPLL_DIVIDER_REFERENCE(r2) |
693			WRPLL_DIVIDER_FEEDBACK(n2) |
694			WRPLL_DIVIDER_POST(p));
695
696	udelay(20);
697
698	/* Use WRPLL1 clock to drive the output to the port, and tell the pipe to use
699	 * this port for connection.
700	 */
701	I915_WRITE(PORT_CLK_SEL(port),
702			PORT_CLK_SEL_WRPLL1);
703	I915_WRITE(PIPE_CLK_SEL(pipe),
704			PIPE_CLK_SEL_PORT(port));
705
706	udelay(20);
707
708	if (intel_hdmi->has_audio) {
709		/* Proper support for digital audio needs a new logic and a new set
710		 * of registers, so we leave it for future patch bombing.
711		 */
712		DRM_DEBUG_DRIVER("HDMI audio on pipe %c not yet supported on DDI\n",
713				 pipe_name(intel_crtc->pipe));
714	}
715
716	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
717	temp = I915_READ(DDI_FUNC_CTL(pipe));
718	temp &= ~PIPE_DDI_PORT_MASK;
719	temp &= ~PIPE_DDI_BPC_12;
720	temp |= PIPE_DDI_SELECT_PORT(port) |
721			PIPE_DDI_MODE_SELECT_HDMI |
722			((intel_crtc->bpp > 24) ?
723				PIPE_DDI_BPC_12 :
724				PIPE_DDI_BPC_8) |
725			PIPE_DDI_FUNC_ENABLE;
726
727	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
728
729	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
730	intel_hdmi_set_spd_infoframe(encoder);
731}
732
733void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
734{
735	struct drm_device *dev = encoder->dev;
736	struct drm_i915_private *dev_priv = dev->dev_private;
737	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
738	int port = intel_hdmi->ddi_port;
739	u32 temp;
740
741	temp = I915_READ(DDI_BUF_CTL(port));
742
743	if (mode != DRM_MODE_DPMS_ON) {
744		temp &= ~DDI_BUF_CTL_ENABLE;
745	} else {
746		temp |= DDI_BUF_CTL_ENABLE;
747	}
748
749	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
750	 * and swing/emphasis values are ignored so nothing special needs
751	 * to be done besides enabling the port.
752	 */
753	I915_WRITE(DDI_BUF_CTL(port),
754			temp);
755}