Blame view

drivers/gpu/drm/i915/intel_hdmi.c 39.3 KB
7d57382e6   Eric Anholt   drm/i915: Add sup...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * Copyright 2006 Dave Airlie <airlied@linux.ie>
   * Copyright © 2006-2009 Intel Corporation
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
   * to deal in the Software without restriction, including without limitation
   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   * and/or sell copies of the Software, and to permit persons to whom the
   * Software is furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice (including the next
   * paragraph) shall be included in all copies or substantial portions of the
   * Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   * DEALINGS IN THE SOFTWARE.
   *
   * Authors:
   *	Eric Anholt <eric@anholt.net>
   *	Jesse Barnes <jesse.barnes@intel.com>
   */
  
  #include <linux/i2c.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
30
  #include <linux/slab.h>
7d57382e6   Eric Anholt   drm/i915: Add sup...
31
  #include <linux/delay.h>
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
32
  #include <linux/hdmi.h>
760285e7e   David Howells   UAPI: (Scripted) ...
33
34
35
  #include <drm/drmP.h>
  #include <drm/drm_crtc.h>
  #include <drm/drm_edid.h>
7d57382e6   Eric Anholt   drm/i915: Add sup...
36
  #include "intel_drv.h"
760285e7e   David Howells   UAPI: (Scripted) ...
37
  #include <drm/i915_drm.h>
7d57382e6   Eric Anholt   drm/i915: Add sup...
38
  #include "i915_drv.h"
30add22d8   Paulo Zanoni   drm/i915: add int...
39
40
  static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
  {
da63a9f2e   Paulo Zanoni   drm/i915: create ...
41
  	return hdmi_to_dig_port(intel_hdmi)->base.base.dev;
30add22d8   Paulo Zanoni   drm/i915: add int...
42
  }
afba01889   Daniel Vetter   drm/i915: ensure ...
43
44
45
  static void
  assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)
  {
30add22d8   Paulo Zanoni   drm/i915: add int...
46
  	struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);
afba01889   Daniel Vetter   drm/i915: ensure ...
47
48
  	struct drm_i915_private *dev_priv = dev->dev_private;
  	uint32_t enabled_bits;
affa93544   Paulo Zanoni   drm/i915: add HAS...
49
  	enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
afba01889   Daniel Vetter   drm/i915: ensure ...
50

b242b7f74   Paulo Zanoni   drm/i915: rename ...
51
  	WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits,
afba01889   Daniel Vetter   drm/i915: ensure ...
52
53
54
  	     "HDMI port enabled, expecting disabled
  ");
  }
f5bbfca3e   Eugeni Dodonov   drm/i915: move HD...
55
  struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
ea5b213ad   Chris Wilson   drm/i915: Subclas...
56
  {
da63a9f2e   Paulo Zanoni   drm/i915: create ...
57
58
59
  	struct intel_digital_port *intel_dig_port =
  		container_of(encoder, struct intel_digital_port, base.base);
  	return &intel_dig_port->hdmi;
ea5b213ad   Chris Wilson   drm/i915: Subclas...
60
  }
df0e92488   Chris Wilson   drm/i915: Make th...
61
62
  static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
  {
da63a9f2e   Paulo Zanoni   drm/i915: create ...
63
  	return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base);
df0e92488   Chris Wilson   drm/i915: Make th...
64
  }
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
65
  static u32 g4x_infoframe_index(enum hdmi_infoframe_type type)
3c17fe4b8   David Härdeman   i915: enable AVI ...
66
  {
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
67
68
  	switch (type) {
  	case HDMI_INFOFRAME_TYPE_AVI:
ed517fbbb   Paulo Zanoni   drm/i915: small h...
69
  		return VIDEO_DIP_SELECT_AVI;
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
70
  	case HDMI_INFOFRAME_TYPE_SPD:
ed517fbbb   Paulo Zanoni   drm/i915: small h...
71
  		return VIDEO_DIP_SELECT_SPD;
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
72
73
  	case HDMI_INFOFRAME_TYPE_VENDOR:
  		return VIDEO_DIP_SELECT_VENDOR;
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
74
  	default:
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
75
76
  		DRM_DEBUG_DRIVER("unknown info frame type %d
  ", type);
ed517fbbb   Paulo Zanoni   drm/i915: small h...
77
  		return 0;
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
78
  	}
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
79
  }
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
80
  static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type)
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
81
  {
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
82
83
  	switch (type) {
  	case HDMI_INFOFRAME_TYPE_AVI:
ed517fbbb   Paulo Zanoni   drm/i915: small h...
84
  		return VIDEO_DIP_ENABLE_AVI;
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
85
  	case HDMI_INFOFRAME_TYPE_SPD:
ed517fbbb   Paulo Zanoni   drm/i915: small h...
86
  		return VIDEO_DIP_ENABLE_SPD;
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
87
88
  	case HDMI_INFOFRAME_TYPE_VENDOR:
  		return VIDEO_DIP_ENABLE_VENDOR;
fa193ff79   Paulo Zanoni   drm/i915: break i...
89
  	default:
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
90
91
  		DRM_DEBUG_DRIVER("unknown info frame type %d
  ", type);
ed517fbbb   Paulo Zanoni   drm/i915: small h...
92
  		return 0;
fa193ff79   Paulo Zanoni   drm/i915: break i...
93
  	}
fa193ff79   Paulo Zanoni   drm/i915: break i...
94
  }
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
95
  static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type)
2da8af540   Paulo Zanoni   drm/i915: impleme...
96
  {
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
97
98
  	switch (type) {
  	case HDMI_INFOFRAME_TYPE_AVI:
2da8af540   Paulo Zanoni   drm/i915: impleme...
99
  		return VIDEO_DIP_ENABLE_AVI_HSW;
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
100
  	case HDMI_INFOFRAME_TYPE_SPD:
2da8af540   Paulo Zanoni   drm/i915: impleme...
101
  		return VIDEO_DIP_ENABLE_SPD_HSW;
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
102
103
  	case HDMI_INFOFRAME_TYPE_VENDOR:
  		return VIDEO_DIP_ENABLE_VS_HSW;
2da8af540   Paulo Zanoni   drm/i915: impleme...
104
  	default:
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
105
106
  		DRM_DEBUG_DRIVER("unknown info frame type %d
  ", type);
2da8af540   Paulo Zanoni   drm/i915: impleme...
107
108
109
  		return 0;
  	}
  }
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
110
  static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type,
a57c774ab   Antti Koskipaa   drm/i915: Reorgan...
111
112
  				  enum transcoder cpu_transcoder,
  				  struct drm_i915_private *dev_priv)
2da8af540   Paulo Zanoni   drm/i915: impleme...
113
  {
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
114
115
  	switch (type) {
  	case HDMI_INFOFRAME_TYPE_AVI:
7d9bcebe1   Rodrigo Vivi   drm/i915: Use cpu...
116
  		return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder);
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
117
  	case HDMI_INFOFRAME_TYPE_SPD:
7d9bcebe1   Rodrigo Vivi   drm/i915: Use cpu...
118
  		return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder);
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
119
120
  	case HDMI_INFOFRAME_TYPE_VENDOR:
  		return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder);
2da8af540   Paulo Zanoni   drm/i915: impleme...
121
  	default:
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
122
123
  		DRM_DEBUG_DRIVER("unknown info frame type %d
  ", type);
2da8af540   Paulo Zanoni   drm/i915: impleme...
124
125
126
  		return 0;
  	}
  }
a3da1df7b   Daniel Vetter   drm/i915: s/i9xx_...
127
  static void g4x_write_infoframe(struct drm_encoder *encoder,
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
128
  				enum hdmi_infoframe_type type,
fff638676   Ville Syrjälä   drm/i915: Don't c...
129
  				const void *frame, ssize_t len)
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
130
  {
fff638676   Ville Syrjälä   drm/i915: Don't c...
131
  	const uint32_t *data = frame;
3c17fe4b8   David Härdeman   i915: enable AVI ...
132
133
  	struct drm_device *dev = encoder->dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
22509ec86   Paulo Zanoni   drm/i915: change ...
134
  	u32 val = I915_READ(VIDEO_DIP_CTL);
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
135
  	int i;
3c17fe4b8   David Härdeman   i915: enable AVI ...
136

822974aea   Paulo Zanoni   drm/i915: enable ...
137
138
  	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled
  ");
1d4f85ac2   Paulo Zanoni   drm/i915: start w...
139
  	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
140
  	val |= g4x_infoframe_index(type);
22509ec86   Paulo Zanoni   drm/i915: change ...
141

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
142
  	val &= ~g4x_infoframe_enable(type);
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
143

22509ec86   Paulo Zanoni   drm/i915: change ...
144
  	I915_WRITE(VIDEO_DIP_CTL, val);
3c17fe4b8   David Härdeman   i915: enable AVI ...
145

9d9740f09   Paulo Zanoni   drm/i915: add som...
146
  	mmiowb();
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
147
  	for (i = 0; i < len; i += 4) {
3c17fe4b8   David Härdeman   i915: enable AVI ...
148
149
150
  		I915_WRITE(VIDEO_DIP_DATA, *data);
  		data++;
  	}
adf00b26d   Paulo Zanoni   drm/i915: make su...
151
152
153
  	/* Write every possible data byte to force correct ECC calculation. */
  	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
  		I915_WRITE(VIDEO_DIP_DATA, 0);
9d9740f09   Paulo Zanoni   drm/i915: add som...
154
  	mmiowb();
3c17fe4b8   David Härdeman   i915: enable AVI ...
155

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
156
  	val |= g4x_infoframe_enable(type);
60c5ea2dd   Paulo Zanoni   drm/i915: mask th...
157
  	val &= ~VIDEO_DIP_FREQ_MASK;
4b24c9331   Daniel Vetter   drm/i915: replace...
158
  	val |= VIDEO_DIP_FREQ_VSYNC;
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
159

22509ec86   Paulo Zanoni   drm/i915: change ...
160
  	I915_WRITE(VIDEO_DIP_CTL, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
161
  	POSTING_READ(VIDEO_DIP_CTL);
3c17fe4b8   David Härdeman   i915: enable AVI ...
162
  }
fdf1250aa   Paulo Zanoni   drm/i915: split i...
163
  static void ibx_write_infoframe(struct drm_encoder *encoder,
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
164
  				enum hdmi_infoframe_type type,
fff638676   Ville Syrjälä   drm/i915: Don't c...
165
  				const void *frame, ssize_t len)
fdf1250aa   Paulo Zanoni   drm/i915: split i...
166
  {
fff638676   Ville Syrjälä   drm/i915: Don't c...
167
  	const uint32_t *data = frame;
fdf1250aa   Paulo Zanoni   drm/i915: split i...
168
169
  	struct drm_device *dev = encoder->dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
ed517fbbb   Paulo Zanoni   drm/i915: small h...
170
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
171
  	int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
fdf1250aa   Paulo Zanoni   drm/i915: split i...
172
  	u32 val = I915_READ(reg);
822974aea   Paulo Zanoni   drm/i915: enable ...
173
174
  	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled
  ");
fdf1250aa   Paulo Zanoni   drm/i915: split i...
175
  	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
176
  	val |= g4x_infoframe_index(type);
fdf1250aa   Paulo Zanoni   drm/i915: split i...
177

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
178
  	val &= ~g4x_infoframe_enable(type);
fdf1250aa   Paulo Zanoni   drm/i915: split i...
179
180
  
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
181
  	mmiowb();
fdf1250aa   Paulo Zanoni   drm/i915: split i...
182
183
184
185
  	for (i = 0; i < len; i += 4) {
  		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
  		data++;
  	}
adf00b26d   Paulo Zanoni   drm/i915: make su...
186
187
188
  	/* Write every possible data byte to force correct ECC calculation. */
  	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
  		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
9d9740f09   Paulo Zanoni   drm/i915: add som...
189
  	mmiowb();
fdf1250aa   Paulo Zanoni   drm/i915: split i...
190

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
191
  	val |= g4x_infoframe_enable(type);
fdf1250aa   Paulo Zanoni   drm/i915: split i...
192
  	val &= ~VIDEO_DIP_FREQ_MASK;
4b24c9331   Daniel Vetter   drm/i915: replace...
193
  	val |= VIDEO_DIP_FREQ_VSYNC;
fdf1250aa   Paulo Zanoni   drm/i915: split i...
194
195
  
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
196
  	POSTING_READ(reg);
fdf1250aa   Paulo Zanoni   drm/i915: split i...
197
198
199
  }
  
  static void cpt_write_infoframe(struct drm_encoder *encoder,
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
200
  				enum hdmi_infoframe_type type,
fff638676   Ville Syrjälä   drm/i915: Don't c...
201
  				const void *frame, ssize_t len)
b055c8f3e   Jesse Barnes   drm/i915/hdmi: se...
202
  {
fff638676   Ville Syrjälä   drm/i915: Don't c...
203
  	const uint32_t *data = frame;
b055c8f3e   Jesse Barnes   drm/i915/hdmi: se...
204
205
  	struct drm_device *dev = encoder->dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
ed517fbbb   Paulo Zanoni   drm/i915: small h...
206
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
207
  	int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
22509ec86   Paulo Zanoni   drm/i915: change ...
208
  	u32 val = I915_READ(reg);
b055c8f3e   Jesse Barnes   drm/i915/hdmi: se...
209

822974aea   Paulo Zanoni   drm/i915: enable ...
210
211
  	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled
  ");
64a8fc014   Jesse Barnes   drm/i915: fix ILK...
212
  	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
213
  	val |= g4x_infoframe_index(type);
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
214

ecb978515   Paulo Zanoni   drm/i915: disable...
215
216
  	/* The DIP control register spec says that we need to update the AVI
  	 * infoframe without clearing its enable bit */
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
217
218
  	if (type != HDMI_INFOFRAME_TYPE_AVI)
  		val &= ~g4x_infoframe_enable(type);
ecb978515   Paulo Zanoni   drm/i915: disable...
219

22509ec86   Paulo Zanoni   drm/i915: change ...
220
  	I915_WRITE(reg, val);
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
221

9d9740f09   Paulo Zanoni   drm/i915: add som...
222
  	mmiowb();
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
223
  	for (i = 0; i < len; i += 4) {
b055c8f3e   Jesse Barnes   drm/i915/hdmi: se...
224
225
226
  		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
  		data++;
  	}
adf00b26d   Paulo Zanoni   drm/i915: make su...
227
228
229
  	/* Write every possible data byte to force correct ECC calculation. */
  	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
  		I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
9d9740f09   Paulo Zanoni   drm/i915: add som...
230
  	mmiowb();
b055c8f3e   Jesse Barnes   drm/i915/hdmi: se...
231

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
232
  	val |= g4x_infoframe_enable(type);
60c5ea2dd   Paulo Zanoni   drm/i915: mask th...
233
  	val &= ~VIDEO_DIP_FREQ_MASK;
4b24c9331   Daniel Vetter   drm/i915: replace...
234
  	val |= VIDEO_DIP_FREQ_VSYNC;
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
235

22509ec86   Paulo Zanoni   drm/i915: change ...
236
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
237
  	POSTING_READ(reg);
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
238
  }
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
239
240
  
  static void vlv_write_infoframe(struct drm_encoder *encoder,
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
241
  				enum hdmi_infoframe_type type,
fff638676   Ville Syrjälä   drm/i915: Don't c...
242
  				const void *frame, ssize_t len)
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
243
  {
fff638676   Ville Syrjälä   drm/i915: Don't c...
244
  	const uint32_t *data = frame;
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
245
246
  	struct drm_device *dev = encoder->dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
ed517fbbb   Paulo Zanoni   drm/i915: small h...
247
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
248
  	int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
22509ec86   Paulo Zanoni   drm/i915: change ...
249
  	u32 val = I915_READ(reg);
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
250

822974aea   Paulo Zanoni   drm/i915: enable ...
251
252
  	WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled
  ");
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
253
  	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
254
  	val |= g4x_infoframe_index(type);
22509ec86   Paulo Zanoni   drm/i915: change ...
255

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
256
  	val &= ~g4x_infoframe_enable(type);
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
257

22509ec86   Paulo Zanoni   drm/i915: change ...
258
  	I915_WRITE(reg, val);
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
259

9d9740f09   Paulo Zanoni   drm/i915: add som...
260
  	mmiowb();
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
261
262
263
264
  	for (i = 0; i < len; i += 4) {
  		I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
  		data++;
  	}
adf00b26d   Paulo Zanoni   drm/i915: make su...
265
266
267
  	/* Write every possible data byte to force correct ECC calculation. */
  	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
  		I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0);
9d9740f09   Paulo Zanoni   drm/i915: add som...
268
  	mmiowb();
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
269

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
270
  	val |= g4x_infoframe_enable(type);
60c5ea2dd   Paulo Zanoni   drm/i915: mask th...
271
  	val &= ~VIDEO_DIP_FREQ_MASK;
4b24c9331   Daniel Vetter   drm/i915: replace...
272
  	val |= VIDEO_DIP_FREQ_VSYNC;
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
273

22509ec86   Paulo Zanoni   drm/i915: change ...
274
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
275
  	POSTING_READ(reg);
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
276
  }
8c5f5f7c4   Eugeni Dodonov   drm/i915: add new...
277
  static void hsw_write_infoframe(struct drm_encoder *encoder,
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
278
  				enum hdmi_infoframe_type type,
fff638676   Ville Syrjälä   drm/i915: Don't c...
279
  				const void *frame, ssize_t len)
8c5f5f7c4   Eugeni Dodonov   drm/i915: add new...
280
  {
fff638676   Ville Syrjälä   drm/i915: Don't c...
281
  	const uint32_t *data = frame;
2da8af540   Paulo Zanoni   drm/i915: impleme...
282
283
284
  	struct drm_device *dev = encoder->dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
3b117c8f2   Daniel Vetter   drm/i915: move cp...
285
  	u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder);
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
286
287
  	u32 data_reg;
  	int i;
2da8af540   Paulo Zanoni   drm/i915: impleme...
288
  	u32 val = I915_READ(ctl_reg);
8c5f5f7c4   Eugeni Dodonov   drm/i915: add new...
289

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
290
  	data_reg = hsw_infoframe_data_reg(type,
a57c774ab   Antti Koskipaa   drm/i915: Reorgan...
291
292
  					  intel_crtc->config.cpu_transcoder,
  					  dev_priv);
2da8af540   Paulo Zanoni   drm/i915: impleme...
293
294
  	if (data_reg == 0)
  		return;
178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
295
  	val &= ~hsw_infoframe_enable(type);
2da8af540   Paulo Zanoni   drm/i915: impleme...
296
  	I915_WRITE(ctl_reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
297
  	mmiowb();
2da8af540   Paulo Zanoni   drm/i915: impleme...
298
299
300
301
  	for (i = 0; i < len; i += 4) {
  		I915_WRITE(data_reg + i, *data);
  		data++;
  	}
adf00b26d   Paulo Zanoni   drm/i915: make su...
302
303
304
  	/* Write every possible data byte to force correct ECC calculation. */
  	for (; i < VIDEO_DIP_DATA_SIZE; i += 4)
  		I915_WRITE(data_reg + i, 0);
9d9740f09   Paulo Zanoni   drm/i915: add som...
305
  	mmiowb();
8c5f5f7c4   Eugeni Dodonov   drm/i915: add new...
306

178f736ab   Damien Lespiau   drm/i915/hdmi: Ch...
307
  	val |= hsw_infoframe_enable(type);
2da8af540   Paulo Zanoni   drm/i915: impleme...
308
  	I915_WRITE(ctl_reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
309
  	POSTING_READ(ctl_reg);
8c5f5f7c4   Eugeni Dodonov   drm/i915: add new...
310
  }
5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  /*
   * The data we write to the DIP data buffer registers is 1 byte bigger than the
   * HDMI infoframe size because of an ECC/reserved byte at position 3 (starting
   * at 0). It's also a byte used by DisplayPort so the same DIP registers can be
   * used for both technologies.
   *
   * DW0: Reserved/ECC/DP | HB2 | HB1 | HB0
   * DW1:       DB3       | DB2 | DB1 | DB0
   * DW2:       DB7       | DB6 | DB5 | DB4
   * DW3: ...
   *
   * (HB is Header Byte, DB is Data Byte)
   *
   * The hdmi pack() functions don't know about that hardware specific hole so we
   * trick them by giving an offset into the buffer and moving back the header
   * bytes by one.
   */
9198ee5b9   Damien Lespiau   drm/i915/hmdi: Re...
328
329
  static void intel_write_infoframe(struct drm_encoder *encoder,
  				  union hdmi_infoframe *frame)
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
330
331
  {
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
332
333
  	uint8_t buffer[VIDEO_DIP_DATA_SIZE];
  	ssize_t len;
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
334

5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
335
336
337
338
339
340
341
342
343
344
345
  	/* see comment above for the reason for this offset */
  	len = hdmi_infoframe_pack(frame, buffer + 1, sizeof(buffer) - 1);
  	if (len < 0)
  		return;
  
  	/* Insert the 'hole' (see big comment above) at position 3 */
  	buffer[0] = buffer[1];
  	buffer[1] = buffer[2];
  	buffer[2] = buffer[3];
  	buffer[3] = 0;
  	len++;
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
346

5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
347
  	intel_hdmi->write_infoframe(encoder, frame->any.type, buffer, len);
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
348
  }
687f4d06d   Paulo Zanoni   drm/i915: add set...
349
  static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
c846b6194   Paulo Zanoni   drm/i915: make DB...
350
  					 struct drm_display_mode *adjusted_mode)
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
351
  {
abedc077b   Ville Syrjälä   drm/i915: Provide...
352
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
50f3b016b   Daniel Vetter   drm/i915: add pip...
353
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
354
355
  	union hdmi_infoframe frame;
  	int ret;
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
356

5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
357
358
359
360
361
362
363
  	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
  						       adjusted_mode);
  	if (ret < 0) {
  		DRM_ERROR("couldn't fill AVI infoframe
  ");
  		return;
  	}
c846b6194   Paulo Zanoni   drm/i915: make DB...
364

abedc077b   Ville Syrjälä   drm/i915: Provide...
365
  	if (intel_hdmi->rgb_quant_range_selectable) {
50f3b016b   Daniel Vetter   drm/i915: add pip...
366
  		if (intel_crtc->config.limited_color_range)
5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
367
368
  			frame.avi.quantization_range =
  				HDMI_QUANTIZATION_RANGE_LIMITED;
abedc077b   Ville Syrjälä   drm/i915: Provide...
369
  		else
5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
370
371
  			frame.avi.quantization_range =
  				HDMI_QUANTIZATION_RANGE_FULL;
abedc077b   Ville Syrjälä   drm/i915: Provide...
372
  	}
9198ee5b9   Damien Lespiau   drm/i915/hmdi: Re...
373
  	intel_write_infoframe(encoder, &frame);
b055c8f3e   Jesse Barnes   drm/i915/hdmi: se...
374
  }
687f4d06d   Paulo Zanoni   drm/i915: add set...
375
  static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
c0864cb39   Jesse Barnes   drm/i915/hdmi: HD...
376
  {
5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
377
378
379
380
381
382
383
384
385
  	union hdmi_infoframe frame;
  	int ret;
  
  	ret = hdmi_spd_infoframe_init(&frame.spd, "Intel", "Integrated gfx");
  	if (ret < 0) {
  		DRM_ERROR("couldn't fill SPD infoframe
  ");
  		return;
  	}
c0864cb39   Jesse Barnes   drm/i915/hdmi: HD...
386

5adaea799   Damien Lespiau   drm/i915/hdmi: Po...
387
  	frame.spd.sdi = HDMI_SPD_SDI_PC;
c0864cb39   Jesse Barnes   drm/i915/hdmi: HD...
388

9198ee5b9   Damien Lespiau   drm/i915/hmdi: Re...
389
  	intel_write_infoframe(encoder, &frame);
c0864cb39   Jesse Barnes   drm/i915/hdmi: HD...
390
  }
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  static void
  intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder,
  			      struct drm_display_mode *adjusted_mode)
  {
  	union hdmi_infoframe frame;
  	int ret;
  
  	ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
  							  adjusted_mode);
  	if (ret < 0)
  		return;
  
  	intel_write_infoframe(encoder, &frame);
  }
687f4d06d   Paulo Zanoni   drm/i915: add set...
405
406
407
  static void g4x_set_infoframes(struct drm_encoder *encoder,
  			       struct drm_display_mode *adjusted_mode)
  {
0c14c7f95   Paulo Zanoni   drm/i915: properl...
408
  	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
69fde0a61   Ville Syrjälä   drm/i915: Convert...
409
410
  	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
  	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
0c14c7f95   Paulo Zanoni   drm/i915: properl...
411
412
  	u32 reg = VIDEO_DIP_CTL;
  	u32 val = I915_READ(reg);
822cdc529   Ville Syrjälä   drm/i915: Convert...
413
  	u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
414

afba01889   Daniel Vetter   drm/i915: ensure ...
415
  	assert_hdmi_port_disabled(intel_hdmi);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
  	/* If the registers were not initialized yet, they might be zeroes,
  	 * which means we're selecting the AVI DIP and we're setting its
  	 * frequency to once. This seems to really confuse the HW and make
  	 * things stop working (the register spec says the AVI always needs to
  	 * be sent every VSync). So here we avoid writing to the register more
  	 * than we need and also explicitly select the AVI DIP and explicitly
  	 * set its frequency to every VSync. Avoiding to write it twice seems to
  	 * be enough to solve the problem, but being defensive shouldn't hurt us
  	 * either. */
  	val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
  
  	if (!intel_hdmi->has_hdmi_sink) {
  		if (!(val & VIDEO_DIP_ENABLE))
  			return;
  		val &= ~VIDEO_DIP_ENABLE;
  		I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
432
  		POSTING_READ(reg);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
433
434
  		return;
  	}
72b78c9d1   Paulo Zanoni   drm/i915: disable...
435
436
437
438
  	if (port != (val & VIDEO_DIP_PORT_MASK)) {
  		if (val & VIDEO_DIP_ENABLE) {
  			val &= ~VIDEO_DIP_ENABLE;
  			I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
439
  			POSTING_READ(reg);
72b78c9d1   Paulo Zanoni   drm/i915: disable...
440
441
442
443
  		}
  		val &= ~VIDEO_DIP_PORT_MASK;
  		val |= port;
  	}
822974aea   Paulo Zanoni   drm/i915: enable ...
444
  	val |= VIDEO_DIP_ENABLE;
0dd87d208   Paulo Zanoni   drm/i915: explici...
445
  	val &= ~VIDEO_DIP_ENABLE_VENDOR;
822974aea   Paulo Zanoni   drm/i915: enable ...
446

f278d9721   Paulo Zanoni   drm/i915: only se...
447
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
448
  	POSTING_READ(reg);
f278d9721   Paulo Zanoni   drm/i915: only se...
449

687f4d06d   Paulo Zanoni   drm/i915: add set...
450
451
  	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
  	intel_hdmi_set_spd_infoframe(encoder);
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
452
  	intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
687f4d06d   Paulo Zanoni   drm/i915: add set...
453
454
455
456
457
  }
  
  static void ibx_set_infoframes(struct drm_encoder *encoder,
  			       struct drm_display_mode *adjusted_mode)
  {
0c14c7f95   Paulo Zanoni   drm/i915: properl...
458
459
  	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
69fde0a61   Ville Syrjälä   drm/i915: Convert...
460
461
  	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
  	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
0c14c7f95   Paulo Zanoni   drm/i915: properl...
462
463
  	u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
  	u32 val = I915_READ(reg);
822cdc529   Ville Syrjälä   drm/i915: Convert...
464
  	u32 port = VIDEO_DIP_PORT(intel_dig_port->port);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
465

afba01889   Daniel Vetter   drm/i915: ensure ...
466
  	assert_hdmi_port_disabled(intel_hdmi);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
467
468
469
470
471
472
473
474
  	/* See the big comment in g4x_set_infoframes() */
  	val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
  
  	if (!intel_hdmi->has_hdmi_sink) {
  		if (!(val & VIDEO_DIP_ENABLE))
  			return;
  		val &= ~VIDEO_DIP_ENABLE;
  		I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
475
  		POSTING_READ(reg);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
476
477
  		return;
  	}
72b78c9d1   Paulo Zanoni   drm/i915: disable...
478
479
480
481
  	if (port != (val & VIDEO_DIP_PORT_MASK)) {
  		if (val & VIDEO_DIP_ENABLE) {
  			val &= ~VIDEO_DIP_ENABLE;
  			I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
482
  			POSTING_READ(reg);
72b78c9d1   Paulo Zanoni   drm/i915: disable...
483
484
485
486
  		}
  		val &= ~VIDEO_DIP_PORT_MASK;
  		val |= port;
  	}
822974aea   Paulo Zanoni   drm/i915: enable ...
487
  	val |= VIDEO_DIP_ENABLE;
0dd87d208   Paulo Zanoni   drm/i915: explici...
488
489
  	val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
  		 VIDEO_DIP_ENABLE_GCP);
822974aea   Paulo Zanoni   drm/i915: enable ...
490

f278d9721   Paulo Zanoni   drm/i915: only se...
491
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
492
  	POSTING_READ(reg);
f278d9721   Paulo Zanoni   drm/i915: only se...
493

687f4d06d   Paulo Zanoni   drm/i915: add set...
494
495
  	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
  	intel_hdmi_set_spd_infoframe(encoder);
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
496
  	intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
687f4d06d   Paulo Zanoni   drm/i915: add set...
497
498
499
500
501
  }
  
  static void cpt_set_infoframes(struct drm_encoder *encoder,
  			       struct drm_display_mode *adjusted_mode)
  {
0c14c7f95   Paulo Zanoni   drm/i915: properl...
502
503
504
505
506
  	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
  	u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
  	u32 val = I915_READ(reg);
afba01889   Daniel Vetter   drm/i915: ensure ...
507
  	assert_hdmi_port_disabled(intel_hdmi);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
508
509
510
511
512
513
514
515
  	/* See the big comment in g4x_set_infoframes() */
  	val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
  
  	if (!intel_hdmi->has_hdmi_sink) {
  		if (!(val & VIDEO_DIP_ENABLE))
  			return;
  		val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI);
  		I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
516
  		POSTING_READ(reg);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
517
518
  		return;
  	}
822974aea   Paulo Zanoni   drm/i915: enable ...
519
520
  	/* Set both together, unset both together: see the spec. */
  	val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI;
0dd87d208   Paulo Zanoni   drm/i915: explici...
521
522
  	val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
  		 VIDEO_DIP_ENABLE_GCP);
822974aea   Paulo Zanoni   drm/i915: enable ...
523
524
  
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
525
  	POSTING_READ(reg);
822974aea   Paulo Zanoni   drm/i915: enable ...
526

687f4d06d   Paulo Zanoni   drm/i915: add set...
527
528
  	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
  	intel_hdmi_set_spd_infoframe(encoder);
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
529
  	intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
687f4d06d   Paulo Zanoni   drm/i915: add set...
530
531
532
533
534
  }
  
  static void vlv_set_infoframes(struct drm_encoder *encoder,
  			       struct drm_display_mode *adjusted_mode)
  {
0c14c7f95   Paulo Zanoni   drm/i915: properl...
535
536
537
538
539
  	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
  	u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe);
  	u32 val = I915_READ(reg);
afba01889   Daniel Vetter   drm/i915: ensure ...
540
  	assert_hdmi_port_disabled(intel_hdmi);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
541
542
543
544
545
546
547
548
  	/* See the big comment in g4x_set_infoframes() */
  	val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC;
  
  	if (!intel_hdmi->has_hdmi_sink) {
  		if (!(val & VIDEO_DIP_ENABLE))
  			return;
  		val &= ~VIDEO_DIP_ENABLE;
  		I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
549
  		POSTING_READ(reg);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
550
551
  		return;
  	}
822974aea   Paulo Zanoni   drm/i915: enable ...
552
  	val |= VIDEO_DIP_ENABLE;
0dd87d208   Paulo Zanoni   drm/i915: explici...
553
554
  	val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT |
  		 VIDEO_DIP_ENABLE_GCP);
822974aea   Paulo Zanoni   drm/i915: enable ...
555
556
  
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
557
  	POSTING_READ(reg);
822974aea   Paulo Zanoni   drm/i915: enable ...
558

687f4d06d   Paulo Zanoni   drm/i915: add set...
559
560
  	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
  	intel_hdmi_set_spd_infoframe(encoder);
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
561
  	intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
687f4d06d   Paulo Zanoni   drm/i915: add set...
562
563
564
565
566
  }
  
  static void hsw_set_infoframes(struct drm_encoder *encoder,
  			       struct drm_display_mode *adjusted_mode)
  {
0c14c7f95   Paulo Zanoni   drm/i915: properl...
567
568
569
  	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
3b117c8f2   Daniel Vetter   drm/i915: move cp...
570
  	u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder);
0dd87d208   Paulo Zanoni   drm/i915: explici...
571
  	u32 val = I915_READ(reg);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
572

afba01889   Daniel Vetter   drm/i915: ensure ...
573
  	assert_hdmi_port_disabled(intel_hdmi);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
574
575
  	if (!intel_hdmi->has_hdmi_sink) {
  		I915_WRITE(reg, 0);
9d9740f09   Paulo Zanoni   drm/i915: add som...
576
  		POSTING_READ(reg);
0c14c7f95   Paulo Zanoni   drm/i915: properl...
577
578
  		return;
  	}
0dd87d208   Paulo Zanoni   drm/i915: explici...
579
580
581
582
  	val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW |
  		 VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW);
  
  	I915_WRITE(reg, val);
9d9740f09   Paulo Zanoni   drm/i915: add som...
583
  	POSTING_READ(reg);
0dd87d208   Paulo Zanoni   drm/i915: explici...
584

687f4d06d   Paulo Zanoni   drm/i915: add set...
585
586
  	intel_hdmi_set_avi_infoframe(encoder, adjusted_mode);
  	intel_hdmi_set_spd_infoframe(encoder);
c8bb75aff   Lespiau, Damien   drm/i915/hdmi: Wr...
587
  	intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
687f4d06d   Paulo Zanoni   drm/i915: add set...
588
  }
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
589
  static void intel_hdmi_mode_set(struct intel_encoder *encoder)
7d57382e6   Eric Anholt   drm/i915: Add sup...
590
  {
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
591
  	struct drm_device *dev = encoder->base.dev;
7d57382e6   Eric Anholt   drm/i915: Add sup...
592
  	struct drm_i915_private *dev_priv = dev->dev_private;
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
593
594
595
  	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
  	struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode;
b242b7f74   Paulo Zanoni   drm/i915: rename ...
596
  	u32 hdmi_val;
7d57382e6   Eric Anholt   drm/i915: Add sup...
597

b242b7f74   Paulo Zanoni   drm/i915: rename ...
598
  	hdmi_val = SDVO_ENCODING_HDMI;
2af2c4909   Ville Syrjälä   Revert "drm/i915:...
599
  	if (!HAS_PCH_SPLIT(dev))
b242b7f74   Paulo Zanoni   drm/i915: rename ...
600
  		hdmi_val |= intel_hdmi->color_range;
b599c0bca   Adam Jackson   drm/i915/hdmi: Se...
601
  	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
b242b7f74   Paulo Zanoni   drm/i915: rename ...
602
  		hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
b599c0bca   Adam Jackson   drm/i915/hdmi: Se...
603
  	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
b242b7f74   Paulo Zanoni   drm/i915: rename ...
604
  		hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH;
7d57382e6   Eric Anholt   drm/i915: Add sup...
605

c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
606
  	if (crtc->config.pipe_bpp > 24)
4f3a8bc7b   Paulo Zanoni   drm/i915: rename ...
607
  		hdmi_val |= HDMI_COLOR_FORMAT_12bpc;
020f6704b   Jesse Barnes   drm/i915: use pip...
608
  	else
4f3a8bc7b   Paulo Zanoni   drm/i915: rename ...
609
  		hdmi_val |= SDVO_COLOR_FORMAT_8bpc;
020f6704b   Jesse Barnes   drm/i915: use pip...
610

2e3d6006a   Zhenyu Wang   drm/i915: Enable ...
611
612
  	/* Required on CPT */
  	if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
dc0fa7181   Paulo Zanoni   drm/i915: remove ...
613
  		hdmi_val |= HDMI_MODE_SELECT_HDMI;
2e3d6006a   Zhenyu Wang   drm/i915: Enable ...
614

3c17fe4b8   David Härdeman   i915: enable AVI ...
615
  	if (intel_hdmi->has_audio) {
e0dac65ed   Wu Fengguang   drm/i915: pass EL...
616
617
  		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c
  ",
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
618
  				 pipe_name(crtc->pipe));
b242b7f74   Paulo Zanoni   drm/i915: rename ...
619
  		hdmi_val |= SDVO_AUDIO_ENABLE;
dc0fa7181   Paulo Zanoni   drm/i915: remove ...
620
  		hdmi_val |= HDMI_MODE_SELECT_HDMI;
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
621
  		intel_write_eld(&encoder->base, adjusted_mode);
3c17fe4b8   David Härdeman   i915: enable AVI ...
622
  	}
7d57382e6   Eric Anholt   drm/i915: Add sup...
623

75770564c   Jesse Barnes   drm/i915: use tra...
624
  	if (HAS_PCH_CPT(dev))
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
625
  		hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
dc0fa7181   Paulo Zanoni   drm/i915: remove ...
626
  	else
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
627
  		hdmi_val |= SDVO_PIPE_SEL(crtc->pipe);
7d57382e6   Eric Anholt   drm/i915: Add sup...
628

b242b7f74   Paulo Zanoni   drm/i915: rename ...
629
630
  	I915_WRITE(intel_hdmi->hdmi_reg, hdmi_val);
  	POSTING_READ(intel_hdmi->hdmi_reg);
3c17fe4b8   David Härdeman   i915: enable AVI ...
631

c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
632
  	intel_hdmi->set_infoframes(&encoder->base, adjusted_mode);
7d57382e6   Eric Anholt   drm/i915: Add sup...
633
  }
85234cdc2   Daniel Vetter   drm/i915/hdmi: im...
634
635
  static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
  				    enum pipe *pipe)
7d57382e6   Eric Anholt   drm/i915: Add sup...
636
  {
85234cdc2   Daniel Vetter   drm/i915/hdmi: im...
637
  	struct drm_device *dev = encoder->base.dev;
7d57382e6   Eric Anholt   drm/i915: Add sup...
638
  	struct drm_i915_private *dev_priv = dev->dev_private;
85234cdc2   Daniel Vetter   drm/i915/hdmi: im...
639
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
6d129beac   Imre Deak   drm/i915: check p...
640
  	enum intel_display_power_domain power_domain;
85234cdc2   Daniel Vetter   drm/i915/hdmi: im...
641
  	u32 tmp;
6d129beac   Imre Deak   drm/i915: check p...
642
643
644
  	power_domain = intel_display_port_power_domain(encoder);
  	if (!intel_display_power_enabled(dev_priv, power_domain))
  		return false;
b242b7f74   Paulo Zanoni   drm/i915: rename ...
645
  	tmp = I915_READ(intel_hdmi->hdmi_reg);
85234cdc2   Daniel Vetter   drm/i915/hdmi: im...
646
647
648
649
650
651
652
653
654
655
656
  
  	if (!(tmp & SDVO_ENABLE))
  		return false;
  
  	if (HAS_PCH_CPT(dev))
  		*pipe = PORT_TO_PIPE_CPT(tmp);
  	else
  		*pipe = PORT_TO_PIPE(tmp);
  
  	return true;
  }
045ac3b56   Jesse Barnes   drm/i915: add enc...
657
658
659
660
661
662
  static void intel_hdmi_get_config(struct intel_encoder *encoder,
  				  struct intel_crtc_config *pipe_config)
  {
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
  	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
  	u32 tmp, flags = 0;
18442d087   Ville Syrjälä   drm/i915: Fix por...
663
  	int dotclock;
045ac3b56   Jesse Barnes   drm/i915: add enc...
664
665
666
667
668
669
670
671
672
673
674
675
676
677
  
  	tmp = I915_READ(intel_hdmi->hdmi_reg);
  
  	if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
  		flags |= DRM_MODE_FLAG_PHSYNC;
  	else
  		flags |= DRM_MODE_FLAG_NHSYNC;
  
  	if (tmp & SDVO_VSYNC_ACTIVE_HIGH)
  		flags |= DRM_MODE_FLAG_PVSYNC;
  	else
  		flags |= DRM_MODE_FLAG_NVSYNC;
  
  	pipe_config->adjusted_mode.flags |= flags;
18442d087   Ville Syrjälä   drm/i915: Fix por...
678
679
680
681
682
683
684
685
  
  	if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc)
  		dotclock = pipe_config->port_clock * 2 / 3;
  	else
  		dotclock = pipe_config->port_clock;
  
  	if (HAS_PCH_SPLIT(dev_priv->dev))
  		ironlake_check_encoder_dotclock(pipe_config, dotclock);
241bfc389   Damien Lespiau   drm/i915: Use crt...
686
  	pipe_config->adjusted_mode.crtc_clock = dotclock;
045ac3b56   Jesse Barnes   drm/i915: add enc...
687
  }
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
688
  static void intel_enable_hdmi(struct intel_encoder *encoder)
7d57382e6   Eric Anholt   drm/i915: Add sup...
689
  {
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
690
  	struct drm_device *dev = encoder->base.dev;
7d57382e6   Eric Anholt   drm/i915: Add sup...
691
  	struct drm_i915_private *dev_priv = dev->dev_private;
dc0fa7181   Paulo Zanoni   drm/i915: remove ...
692
  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
693
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
7d57382e6   Eric Anholt   drm/i915: Add sup...
694
  	u32 temp;
2deed7611   Wu Fengguang   drm/i915: HDMI ho...
695
696
697
698
  	u32 enable_bits = SDVO_ENABLE;
  
  	if (intel_hdmi->has_audio)
  		enable_bits |= SDVO_AUDIO_ENABLE;
7d57382e6   Eric Anholt   drm/i915: Add sup...
699

b242b7f74   Paulo Zanoni   drm/i915: rename ...
700
  	temp = I915_READ(intel_hdmi->hdmi_reg);
d8a2d0e00   Zhenyu Wang   drm/i915: HDMI ha...
701

7a87c2897   Daniel Vetter   drm/i915: impleme...
702
  	/* HW workaround for IBX, we need to move the port to transcoder A
dc0fa7181   Paulo Zanoni   drm/i915: remove ...
703
704
705
  	 * before disabling it, so restore the transcoder select bit here. */
  	if (HAS_PCH_IBX(dev))
  		enable_bits |= SDVO_PIPE_SEL(intel_crtc->pipe);
7a87c2897   Daniel Vetter   drm/i915: impleme...
706

d8a2d0e00   Zhenyu Wang   drm/i915: HDMI ha...
707
708
709
  	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
  	 * we do this anyway which shows more stable in testing.
  	 */
c619eed4b   Eric Anholt   drm/i915: More s/...
710
  	if (HAS_PCH_SPLIT(dev)) {
b242b7f74   Paulo Zanoni   drm/i915: rename ...
711
712
  		I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE);
  		POSTING_READ(intel_hdmi->hdmi_reg);
d8a2d0e00   Zhenyu Wang   drm/i915: HDMI ha...
713
  	}
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
714
  	temp |= enable_bits;
b242b7f74   Paulo Zanoni   drm/i915: rename ...
715
716
  	I915_WRITE(intel_hdmi->hdmi_reg, temp);
  	POSTING_READ(intel_hdmi->hdmi_reg);
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
717
718
719
720
721
  
  	/* HW workaround, need to write this twice for issue that may result
  	 * in first write getting masked.
  	 */
  	if (HAS_PCH_SPLIT(dev)) {
b242b7f74   Paulo Zanoni   drm/i915: rename ...
722
723
  		I915_WRITE(intel_hdmi->hdmi_reg, temp);
  		POSTING_READ(intel_hdmi->hdmi_reg);
7d57382e6   Eric Anholt   drm/i915: Add sup...
724
  	}
b76cf76bf   Jani Nikula   drm/i915: rearran...
725
  }
89b667f86   Jesse Barnes   drm/i915: update ...
726

b76cf76bf   Jani Nikula   drm/i915: rearran...
727
728
  static void vlv_enable_hdmi(struct intel_encoder *encoder)
  {
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
729
730
731
732
733
734
735
736
  }
  
  static void intel_disable_hdmi(struct intel_encoder *encoder)
  {
  	struct drm_device *dev = encoder->base.dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
  	u32 temp;
3cce574f0   Wang Xingchao   drm/i915: HDMI - ...
737
  	u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE;
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
738

b242b7f74   Paulo Zanoni   drm/i915: rename ...
739
  	temp = I915_READ(intel_hdmi->hdmi_reg);
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
740
741
742
743
744
745
746
747
748
  
  	/* HW workaround for IBX, we need to move the port to transcoder A
  	 * before disabling it. */
  	if (HAS_PCH_IBX(dev)) {
  		struct drm_crtc *crtc = encoder->base.crtc;
  		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
  
  		if (temp & SDVO_PIPE_B_SELECT) {
  			temp &= ~SDVO_PIPE_B_SELECT;
b242b7f74   Paulo Zanoni   drm/i915: rename ...
749
750
  			I915_WRITE(intel_hdmi->hdmi_reg, temp);
  			POSTING_READ(intel_hdmi->hdmi_reg);
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
751
752
  
  			/* Again we need to write this twice. */
b242b7f74   Paulo Zanoni   drm/i915: rename ...
753
754
  			I915_WRITE(intel_hdmi->hdmi_reg, temp);
  			POSTING_READ(intel_hdmi->hdmi_reg);
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
755
756
757
758
759
760
761
762
  
  			/* Transcoder selection bits only update
  			 * effectively on vblank. */
  			if (crtc)
  				intel_wait_for_vblank(dev, pipe);
  			else
  				msleep(50);
  		}
7d57382e6   Eric Anholt   drm/i915: Add sup...
763
  	}
d8a2d0e00   Zhenyu Wang   drm/i915: HDMI ha...
764

5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
765
766
767
768
  	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
  	 * we do this anyway which shows more stable in testing.
  	 */
  	if (HAS_PCH_SPLIT(dev)) {
b242b7f74   Paulo Zanoni   drm/i915: rename ...
769
770
  		I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE);
  		POSTING_READ(intel_hdmi->hdmi_reg);
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
771
772
773
  	}
  
  	temp &= ~enable_bits;
d8a2d0e00   Zhenyu Wang   drm/i915: HDMI ha...
774

b242b7f74   Paulo Zanoni   drm/i915: rename ...
775
776
  	I915_WRITE(intel_hdmi->hdmi_reg, temp);
  	POSTING_READ(intel_hdmi->hdmi_reg);
d8a2d0e00   Zhenyu Wang   drm/i915: HDMI ha...
777
778
779
780
  
  	/* HW workaround, need to write this twice for issue that may result
  	 * in first write getting masked.
  	 */
c619eed4b   Eric Anholt   drm/i915: More s/...
781
  	if (HAS_PCH_SPLIT(dev)) {
b242b7f74   Paulo Zanoni   drm/i915: rename ...
782
783
  		I915_WRITE(intel_hdmi->hdmi_reg, temp);
  		POSTING_READ(intel_hdmi->hdmi_reg);
d8a2d0e00   Zhenyu Wang   drm/i915: HDMI ha...
784
  	}
7d57382e6   Eric Anholt   drm/i915: Add sup...
785
  }
40478455f   Ville Syrjälä   drm/i915: Allow u...
786
  static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit)
7d148ef51   Daniel Vetter   drm/i915: fix hdm...
787
788
  {
  	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
40478455f   Ville Syrjälä   drm/i915: Allow u...
789
  	if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev))
7d148ef51   Daniel Vetter   drm/i915: fix hdm...
790
  		return 165000;
e3c335786   Damien Lespiau   drm/i915/bdw: Bro...
791
  	else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8)
7d148ef51   Daniel Vetter   drm/i915: fix hdm...
792
793
794
795
  		return 300000;
  	else
  		return 225000;
  }
c19de8eb6   Damien Lespiau   drm/i915: Return ...
796
797
798
  static enum drm_mode_status
  intel_hdmi_mode_valid(struct drm_connector *connector,
  		      struct drm_display_mode *mode)
7d57382e6   Eric Anholt   drm/i915: Add sup...
799
  {
40478455f   Ville Syrjälä   drm/i915: Allow u...
800
801
  	if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector),
  					       true))
7d57382e6   Eric Anholt   drm/i915: Add sup...
802
803
  		return MODE_CLOCK_HIGH;
  	if (mode->clock < 20000)
5cbba41d2   Nicolas Kaiser   drm: i915: correc...
804
  		return MODE_CLOCK_LOW;
7d57382e6   Eric Anholt   drm/i915: Add sup...
805
806
807
808
809
810
  
  	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
  		return MODE_NO_DBLESCAN;
  
  	return MODE_OK;
  }
718006329   Ville Syrjälä   drm/i915: Don't u...
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
  static bool hdmi_12bpc_possible(struct intel_crtc *crtc)
  {
  	struct drm_device *dev = crtc->base.dev;
  	struct intel_encoder *encoder;
  	int count = 0, count_hdmi = 0;
  
  	if (!HAS_PCH_SPLIT(dev))
  		return false;
  
  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
  		if (encoder->new_crtc != crtc)
  			continue;
  
  		count_hdmi += encoder->type == INTEL_OUTPUT_HDMI;
  		count++;
  	}
  
  	/*
  	 * HDMI 12bpc affects the clocks, so it's only possible
  	 * when not cloning with other encoder types.
  	 */
  	return count_hdmi > 0 && count_hdmi == count;
  }
5bfe2ac00   Daniel Vetter   drm/i915: add pip...
834
835
  bool intel_hdmi_compute_config(struct intel_encoder *encoder,
  			       struct intel_crtc_config *pipe_config)
7d57382e6   Eric Anholt   drm/i915: Add sup...
836
  {
5bfe2ac00   Daniel Vetter   drm/i915: add pip...
837
838
839
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
  	struct drm_device *dev = encoder->base.dev;
  	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
241bfc389   Damien Lespiau   drm/i915: Use crt...
840
  	int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2;
40478455f   Ville Syrjälä   drm/i915: Allow u...
841
  	int portclock_limit = hdmi_portclock_limit(intel_hdmi, false);
e29c22c0c   Daniel Vetter   drm/i915: impleme...
842
  	int desired_bpp;
3685a8f38   Ville Syrjälä   drm/i915: Fix RGB...
843

55bc60db5   Ville Syrjälä   drm/i915: Add "Au...
844
845
846
  	if (intel_hdmi->color_range_auto) {
  		/* See CEA-861-E - 5.1 Default Encoding Parameters */
  		if (intel_hdmi->has_hdmi_sink &&
18316c8c3   Thierry Reding   drm: Remove dupli...
847
  		    drm_match_cea_mode(adjusted_mode) > 1)
4f3a8bc7b   Paulo Zanoni   drm/i915: rename ...
848
  			intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235;
55bc60db5   Ville Syrjälä   drm/i915: Add "Au...
849
850
851
  		else
  			intel_hdmi->color_range = 0;
  	}
3685a8f38   Ville Syrjälä   drm/i915: Fix RGB...
852
  	if (intel_hdmi->color_range)
50f3b016b   Daniel Vetter   drm/i915: add pip...
853
  		pipe_config->limited_color_range = true;
3685a8f38   Ville Syrjälä   drm/i915: Fix RGB...
854

5bfe2ac00   Daniel Vetter   drm/i915: add pip...
855
856
  	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev))
  		pipe_config->has_pch_encoder = true;
4e53c2e01   Daniel Vetter   drm/i915: precomp...
857
858
859
  	/*
  	 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
  	 * through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi
325b9d048   Daniel Vetter   drm/i915: fixup 1...
860
861
  	 * outputs. We also need to check that the higher clock still fits
  	 * within limits.
4e53c2e01   Daniel Vetter   drm/i915: precomp...
862
  	 */
6375b768a   Ville Syrjälä   drm/i915: Reject ...
863
  	if (pipe_config->pipe_bpp > 8*3 && intel_hdmi->has_hdmi_sink &&
718006329   Ville Syrjälä   drm/i915: Don't u...
864
865
  	    clock_12bpc <= portclock_limit &&
  	    hdmi_12bpc_possible(encoder->new_crtc)) {
e29c22c0c   Daniel Vetter   drm/i915: impleme...
866
867
868
  		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output
  ");
  		desired_bpp = 12*3;
325b9d048   Daniel Vetter   drm/i915: fixup 1...
869
870
  
  		/* Need to adjust the port link by 1.5x for 12bpc. */
ff9a6750a   Daniel Vetter   drm/i915: store a...
871
  		pipe_config->port_clock = clock_12bpc;
4e53c2e01   Daniel Vetter   drm/i915: precomp...
872
  	} else {
e29c22c0c   Daniel Vetter   drm/i915: impleme...
873
874
875
876
877
878
879
880
881
  		DRM_DEBUG_KMS("picking bpc to 8 for HDMI output
  ");
  		desired_bpp = 8*3;
  	}
  
  	if (!pipe_config->bw_constrained) {
  		DRM_DEBUG_KMS("forcing pipe bpc to %i for HDMI
  ", desired_bpp);
  		pipe_config->pipe_bpp = desired_bpp;
4e53c2e01   Daniel Vetter   drm/i915: precomp...
882
  	}
241bfc389   Damien Lespiau   drm/i915: Use crt...
883
  	if (adjusted_mode->crtc_clock > portclock_limit) {
325b9d048   Daniel Vetter   drm/i915: fixup 1...
884
885
886
887
  		DRM_DEBUG_KMS("too high HDMI clock, rejecting mode
  ");
  		return false;
  	}
7d57382e6   Eric Anholt   drm/i915: Add sup...
888
889
  	return true;
  }
aa93d632c   Keith Packard   drm/i915: Require...
890
  static enum drm_connector_status
930a9e283   Chris Wilson   drm: Use a nondes...
891
  intel_hdmi_detect(struct drm_connector *connector, bool force)
9dff6af86   Ma Ling   drm/i915: sync hd...
892
  {
b0ea7d37a   Damien Lespiau   drm/i915/hdmi: Re...
893
  	struct drm_device *dev = connector->dev;
df0e92488   Chris Wilson   drm/i915: Make th...
894
  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
d63885da9   Paulo Zanoni   drm/i915: reset i...
895
896
897
  	struct intel_digital_port *intel_dig_port =
  		hdmi_to_dig_port(intel_hdmi);
  	struct intel_encoder *intel_encoder = &intel_dig_port->base;
b0ea7d37a   Damien Lespiau   drm/i915/hdmi: Re...
898
  	struct drm_i915_private *dev_priv = dev->dev_private;
f899fc64c   Chris Wilson   drm/i915: use GMB...
899
  	struct edid *edid;
671dedd21   Imre Deak   drm/i915: get por...
900
  	enum intel_display_power_domain power_domain;
aa93d632c   Keith Packard   drm/i915: Require...
901
  	enum drm_connector_status status = connector_status_disconnected;
9dff6af86   Ma Ling   drm/i915: sync hd...
902

164c85984   Chris Wilson   drm/i915: Add som...
903
904
905
  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]
  ",
  		      connector->base.id, drm_get_connector_name(connector));
671dedd21   Imre Deak   drm/i915: get por...
906
907
  	power_domain = intel_display_port_power_domain(intel_encoder);
  	intel_display_power_get(dev_priv, power_domain);
ea5b213ad   Chris Wilson   drm/i915: Subclas...
908
  	intel_hdmi->has_hdmi_sink = false;
2e3d6006a   Zhenyu Wang   drm/i915: Enable ...
909
  	intel_hdmi->has_audio = false;
abedc077b   Ville Syrjälä   drm/i915: Provide...
910
  	intel_hdmi->rgb_quant_range_selectable = false;
f899fc64c   Chris Wilson   drm/i915: use GMB...
911
  	edid = drm_get_edid(connector,
3bd7d9093   Daniel Kurtz   drm/i915/intel_i2...
912
913
  			    intel_gmbus_get_adapter(dev_priv,
  						    intel_hdmi->ddc_bus));
2ded9e274   ling.ma@intel.com   drm/i915: hdmi de...
914

aa93d632c   Keith Packard   drm/i915: Require...
915
  	if (edid) {
be9f1c4f7   Eric Anholt   Merge commit 'kei...
916
  		if (edid->input & DRM_EDID_INPUT_DIGITAL) {
aa93d632c   Keith Packard   drm/i915: Require...
917
  			status = connector_status_connected;
b1d7e4b41   Wu Fengguang   drm/i915: add a "...
918
919
920
  			if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI)
  				intel_hdmi->has_hdmi_sink =
  						drm_detect_hdmi_monitor(edid);
2e3d6006a   Zhenyu Wang   drm/i915: Enable ...
921
  			intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
abedc077b   Ville Syrjälä   drm/i915: Provide...
922
923
  			intel_hdmi->rgb_quant_range_selectable =
  				drm_rgb_quant_range_selectable(edid);
aa93d632c   Keith Packard   drm/i915: Require...
924
  		}
aa93d632c   Keith Packard   drm/i915: Require...
925
  		kfree(edid);
9dff6af86   Ma Ling   drm/i915: sync hd...
926
  	}
30ad48b73   Zhenyu Wang   drm/i915: Add HDM...
927

55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
928
  	if (status == connector_status_connected) {
b1d7e4b41   Wu Fengguang   drm/i915: add a "...
929
930
931
  		if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
  			intel_hdmi->has_audio =
  				(intel_hdmi->force_audio == HDMI_AUDIO_ON);
d63885da9   Paulo Zanoni   drm/i915: reset i...
932
  		intel_encoder->type = INTEL_OUTPUT_HDMI;
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
933
  	}
671dedd21   Imre Deak   drm/i915: get por...
934
  	intel_display_power_put(dev_priv, power_domain);
2ded9e274   ling.ma@intel.com   drm/i915: hdmi de...
935
  	return status;
7d57382e6   Eric Anholt   drm/i915: Add sup...
936
937
938
939
  }
  
  static int intel_hdmi_get_modes(struct drm_connector *connector)
  {
671dedd21   Imre Deak   drm/i915: get por...
940
941
  	struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
f899fc64c   Chris Wilson   drm/i915: use GMB...
942
  	struct drm_i915_private *dev_priv = connector->dev->dev_private;
671dedd21   Imre Deak   drm/i915: get por...
943
944
  	enum intel_display_power_domain power_domain;
  	int ret;
7d57382e6   Eric Anholt   drm/i915: Add sup...
945
946
947
948
  
  	/* We should parse the EDID data and find out if it's an HDMI sink so
  	 * we can send audio to it.
  	 */
671dedd21   Imre Deak   drm/i915: get por...
949
950
951
952
  	power_domain = intel_display_port_power_domain(intel_encoder);
  	intel_display_power_get(dev_priv, power_domain);
  
  	ret = intel_ddc_get_modes(connector,
3bd7d9093   Daniel Kurtz   drm/i915/intel_i2...
953
954
  				   intel_gmbus_get_adapter(dev_priv,
  							   intel_hdmi->ddc_bus));
671dedd21   Imre Deak   drm/i915: get por...
955
956
957
958
  
  	intel_display_power_put(dev_priv, power_domain);
  
  	return ret;
7d57382e6   Eric Anholt   drm/i915: Add sup...
959
  }
1aad7ac04   Chris Wilson   drm/i915: Trigger...
960
961
962
  static bool
  intel_hdmi_detect_audio(struct drm_connector *connector)
  {
671dedd21   Imre Deak   drm/i915: get por...
963
964
  	struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
1aad7ac04   Chris Wilson   drm/i915: Trigger...
965
  	struct drm_i915_private *dev_priv = connector->dev->dev_private;
671dedd21   Imre Deak   drm/i915: get por...
966
  	enum intel_display_power_domain power_domain;
1aad7ac04   Chris Wilson   drm/i915: Trigger...
967
968
  	struct edid *edid;
  	bool has_audio = false;
671dedd21   Imre Deak   drm/i915: get por...
969
970
  	power_domain = intel_display_port_power_domain(intel_encoder);
  	intel_display_power_get(dev_priv, power_domain);
1aad7ac04   Chris Wilson   drm/i915: Trigger...
971
  	edid = drm_get_edid(connector,
3bd7d9093   Daniel Kurtz   drm/i915/intel_i2...
972
973
  			    intel_gmbus_get_adapter(dev_priv,
  						    intel_hdmi->ddc_bus));
1aad7ac04   Chris Wilson   drm/i915: Trigger...
974
975
976
  	if (edid) {
  		if (edid->input & DRM_EDID_INPUT_DIGITAL)
  			has_audio = drm_detect_monitor_audio(edid);
1aad7ac04   Chris Wilson   drm/i915: Trigger...
977
978
  		kfree(edid);
  	}
671dedd21   Imre Deak   drm/i915: get por...
979
  	intel_display_power_put(dev_priv, power_domain);
1aad7ac04   Chris Wilson   drm/i915: Trigger...
980
981
  	return has_audio;
  }
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
982
983
  static int
  intel_hdmi_set_property(struct drm_connector *connector,
ed517fbbb   Paulo Zanoni   drm/i915: small h...
984
985
  			struct drm_property *property,
  			uint64_t val)
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
986
987
  {
  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
da63a9f2e   Paulo Zanoni   drm/i915: create ...
988
989
  	struct intel_digital_port *intel_dig_port =
  		hdmi_to_dig_port(intel_hdmi);
e953fd7bb   Chris Wilson   drm/i915: Add sup...
990
  	struct drm_i915_private *dev_priv = connector->dev->dev_private;
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
991
  	int ret;
662595df9   Rob Clark   drm/i915: drm_con...
992
  	ret = drm_object_property_set_value(&connector->base, property, val);
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
993
994
  	if (ret)
  		return ret;
3f43c48d3   Chris Wilson   drm/i915: Share t...
995
  	if (property == dev_priv->force_audio_property) {
b1d7e4b41   Wu Fengguang   drm/i915: add a "...
996
  		enum hdmi_force_audio i = val;
1aad7ac04   Chris Wilson   drm/i915: Trigger...
997
998
999
  		bool has_audio;
  
  		if (i == intel_hdmi->force_audio)
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1000
  			return 0;
1aad7ac04   Chris Wilson   drm/i915: Trigger...
1001
  		intel_hdmi->force_audio = i;
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1002

b1d7e4b41   Wu Fengguang   drm/i915: add a "...
1003
  		if (i == HDMI_AUDIO_AUTO)
1aad7ac04   Chris Wilson   drm/i915: Trigger...
1004
1005
  			has_audio = intel_hdmi_detect_audio(connector);
  		else
b1d7e4b41   Wu Fengguang   drm/i915: add a "...
1006
  			has_audio = (i == HDMI_AUDIO_ON);
1aad7ac04   Chris Wilson   drm/i915: Trigger...
1007

b1d7e4b41   Wu Fengguang   drm/i915: add a "...
1008
1009
  		if (i == HDMI_AUDIO_OFF_DVI)
  			intel_hdmi->has_hdmi_sink = 0;
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1010

1aad7ac04   Chris Wilson   drm/i915: Trigger...
1011
  		intel_hdmi->has_audio = has_audio;
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1012
1013
  		goto done;
  	}
e953fd7bb   Chris Wilson   drm/i915: Add sup...
1014
  	if (property == dev_priv->broadcast_rgb_property) {
ae4edb808   Daniel Vetter   drm/i915: avoid f...
1015
1016
  		bool old_auto = intel_hdmi->color_range_auto;
  		uint32_t old_range = intel_hdmi->color_range;
55bc60db5   Ville Syrjälä   drm/i915: Add "Au...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  		switch (val) {
  		case INTEL_BROADCAST_RGB_AUTO:
  			intel_hdmi->color_range_auto = true;
  			break;
  		case INTEL_BROADCAST_RGB_FULL:
  			intel_hdmi->color_range_auto = false;
  			intel_hdmi->color_range = 0;
  			break;
  		case INTEL_BROADCAST_RGB_LIMITED:
  			intel_hdmi->color_range_auto = false;
4f3a8bc7b   Paulo Zanoni   drm/i915: rename ...
1027
  			intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235;
55bc60db5   Ville Syrjälä   drm/i915: Add "Au...
1028
1029
1030
1031
  			break;
  		default:
  			return -EINVAL;
  		}
ae4edb808   Daniel Vetter   drm/i915: avoid f...
1032
1033
1034
1035
  
  		if (old_auto == intel_hdmi->color_range_auto &&
  		    old_range == intel_hdmi->color_range)
  			return 0;
e953fd7bb   Chris Wilson   drm/i915: Add sup...
1036
1037
  		goto done;
  	}
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1038
1039
1040
  	return -EINVAL;
  
  done:
c0c36b941   Chris Wilson   drm/i915: Return ...
1041
1042
  	if (intel_dig_port->base.base.crtc)
  		intel_crtc_restore_mode(intel_dig_port->base.base.crtc);
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1043
1044
1045
  
  	return 0;
  }
9514ac6e7   Chon Ming Lee   drm/i915: Move so...
1046
  static void vlv_hdmi_pre_enable(struct intel_encoder *encoder)
89b667f86   Jesse Barnes   drm/i915: update ...
1047
1048
1049
1050
1051
1052
  {
  	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
  	struct drm_device *dev = encoder->base.dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
  	struct intel_crtc *intel_crtc =
  		to_intel_crtc(encoder->base.crtc);
e4607fcfb   Chon Ming Lee   drm/i915/vlv: Mak...
1053
  	enum dpio_channel port = vlv_dport_to_channel(dport);
89b667f86   Jesse Barnes   drm/i915: update ...
1054
1055
1056
1057
1058
  	int pipe = intel_crtc->pipe;
  	u32 val;
  
  	if (!IS_VALLEYVIEW(dev))
  		return;
89b667f86   Jesse Barnes   drm/i915: update ...
1059
  	/* Enable clock channels for this port */
0980a60fb   Chris Wilson   drm/i915: Acquire...
1060
  	mutex_lock(&dev_priv->dpio_lock);
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1061
  	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
89b667f86   Jesse Barnes   drm/i915: update ...
1062
1063
1064
1065
1066
1067
  	val = 0;
  	if (pipe)
  		val |= (1<<21);
  	else
  		val &= ~(1<<21);
  	val |= 0x001000c4;
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1068
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val);
89b667f86   Jesse Barnes   drm/i915: update ...
1069
1070
  
  	/* HDMI 1.0V-2dB */
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1071
1072
1073
1074
1075
1076
1077
1078
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), 0x2b245f5f);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), 0x5578b83a);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0c782040);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX3_DW4(port), 0x2b247878);
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
89b667f86   Jesse Barnes   drm/i915: update ...
1079
1080
  
  	/* Program lane clock */
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1081
1082
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
0980a60fb   Chris Wilson   drm/i915: Acquire...
1083
  	mutex_unlock(&dev_priv->dpio_lock);
b76cf76bf   Jani Nikula   drm/i915: rearran...
1084
1085
  
  	intel_enable_hdmi(encoder);
e4607fcfb   Chon Ming Lee   drm/i915/vlv: Mak...
1086
  	vlv_wait_port_ready(dev_priv, dport);
89b667f86   Jesse Barnes   drm/i915: update ...
1087
  }
9514ac6e7   Chon Ming Lee   drm/i915: Move so...
1088
  static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
89b667f86   Jesse Barnes   drm/i915: update ...
1089
1090
1091
1092
  {
  	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
  	struct drm_device *dev = encoder->base.dev;
  	struct drm_i915_private *dev_priv = dev->dev_private;
5e69f97fb   Chon Ming Lee   drm/i915: Add add...
1093
1094
  	struct intel_crtc *intel_crtc =
  		to_intel_crtc(encoder->base.crtc);
e4607fcfb   Chon Ming Lee   drm/i915/vlv: Mak...
1095
  	enum dpio_channel port = vlv_dport_to_channel(dport);
5e69f97fb   Chon Ming Lee   drm/i915: Add add...
1096
  	int pipe = intel_crtc->pipe;
89b667f86   Jesse Barnes   drm/i915: update ...
1097
1098
1099
  
  	if (!IS_VALLEYVIEW(dev))
  		return;
89b667f86   Jesse Barnes   drm/i915: update ...
1100
  	/* Program Tx lane resets to default */
0980a60fb   Chris Wilson   drm/i915: Acquire...
1101
  	mutex_lock(&dev_priv->dpio_lock);
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1102
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
89b667f86   Jesse Barnes   drm/i915: update ...
1103
1104
  			 DPIO_PCS_TX_LANE2_RESET |
  			 DPIO_PCS_TX_LANE1_RESET);
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1105
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port),
89b667f86   Jesse Barnes   drm/i915: update ...
1106
1107
1108
1109
1110
1111
  			 DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
  			 DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
  			 (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
  			 DPIO_PCS_CLK_SOFT_RESET);
  
  	/* Fix up inter-pair skew failure */
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1112
1113
1114
1115
1116
1117
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
  
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000);
  	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
0980a60fb   Chris Wilson   drm/i915: Acquire...
1118
  	mutex_unlock(&dev_priv->dpio_lock);
89b667f86   Jesse Barnes   drm/i915: update ...
1119
  }
9514ac6e7   Chon Ming Lee   drm/i915: Move so...
1120
  static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
89b667f86   Jesse Barnes   drm/i915: update ...
1121
1122
1123
  {
  	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
  	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
5e69f97fb   Chon Ming Lee   drm/i915: Add add...
1124
1125
  	struct intel_crtc *intel_crtc =
  		to_intel_crtc(encoder->base.crtc);
e4607fcfb   Chon Ming Lee   drm/i915/vlv: Mak...
1126
  	enum dpio_channel port = vlv_dport_to_channel(dport);
5e69f97fb   Chon Ming Lee   drm/i915: Add add...
1127
  	int pipe = intel_crtc->pipe;
89b667f86   Jesse Barnes   drm/i915: update ...
1128
1129
1130
  
  	/* Reset lanes to avoid HDMI flicker (VLV w/a) */
  	mutex_lock(&dev_priv->dpio_lock);
ab3c759a0   Chon Ming Lee   drm/i915/vlv: Ren...
1131
1132
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000);
  	vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060);
89b667f86   Jesse Barnes   drm/i915: update ...
1133
1134
  	mutex_unlock(&dev_priv->dpio_lock);
  }
7d57382e6   Eric Anholt   drm/i915: Add sup...
1135
1136
  static void intel_hdmi_destroy(struct drm_connector *connector)
  {
7d57382e6   Eric Anholt   drm/i915: Add sup...
1137
  	drm_connector_cleanup(connector);
674e2d088   Zhenyu Wang   drm/i915: convert...
1138
  	kfree(connector);
7d57382e6   Eric Anholt   drm/i915: Add sup...
1139
  }
7d57382e6   Eric Anholt   drm/i915: Add sup...
1140
  static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
1141
  	.dpms = intel_connector_dpms,
7d57382e6   Eric Anholt   drm/i915: Add sup...
1142
1143
  	.detect = intel_hdmi_detect,
  	.fill_modes = drm_helper_probe_single_connector_modes,
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1144
  	.set_property = intel_hdmi_set_property,
7d57382e6   Eric Anholt   drm/i915: Add sup...
1145
1146
1147
1148
1149
1150
  	.destroy = intel_hdmi_destroy,
  };
  
  static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
  	.get_modes = intel_hdmi_get_modes,
  	.mode_valid = intel_hdmi_mode_valid,
df0e92488   Chris Wilson   drm/i915: Make th...
1151
  	.best_encoder = intel_best_encoder,
7d57382e6   Eric Anholt   drm/i915: Add sup...
1152
  };
7d57382e6   Eric Anholt   drm/i915: Add sup...
1153
  static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
ea5b213ad   Chris Wilson   drm/i915: Subclas...
1154
  	.destroy = intel_encoder_destroy,
7d57382e6   Eric Anholt   drm/i915: Add sup...
1155
  };
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1156
1157
1158
  static void
  intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
  {
3f43c48d3   Chris Wilson   drm/i915: Share t...
1159
  	intel_attach_force_audio_property(connector);
e953fd7bb   Chris Wilson   drm/i915: Add sup...
1160
  	intel_attach_broadcast_rgb_property(connector);
55bc60db5   Ville Syrjälä   drm/i915: Add "Au...
1161
  	intel_hdmi->color_range_auto = true;
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1162
  }
00c09d70d   Paulo Zanoni   drm/i915: create ...
1163
1164
  void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
  			       struct intel_connector *intel_connector)
7d57382e6   Eric Anholt   drm/i915: Add sup...
1165
  {
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1166
1167
1168
1169
  	struct drm_connector *connector = &intel_connector->base;
  	struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
  	struct intel_encoder *intel_encoder = &intel_dig_port->base;
  	struct drm_device *dev = intel_encoder->base.dev;
7d57382e6   Eric Anholt   drm/i915: Add sup...
1170
  	struct drm_i915_private *dev_priv = dev->dev_private;
174edf1f8   Paulo Zanoni   drm/i915: add por...
1171
  	enum port port = intel_dig_port->port;
373a3cf74   Chris Wilson   drm/i915: call dr...
1172

7d57382e6   Eric Anholt   drm/i915: Add sup...
1173
  	drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
8d91104aa   Adam Jackson   drm/i915: Initial...
1174
  			   DRM_MODE_CONNECTOR_HDMIA);
7d57382e6   Eric Anholt   drm/i915: Add sup...
1175
  	drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
c3febcc43   Peter Ross   drm/i915: allow i...
1176
  	connector->interlace_allowed = 1;
7d57382e6   Eric Anholt   drm/i915: Add sup...
1177
  	connector->doublescan_allowed = 0;
573e74adb   Damien Lespiau   drm/i915: Allow s...
1178
  	connector->stereo_allowed = 1;
66a9278ee   Daniel Vetter   drm/i915: simplif...
1179

08d644add   Daniel Vetter   drm/i915: add por...
1180
1181
  	switch (port) {
  	case PORT_B:
f899fc64c   Chris Wilson   drm/i915: use GMB...
1182
  		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
1d843f9de   Egbert Eich   DRM/I915: Add enu...
1183
  		intel_encoder->hpd_pin = HPD_PORT_B;
08d644add   Daniel Vetter   drm/i915: add por...
1184
1185
  		break;
  	case PORT_C:
7ceae0a55   Eugeni Dodonov   drm/i915: add sup...
1186
  		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
1d843f9de   Egbert Eich   DRM/I915: Add enu...
1187
  		intel_encoder->hpd_pin = HPD_PORT_C;
08d644add   Daniel Vetter   drm/i915: add por...
1188
1189
  		break;
  	case PORT_D:
7ceae0a55   Eugeni Dodonov   drm/i915: add sup...
1190
  		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
1d843f9de   Egbert Eich   DRM/I915: Add enu...
1191
  		intel_encoder->hpd_pin = HPD_PORT_D;
08d644add   Daniel Vetter   drm/i915: add por...
1192
1193
  		break;
  	case PORT_A:
1d843f9de   Egbert Eich   DRM/I915: Add enu...
1194
  		intel_encoder->hpd_pin = HPD_PORT_A;
08d644add   Daniel Vetter   drm/i915: add por...
1195
1196
  		/* Internal port only for eDP. */
  	default:
6e4c1677f   Eugeni Dodonov   drm/i915: show un...
1197
  		BUG();
f8aed700c   Ma Ling   drm/i915: Set crt...
1198
  	}
7d57382e6   Eric Anholt   drm/i915: Add sup...
1199

7637bfdb5   Jesse Barnes   drm/i915: use VLV...
1200
  	if (IS_VALLEYVIEW(dev)) {
90b107c8f   Shobhit Kumar   drm/i915: Enable ...
1201
  		intel_hdmi->write_infoframe = vlv_write_infoframe;
687f4d06d   Paulo Zanoni   drm/i915: add set...
1202
  		intel_hdmi->set_infoframes = vlv_set_infoframes;
7637bfdb5   Jesse Barnes   drm/i915: use VLV...
1203
1204
1205
  	} else if (!HAS_PCH_SPLIT(dev)) {
  		intel_hdmi->write_infoframe = g4x_write_infoframe;
  		intel_hdmi->set_infoframes = g4x_set_infoframes;
22b8bf17c   Paulo Zanoni   drm/i915: use HAS...
1206
  	} else if (HAS_DDI(dev)) {
8c5f5f7c4   Eugeni Dodonov   drm/i915: add new...
1207
  		intel_hdmi->write_infoframe = hsw_write_infoframe;
687f4d06d   Paulo Zanoni   drm/i915: add set...
1208
  		intel_hdmi->set_infoframes = hsw_set_infoframes;
fdf1250aa   Paulo Zanoni   drm/i915: split i...
1209
1210
  	} else if (HAS_PCH_IBX(dev)) {
  		intel_hdmi->write_infoframe = ibx_write_infoframe;
687f4d06d   Paulo Zanoni   drm/i915: add set...
1211
  		intel_hdmi->set_infoframes = ibx_set_infoframes;
fdf1250aa   Paulo Zanoni   drm/i915: split i...
1212
1213
  	} else {
  		intel_hdmi->write_infoframe = cpt_write_infoframe;
687f4d06d   Paulo Zanoni   drm/i915: add set...
1214
  		intel_hdmi->set_infoframes = cpt_set_infoframes;
64a8fc014   Jesse Barnes   drm/i915: fix ILK...
1215
  	}
45187ace9   Jesse Barnes   drm/i915/hdmi: sp...
1216

affa93544   Paulo Zanoni   drm/i915: add HAS...
1217
  	if (HAS_DDI(dev))
bcbc889bc   Paulo Zanoni   drm/i915: add int...
1218
1219
1220
  		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
  	else
  		intel_connector->get_hw_state = intel_connector_get_hw_state;
4932e2c3c   Imre Deak   drm/i915: add unr...
1221
  	intel_connector->unregister = intel_connector_unregister;
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
  
  	intel_hdmi_add_properties(intel_hdmi, connector);
  
  	intel_connector_attach_encoder(intel_connector, intel_encoder);
  	drm_sysfs_connector_add(connector);
  
  	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
  	 * 0xd.  Failure to do so will result in spurious interrupts being
  	 * generated on the port when a cable is not attached.
  	 */
  	if (IS_G4X(dev) && !IS_GM45(dev)) {
  		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
  		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
  	}
  }
b242b7f74   Paulo Zanoni   drm/i915: rename ...
1237
  void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1238
1239
1240
  {
  	struct intel_digital_port *intel_dig_port;
  	struct intel_encoder *intel_encoder;
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1241
  	struct intel_connector *intel_connector;
b14c5679d   Daniel Vetter   drm/i915: use poi...
1242
  	intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1243
1244
  	if (!intel_dig_port)
  		return;
b14c5679d   Daniel Vetter   drm/i915: use poi...
1245
  	intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1246
1247
1248
1249
1250
1251
  	if (!intel_connector) {
  		kfree(intel_dig_port);
  		return;
  	}
  
  	intel_encoder = &intel_dig_port->base;
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1252
1253
1254
  
  	drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
  			 DRM_MODE_ENCODER_TMDS);
00c09d70d   Paulo Zanoni   drm/i915: create ...
1255

5bfe2ac00   Daniel Vetter   drm/i915: add pip...
1256
  	intel_encoder->compute_config = intel_hdmi_compute_config;
c59423a3d   Daniel Vetter   drm/i915/hdmi: us...
1257
  	intel_encoder->mode_set = intel_hdmi_mode_set;
00c09d70d   Paulo Zanoni   drm/i915: create ...
1258
1259
  	intel_encoder->disable = intel_disable_hdmi;
  	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
045ac3b56   Jesse Barnes   drm/i915: add enc...
1260
  	intel_encoder->get_config = intel_hdmi_get_config;
89b667f86   Jesse Barnes   drm/i915: update ...
1261
  	if (IS_VALLEYVIEW(dev)) {
9514ac6e7   Chon Ming Lee   drm/i915: Move so...
1262
1263
  		intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
  		intel_encoder->pre_enable = vlv_hdmi_pre_enable;
b76cf76bf   Jani Nikula   drm/i915: rearran...
1264
  		intel_encoder->enable = vlv_enable_hdmi;
9514ac6e7   Chon Ming Lee   drm/i915: Move so...
1265
  		intel_encoder->post_disable = vlv_hdmi_post_disable;
b76cf76bf   Jani Nikula   drm/i915: rearran...
1266
1267
  	} else {
  		intel_encoder->enable = intel_enable_hdmi;
89b667f86   Jesse Barnes   drm/i915: update ...
1268
  	}
5ab432ef4   Daniel Vetter   drm/i915/hdmi: co...
1269

b9cb234cb   Paulo Zanoni   drm/i915: split i...
1270
1271
  	intel_encoder->type = INTEL_OUTPUT_HDMI;
  	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
301ea74a5   Ville Syrjälä   drm/i915: Allow H...
1272
  	intel_encoder->cloneable = 1 << INTEL_OUTPUT_ANALOG;
c6f1495d4   Ville Syrjälä   drm/i915: Allow H...
1273
1274
1275
1276
1277
1278
1279
  	/*
  	 * BSpec is unclear about HDMI+HDMI cloning on g4x, but it seems
  	 * to work on real hardware. And since g4x can send infoframes to
  	 * only one port anyway, nothing is lost by allowing it.
  	 */
  	if (IS_G4X(dev))
  		intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
7d57382e6   Eric Anholt   drm/i915: Add sup...
1280

174edf1f8   Paulo Zanoni   drm/i915: add por...
1281
  	intel_dig_port->port = port;
b242b7f74   Paulo Zanoni   drm/i915: rename ...
1282
  	intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
b9cb234cb   Paulo Zanoni   drm/i915: split i...
1283
  	intel_dig_port->dp.output_reg = 0;
55b7d6e8c   Chris Wilson   drm/i915/hdmi: Ad...
1284

b9cb234cb   Paulo Zanoni   drm/i915: split i...
1285
  	intel_hdmi_init_connector(intel_dig_port, intel_connector);
7d57382e6   Eric Anholt   drm/i915: Add sup...
1286
  }