Blame view
drivers/gpu/drm/i915/intel_hdmi.c
37.6 KB
7d57382e6 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 include cleanup: ... |
30 |
#include <linux/slab.h> |
7d57382e6 drm/i915: Add sup... |
31 |
#include <linux/delay.h> |
178f736ab drm/i915/hdmi: Ch... |
32 |
#include <linux/hdmi.h> |
760285e7e UAPI: (Scripted) ... |
33 34 35 |
#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> |
7d57382e6 drm/i915: Add sup... |
36 |
#include "intel_drv.h" |
760285e7e UAPI: (Scripted) ... |
37 |
#include <drm/i915_drm.h> |
7d57382e6 drm/i915: Add sup... |
38 |
#include "i915_drv.h" |
30add22d8 drm/i915: add int... |
39 40 |
static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi) { |
da63a9f2e drm/i915: create ... |
41 |
return hdmi_to_dig_port(intel_hdmi)->base.base.dev; |
30add22d8 drm/i915: add int... |
42 |
} |
afba01889 drm/i915: ensure ... |
43 44 45 |
static void assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) { |
30add22d8 drm/i915: add int... |
46 |
struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi); |
afba01889 drm/i915: ensure ... |
47 48 |
struct drm_i915_private *dev_priv = dev->dev_private; uint32_t enabled_bits; |
affa93544 drm/i915: add HAS... |
49 |
enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; |
afba01889 drm/i915: ensure ... |
50 |
|
b242b7f74 drm/i915: rename ... |
51 |
WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits, |
afba01889 drm/i915: ensure ... |
52 53 54 |
"HDMI port enabled, expecting disabled "); } |
f5bbfca3e drm/i915: move HD... |
55 |
struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
ea5b213ad drm/i915: Subclas... |
56 |
{ |
da63a9f2e 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 drm/i915: Subclas... |
60 |
} |
df0e92488 drm/i915: Make th... |
61 62 |
static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) { |
da63a9f2e drm/i915: create ... |
63 |
return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base); |
df0e92488 drm/i915: Make th... |
64 |
} |
178f736ab drm/i915/hdmi: Ch... |
65 |
static u32 g4x_infoframe_index(enum hdmi_infoframe_type type) |
3c17fe4b8 i915: enable AVI ... |
66 |
{ |
178f736ab drm/i915/hdmi: Ch... |
67 68 |
switch (type) { case HDMI_INFOFRAME_TYPE_AVI: |
ed517fbbb drm/i915: small h... |
69 |
return VIDEO_DIP_SELECT_AVI; |
178f736ab drm/i915/hdmi: Ch... |
70 |
case HDMI_INFOFRAME_TYPE_SPD: |
ed517fbbb drm/i915: small h... |
71 |
return VIDEO_DIP_SELECT_SPD; |
c8bb75aff drm/i915/hdmi: Wr... |
72 73 |
case HDMI_INFOFRAME_TYPE_VENDOR: return VIDEO_DIP_SELECT_VENDOR; |
45187ace9 drm/i915/hdmi: sp... |
74 |
default: |
178f736ab drm/i915/hdmi: Ch... |
75 76 |
DRM_DEBUG_DRIVER("unknown info frame type %d ", type); |
ed517fbbb drm/i915: small h... |
77 |
return 0; |
45187ace9 drm/i915/hdmi: sp... |
78 |
} |
45187ace9 drm/i915/hdmi: sp... |
79 |
} |
178f736ab drm/i915/hdmi: Ch... |
80 |
static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type) |
45187ace9 drm/i915/hdmi: sp... |
81 |
{ |
178f736ab drm/i915/hdmi: Ch... |
82 83 |
switch (type) { case HDMI_INFOFRAME_TYPE_AVI: |
ed517fbbb drm/i915: small h... |
84 |
return VIDEO_DIP_ENABLE_AVI; |
178f736ab drm/i915/hdmi: Ch... |
85 |
case HDMI_INFOFRAME_TYPE_SPD: |
ed517fbbb drm/i915: small h... |
86 |
return VIDEO_DIP_ENABLE_SPD; |
c8bb75aff drm/i915/hdmi: Wr... |
87 88 |
case HDMI_INFOFRAME_TYPE_VENDOR: return VIDEO_DIP_ENABLE_VENDOR; |
fa193ff79 drm/i915: break i... |
89 |
default: |
178f736ab drm/i915/hdmi: Ch... |
90 91 |
DRM_DEBUG_DRIVER("unknown info frame type %d ", type); |
ed517fbbb drm/i915: small h... |
92 |
return 0; |
fa193ff79 drm/i915: break i... |
93 |
} |
fa193ff79 drm/i915: break i... |
94 |
} |
178f736ab drm/i915/hdmi: Ch... |
95 |
static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type) |
2da8af540 drm/i915: impleme... |
96 |
{ |
178f736ab drm/i915/hdmi: Ch... |
97 98 |
switch (type) { case HDMI_INFOFRAME_TYPE_AVI: |
2da8af540 drm/i915: impleme... |
99 |
return VIDEO_DIP_ENABLE_AVI_HSW; |
178f736ab drm/i915/hdmi: Ch... |
100 |
case HDMI_INFOFRAME_TYPE_SPD: |
2da8af540 drm/i915: impleme... |
101 |
return VIDEO_DIP_ENABLE_SPD_HSW; |
c8bb75aff drm/i915/hdmi: Wr... |
102 103 |
case HDMI_INFOFRAME_TYPE_VENDOR: return VIDEO_DIP_ENABLE_VS_HSW; |
2da8af540 drm/i915: impleme... |
104 |
default: |
178f736ab drm/i915/hdmi: Ch... |
105 106 |
DRM_DEBUG_DRIVER("unknown info frame type %d ", type); |
2da8af540 drm/i915: impleme... |
107 108 109 |
return 0; } } |
178f736ab drm/i915/hdmi: Ch... |
110 |
static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type, |
7d9bcebe1 drm/i915: Use cpu... |
111 |
enum transcoder cpu_transcoder) |
2da8af540 drm/i915: impleme... |
112 |
{ |
178f736ab drm/i915/hdmi: Ch... |
113 114 |
switch (type) { case HDMI_INFOFRAME_TYPE_AVI: |
7d9bcebe1 drm/i915: Use cpu... |
115 |
return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); |
178f736ab drm/i915/hdmi: Ch... |
116 |
case HDMI_INFOFRAME_TYPE_SPD: |
7d9bcebe1 drm/i915: Use cpu... |
117 |
return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); |
c8bb75aff drm/i915/hdmi: Wr... |
118 119 |
case HDMI_INFOFRAME_TYPE_VENDOR: return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder); |
2da8af540 drm/i915: impleme... |
120 |
default: |
178f736ab drm/i915/hdmi: Ch... |
121 122 |
DRM_DEBUG_DRIVER("unknown info frame type %d ", type); |
2da8af540 drm/i915: impleme... |
123 124 125 |
return 0; } } |
a3da1df7b drm/i915: s/i9xx_... |
126 |
static void g4x_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
127 128 |
enum hdmi_infoframe_type type, const uint8_t *frame, ssize_t len) |
45187ace9 drm/i915/hdmi: sp... |
129 130 |
{ uint32_t *data = (uint32_t *)frame; |
3c17fe4b8 i915: enable AVI ... |
131 132 |
struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
22509ec86 drm/i915: change ... |
133 |
u32 val = I915_READ(VIDEO_DIP_CTL); |
178f736ab drm/i915/hdmi: Ch... |
134 |
int i; |
3c17fe4b8 i915: enable AVI ... |
135 |
|
822974aea drm/i915: enable ... |
136 137 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
1d4f85ac2 drm/i915: start w... |
138 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
139 |
val |= g4x_infoframe_index(type); |
22509ec86 drm/i915: change ... |
140 |
|
178f736ab drm/i915/hdmi: Ch... |
141 |
val &= ~g4x_infoframe_enable(type); |
45187ace9 drm/i915/hdmi: sp... |
142 |
|
22509ec86 drm/i915: change ... |
143 |
I915_WRITE(VIDEO_DIP_CTL, val); |
3c17fe4b8 i915: enable AVI ... |
144 |
|
9d9740f09 drm/i915: add som... |
145 |
mmiowb(); |
45187ace9 drm/i915/hdmi: sp... |
146 |
for (i = 0; i < len; i += 4) { |
3c17fe4b8 i915: enable AVI ... |
147 148 149 |
I915_WRITE(VIDEO_DIP_DATA, *data); data++; } |
adf00b26d drm/i915: make su... |
150 151 152 |
/* 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 drm/i915: add som... |
153 |
mmiowb(); |
3c17fe4b8 i915: enable AVI ... |
154 |
|
178f736ab drm/i915/hdmi: Ch... |
155 |
val |= g4x_infoframe_enable(type); |
60c5ea2dd drm/i915: mask th... |
156 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
157 |
val |= VIDEO_DIP_FREQ_VSYNC; |
45187ace9 drm/i915/hdmi: sp... |
158 |
|
22509ec86 drm/i915: change ... |
159 |
I915_WRITE(VIDEO_DIP_CTL, val); |
9d9740f09 drm/i915: add som... |
160 |
POSTING_READ(VIDEO_DIP_CTL); |
3c17fe4b8 i915: enable AVI ... |
161 |
} |
fdf1250aa drm/i915: split i... |
162 |
static void ibx_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
163 164 |
enum hdmi_infoframe_type type, const uint8_t *frame, ssize_t len) |
fdf1250aa drm/i915: split i... |
165 166 167 168 |
{ uint32_t *data = (uint32_t *)frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
ed517fbbb drm/i915: small h... |
169 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
178f736ab drm/i915/hdmi: Ch... |
170 |
int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
fdf1250aa drm/i915: split i... |
171 |
u32 val = I915_READ(reg); |
822974aea drm/i915: enable ... |
172 173 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
fdf1250aa drm/i915: split i... |
174 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
175 |
val |= g4x_infoframe_index(type); |
fdf1250aa drm/i915: split i... |
176 |
|
178f736ab drm/i915/hdmi: Ch... |
177 |
val &= ~g4x_infoframe_enable(type); |
fdf1250aa drm/i915: split i... |
178 179 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
180 |
mmiowb(); |
fdf1250aa drm/i915: split i... |
181 182 183 184 |
for (i = 0; i < len; i += 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } |
adf00b26d drm/i915: make su... |
185 186 187 |
/* 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 drm/i915: add som... |
188 |
mmiowb(); |
fdf1250aa drm/i915: split i... |
189 |
|
178f736ab drm/i915/hdmi: Ch... |
190 |
val |= g4x_infoframe_enable(type); |
fdf1250aa drm/i915: split i... |
191 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
192 |
val |= VIDEO_DIP_FREQ_VSYNC; |
fdf1250aa drm/i915: split i... |
193 194 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
195 |
POSTING_READ(reg); |
fdf1250aa drm/i915: split i... |
196 197 198 |
} static void cpt_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
199 200 |
enum hdmi_infoframe_type type, const uint8_t *frame, ssize_t len) |
b055c8f3e drm/i915/hdmi: se... |
201 |
{ |
45187ace9 drm/i915/hdmi: sp... |
202 |
uint32_t *data = (uint32_t *)frame; |
b055c8f3e drm/i915/hdmi: se... |
203 204 |
struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
ed517fbbb drm/i915: small h... |
205 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
178f736ab drm/i915/hdmi: Ch... |
206 |
int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
22509ec86 drm/i915: change ... |
207 |
u32 val = I915_READ(reg); |
b055c8f3e drm/i915/hdmi: se... |
208 |
|
822974aea drm/i915: enable ... |
209 210 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
64a8fc014 drm/i915: fix ILK... |
211 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
212 |
val |= g4x_infoframe_index(type); |
45187ace9 drm/i915/hdmi: sp... |
213 |
|
ecb978515 drm/i915: disable... |
214 215 |
/* The DIP control register spec says that we need to update the AVI * infoframe without clearing its enable bit */ |
178f736ab drm/i915/hdmi: Ch... |
216 217 |
if (type != HDMI_INFOFRAME_TYPE_AVI) val &= ~g4x_infoframe_enable(type); |
ecb978515 drm/i915: disable... |
218 |
|
22509ec86 drm/i915: change ... |
219 |
I915_WRITE(reg, val); |
45187ace9 drm/i915/hdmi: sp... |
220 |
|
9d9740f09 drm/i915: add som... |
221 |
mmiowb(); |
45187ace9 drm/i915/hdmi: sp... |
222 |
for (i = 0; i < len; i += 4) { |
b055c8f3e drm/i915/hdmi: se... |
223 224 225 |
I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } |
adf00b26d drm/i915: make su... |
226 227 228 |
/* 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 drm/i915: add som... |
229 |
mmiowb(); |
b055c8f3e drm/i915/hdmi: se... |
230 |
|
178f736ab drm/i915/hdmi: Ch... |
231 |
val |= g4x_infoframe_enable(type); |
60c5ea2dd drm/i915: mask th... |
232 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
233 |
val |= VIDEO_DIP_FREQ_VSYNC; |
45187ace9 drm/i915/hdmi: sp... |
234 |
|
22509ec86 drm/i915: change ... |
235 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
236 |
POSTING_READ(reg); |
45187ace9 drm/i915/hdmi: sp... |
237 |
} |
90b107c8f drm/i915: Enable ... |
238 239 |
static void vlv_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
240 241 |
enum hdmi_infoframe_type type, const uint8_t *frame, ssize_t len) |
90b107c8f drm/i915: Enable ... |
242 243 244 245 |
{ uint32_t *data = (uint32_t *)frame; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
ed517fbbb drm/i915: small h... |
246 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
178f736ab drm/i915/hdmi: Ch... |
247 |
int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
22509ec86 drm/i915: change ... |
248 |
u32 val = I915_READ(reg); |
90b107c8f drm/i915: Enable ... |
249 |
|
822974aea drm/i915: enable ... |
250 251 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
90b107c8f drm/i915: Enable ... |
252 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
253 |
val |= g4x_infoframe_index(type); |
22509ec86 drm/i915: change ... |
254 |
|
178f736ab drm/i915/hdmi: Ch... |
255 |
val &= ~g4x_infoframe_enable(type); |
90b107c8f drm/i915: Enable ... |
256 |
|
22509ec86 drm/i915: change ... |
257 |
I915_WRITE(reg, val); |
90b107c8f drm/i915: Enable ... |
258 |
|
9d9740f09 drm/i915: add som... |
259 |
mmiowb(); |
90b107c8f drm/i915: Enable ... |
260 261 262 263 |
for (i = 0; i < len; i += 4) { I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } |
adf00b26d drm/i915: make su... |
264 265 266 |
/* 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 drm/i915: add som... |
267 |
mmiowb(); |
90b107c8f drm/i915: Enable ... |
268 |
|
178f736ab drm/i915/hdmi: Ch... |
269 |
val |= g4x_infoframe_enable(type); |
60c5ea2dd drm/i915: mask th... |
270 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
271 |
val |= VIDEO_DIP_FREQ_VSYNC; |
90b107c8f drm/i915: Enable ... |
272 |
|
22509ec86 drm/i915: change ... |
273 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
274 |
POSTING_READ(reg); |
90b107c8f drm/i915: Enable ... |
275 |
} |
8c5f5f7c4 drm/i915: add new... |
276 |
static void hsw_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
277 278 |
enum hdmi_infoframe_type type, const uint8_t *frame, ssize_t len) |
8c5f5f7c4 drm/i915: add new... |
279 |
{ |
2da8af540 drm/i915: impleme... |
280 281 282 283 |
uint32_t *data = (uint32_t *)frame; 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 drm/i915: move cp... |
284 |
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
178f736ab drm/i915/hdmi: Ch... |
285 286 |
u32 data_reg; int i; |
2da8af540 drm/i915: impleme... |
287 |
u32 val = I915_READ(ctl_reg); |
8c5f5f7c4 drm/i915: add new... |
288 |
|
178f736ab drm/i915/hdmi: Ch... |
289 290 |
data_reg = hsw_infoframe_data_reg(type, intel_crtc->config.cpu_transcoder); |
2da8af540 drm/i915: impleme... |
291 292 |
if (data_reg == 0) return; |
178f736ab drm/i915/hdmi: Ch... |
293 |
val &= ~hsw_infoframe_enable(type); |
2da8af540 drm/i915: impleme... |
294 |
I915_WRITE(ctl_reg, val); |
9d9740f09 drm/i915: add som... |
295 |
mmiowb(); |
2da8af540 drm/i915: impleme... |
296 297 298 299 |
for (i = 0; i < len; i += 4) { I915_WRITE(data_reg + i, *data); data++; } |
adf00b26d drm/i915: make su... |
300 301 302 |
/* 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 drm/i915: add som... |
303 |
mmiowb(); |
8c5f5f7c4 drm/i915: add new... |
304 |
|
178f736ab drm/i915/hdmi: Ch... |
305 |
val |= hsw_infoframe_enable(type); |
2da8af540 drm/i915: impleme... |
306 |
I915_WRITE(ctl_reg, val); |
9d9740f09 drm/i915: add som... |
307 |
POSTING_READ(ctl_reg); |
8c5f5f7c4 drm/i915: add new... |
308 |
} |
5adaea799 drm/i915/hdmi: Po... |
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
/* * 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 drm/i915/hmdi: Re... |
326 327 |
static void intel_write_infoframe(struct drm_encoder *encoder, union hdmi_infoframe *frame) |
45187ace9 drm/i915/hdmi: sp... |
328 329 |
{ struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
5adaea799 drm/i915/hdmi: Po... |
330 331 |
uint8_t buffer[VIDEO_DIP_DATA_SIZE]; ssize_t len; |
45187ace9 drm/i915/hdmi: sp... |
332 |
|
5adaea799 drm/i915/hdmi: Po... |
333 334 335 336 337 338 339 340 341 342 343 |
/* 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 drm/i915/hdmi: sp... |
344 |
|
5adaea799 drm/i915/hdmi: Po... |
345 |
intel_hdmi->write_infoframe(encoder, frame->any.type, buffer, len); |
45187ace9 drm/i915/hdmi: sp... |
346 |
} |
687f4d06d drm/i915: add set... |
347 |
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |
c846b6194 drm/i915: make DB... |
348 |
struct drm_display_mode *adjusted_mode) |
45187ace9 drm/i915/hdmi: sp... |
349 |
{ |
abedc077b drm/i915: Provide... |
350 |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
50f3b016b drm/i915: add pip... |
351 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
5adaea799 drm/i915/hdmi: Po... |
352 353 |
union hdmi_infoframe frame; int ret; |
45187ace9 drm/i915/hdmi: sp... |
354 |
|
5adaea799 drm/i915/hdmi: Po... |
355 356 357 358 359 360 361 |
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, adjusted_mode); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe "); return; } |
c846b6194 drm/i915: make DB... |
362 |
|
abedc077b drm/i915: Provide... |
363 |
if (intel_hdmi->rgb_quant_range_selectable) { |
50f3b016b drm/i915: add pip... |
364 |
if (intel_crtc->config.limited_color_range) |
5adaea799 drm/i915/hdmi: Po... |
365 366 |
frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED; |
abedc077b drm/i915: Provide... |
367 |
else |
5adaea799 drm/i915/hdmi: Po... |
368 369 |
frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; |
abedc077b drm/i915: Provide... |
370 |
} |
9198ee5b9 drm/i915/hmdi: Re... |
371 |
intel_write_infoframe(encoder, &frame); |
b055c8f3e drm/i915/hdmi: se... |
372 |
} |
687f4d06d drm/i915: add set... |
373 |
static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) |
c0864cb39 drm/i915/hdmi: HD... |
374 |
{ |
5adaea799 drm/i915/hdmi: Po... |
375 376 377 378 379 380 381 382 383 |
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 drm/i915/hdmi: HD... |
384 |
|
5adaea799 drm/i915/hdmi: Po... |
385 |
frame.spd.sdi = HDMI_SPD_SDI_PC; |
c0864cb39 drm/i915/hdmi: HD... |
386 |
|
9198ee5b9 drm/i915/hmdi: Re... |
387 |
intel_write_infoframe(encoder, &frame); |
c0864cb39 drm/i915/hdmi: HD... |
388 |
} |
c8bb75aff drm/i915/hdmi: Wr... |
389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
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 drm/i915: add set... |
403 404 405 |
static void g4x_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { |
0c14c7f95 drm/i915: properl... |
406 |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
69fde0a61 drm/i915: Convert... |
407 408 |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; |
0c14c7f95 drm/i915: properl... |
409 410 |
u32 reg = VIDEO_DIP_CTL; u32 val = I915_READ(reg); |
72b78c9d1 drm/i915: disable... |
411 |
u32 port; |
0c14c7f95 drm/i915: properl... |
412 |
|
afba01889 drm/i915: ensure ... |
413 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 drm/i915: properl... |
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
/* 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 drm/i915: add som... |
430 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
431 432 |
return; } |
69fde0a61 drm/i915: Convert... |
433 434 |
switch (intel_dig_port->port) { case PORT_B: |
72b78c9d1 drm/i915: disable... |
435 |
port = VIDEO_DIP_PORT_B; |
f278d9721 drm/i915: only se... |
436 |
break; |
69fde0a61 drm/i915: Convert... |
437 |
case PORT_C: |
72b78c9d1 drm/i915: disable... |
438 |
port = VIDEO_DIP_PORT_C; |
f278d9721 drm/i915: only se... |
439 440 |
break; default: |
57df2ae9d drm/i915: BUG() o... |
441 |
BUG(); |
f278d9721 drm/i915: only se... |
442 443 |
return; } |
72b78c9d1 drm/i915: disable... |
444 445 446 447 |
if (port != (val & VIDEO_DIP_PORT_MASK)) { if (val & VIDEO_DIP_ENABLE) { val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
448 |
POSTING_READ(reg); |
72b78c9d1 drm/i915: disable... |
449 450 451 452 |
} val &= ~VIDEO_DIP_PORT_MASK; val |= port; } |
822974aea drm/i915: enable ... |
453 |
val |= VIDEO_DIP_ENABLE; |
0dd87d208 drm/i915: explici... |
454 |
val &= ~VIDEO_DIP_ENABLE_VENDOR; |
822974aea drm/i915: enable ... |
455 |
|
f278d9721 drm/i915: only se... |
456 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
457 |
POSTING_READ(reg); |
f278d9721 drm/i915: only se... |
458 |
|
687f4d06d drm/i915: add set... |
459 460 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
461 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d drm/i915: add set... |
462 463 464 465 466 |
} static void ibx_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { |
0c14c7f95 drm/i915: properl... |
467 468 |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
69fde0a61 drm/i915: Convert... |
469 470 |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; |
0c14c7f95 drm/i915: properl... |
471 472 |
u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); |
72b78c9d1 drm/i915: disable... |
473 |
u32 port; |
0c14c7f95 drm/i915: properl... |
474 |
|
afba01889 drm/i915: ensure ... |
475 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 drm/i915: properl... |
476 477 478 479 480 481 482 483 |
/* 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 drm/i915: add som... |
484 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
485 486 |
return; } |
69fde0a61 drm/i915: Convert... |
487 488 |
switch (intel_dig_port->port) { case PORT_B: |
72b78c9d1 drm/i915: disable... |
489 |
port = VIDEO_DIP_PORT_B; |
f278d9721 drm/i915: only se... |
490 |
break; |
69fde0a61 drm/i915: Convert... |
491 |
case PORT_C: |
72b78c9d1 drm/i915: disable... |
492 |
port = VIDEO_DIP_PORT_C; |
f278d9721 drm/i915: only se... |
493 |
break; |
69fde0a61 drm/i915: Convert... |
494 |
case PORT_D: |
72b78c9d1 drm/i915: disable... |
495 |
port = VIDEO_DIP_PORT_D; |
f278d9721 drm/i915: only se... |
496 497 |
break; default: |
57df2ae9d drm/i915: BUG() o... |
498 |
BUG(); |
f278d9721 drm/i915: only se... |
499 500 |
return; } |
72b78c9d1 drm/i915: disable... |
501 502 503 504 |
if (port != (val & VIDEO_DIP_PORT_MASK)) { if (val & VIDEO_DIP_ENABLE) { val &= ~VIDEO_DIP_ENABLE; I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
505 |
POSTING_READ(reg); |
72b78c9d1 drm/i915: disable... |
506 507 508 509 |
} val &= ~VIDEO_DIP_PORT_MASK; val |= port; } |
822974aea drm/i915: enable ... |
510 |
val |= VIDEO_DIP_ENABLE; |
0dd87d208 drm/i915: explici... |
511 512 |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); |
822974aea drm/i915: enable ... |
513 |
|
f278d9721 drm/i915: only se... |
514 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
515 |
POSTING_READ(reg); |
f278d9721 drm/i915: only se... |
516 |
|
687f4d06d drm/i915: add set... |
517 518 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
519 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d drm/i915: add set... |
520 521 522 523 524 |
} static void cpt_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { |
0c14c7f95 drm/i915: properl... |
525 526 527 528 529 |
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 drm/i915: ensure ... |
530 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 drm/i915: properl... |
531 532 533 534 535 536 537 538 |
/* 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 drm/i915: add som... |
539 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
540 541 |
return; } |
822974aea drm/i915: enable ... |
542 543 |
/* Set both together, unset both together: see the spec. */ val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; |
0dd87d208 drm/i915: explici... |
544 545 |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); |
822974aea drm/i915: enable ... |
546 547 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
548 |
POSTING_READ(reg); |
822974aea drm/i915: enable ... |
549 |
|
687f4d06d drm/i915: add set... |
550 551 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
552 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d drm/i915: add set... |
553 554 555 556 557 |
} static void vlv_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { |
0c14c7f95 drm/i915: properl... |
558 559 560 561 562 |
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 drm/i915: ensure ... |
563 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 drm/i915: properl... |
564 565 566 567 568 569 570 571 |
/* 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 drm/i915: add som... |
572 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
573 574 |
return; } |
822974aea drm/i915: enable ... |
575 |
val |= VIDEO_DIP_ENABLE; |
0dd87d208 drm/i915: explici... |
576 577 |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); |
822974aea drm/i915: enable ... |
578 579 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
580 |
POSTING_READ(reg); |
822974aea drm/i915: enable ... |
581 |
|
687f4d06d drm/i915: add set... |
582 583 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
584 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d drm/i915: add set... |
585 586 587 588 589 |
} static void hsw_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { |
0c14c7f95 drm/i915: properl... |
590 591 592 |
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 drm/i915: move cp... |
593 |
u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
0dd87d208 drm/i915: explici... |
594 |
u32 val = I915_READ(reg); |
0c14c7f95 drm/i915: properl... |
595 |
|
afba01889 drm/i915: ensure ... |
596 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 drm/i915: properl... |
597 598 |
if (!intel_hdmi->has_hdmi_sink) { I915_WRITE(reg, 0); |
9d9740f09 drm/i915: add som... |
599 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
600 601 |
return; } |
0dd87d208 drm/i915: explici... |
602 603 604 605 |
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 drm/i915: add som... |
606 |
POSTING_READ(reg); |
0dd87d208 drm/i915: explici... |
607 |
|
687f4d06d drm/i915: add set... |
608 609 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
610 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d drm/i915: add set... |
611 |
} |
c59423a3d drm/i915/hdmi: us... |
612 |
static void intel_hdmi_mode_set(struct intel_encoder *encoder) |
7d57382e6 drm/i915: Add sup... |
613 |
{ |
c59423a3d drm/i915/hdmi: us... |
614 |
struct drm_device *dev = encoder->base.dev; |
7d57382e6 drm/i915: Add sup... |
615 |
struct drm_i915_private *dev_priv = dev->dev_private; |
c59423a3d drm/i915/hdmi: us... |
616 617 618 |
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 drm/i915: rename ... |
619 |
u32 hdmi_val; |
7d57382e6 drm/i915: Add sup... |
620 |
|
b242b7f74 drm/i915: rename ... |
621 |
hdmi_val = SDVO_ENCODING_HDMI; |
2af2c4909 Revert "drm/i915:... |
622 |
if (!HAS_PCH_SPLIT(dev)) |
b242b7f74 drm/i915: rename ... |
623 |
hdmi_val |= intel_hdmi->color_range; |
b599c0bca drm/i915/hdmi: Se... |
624 |
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
b242b7f74 drm/i915: rename ... |
625 |
hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; |
b599c0bca drm/i915/hdmi: Se... |
626 |
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
b242b7f74 drm/i915: rename ... |
627 |
hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH; |
7d57382e6 drm/i915: Add sup... |
628 |
|
c59423a3d drm/i915/hdmi: us... |
629 |
if (crtc->config.pipe_bpp > 24) |
4f3a8bc7b drm/i915: rename ... |
630 |
hdmi_val |= HDMI_COLOR_FORMAT_12bpc; |
020f6704b drm/i915: use pip... |
631 |
else |
4f3a8bc7b drm/i915: rename ... |
632 |
hdmi_val |= SDVO_COLOR_FORMAT_8bpc; |
020f6704b drm/i915: use pip... |
633 |
|
2e3d6006a drm/i915: Enable ... |
634 635 |
/* Required on CPT */ if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) |
dc0fa7181 drm/i915: remove ... |
636 |
hdmi_val |= HDMI_MODE_SELECT_HDMI; |
2e3d6006a drm/i915: Enable ... |
637 |
|
3c17fe4b8 i915: enable AVI ... |
638 |
if (intel_hdmi->has_audio) { |
e0dac65ed drm/i915: pass EL... |
639 640 |
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c ", |
c59423a3d drm/i915/hdmi: us... |
641 |
pipe_name(crtc->pipe)); |
b242b7f74 drm/i915: rename ... |
642 |
hdmi_val |= SDVO_AUDIO_ENABLE; |
dc0fa7181 drm/i915: remove ... |
643 |
hdmi_val |= HDMI_MODE_SELECT_HDMI; |
c59423a3d drm/i915/hdmi: us... |
644 |
intel_write_eld(&encoder->base, adjusted_mode); |
3c17fe4b8 i915: enable AVI ... |
645 |
} |
7d57382e6 drm/i915: Add sup... |
646 |
|
75770564c drm/i915: use tra... |
647 |
if (HAS_PCH_CPT(dev)) |
c59423a3d drm/i915/hdmi: us... |
648 |
hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); |
dc0fa7181 drm/i915: remove ... |
649 |
else |
c59423a3d drm/i915/hdmi: us... |
650 |
hdmi_val |= SDVO_PIPE_SEL(crtc->pipe); |
7d57382e6 drm/i915: Add sup... |
651 |
|
b242b7f74 drm/i915: rename ... |
652 653 |
I915_WRITE(intel_hdmi->hdmi_reg, hdmi_val); POSTING_READ(intel_hdmi->hdmi_reg); |
3c17fe4b8 i915: enable AVI ... |
654 |
|
c59423a3d drm/i915/hdmi: us... |
655 |
intel_hdmi->set_infoframes(&encoder->base, adjusted_mode); |
7d57382e6 drm/i915: Add sup... |
656 |
} |
85234cdc2 drm/i915/hdmi: im... |
657 658 |
static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) |
7d57382e6 drm/i915: Add sup... |
659 |
{ |
85234cdc2 drm/i915/hdmi: im... |
660 |
struct drm_device *dev = encoder->base.dev; |
7d57382e6 drm/i915: Add sup... |
661 |
struct drm_i915_private *dev_priv = dev->dev_private; |
85234cdc2 drm/i915/hdmi: im... |
662 663 |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); u32 tmp; |
b242b7f74 drm/i915: rename ... |
664 |
tmp = I915_READ(intel_hdmi->hdmi_reg); |
85234cdc2 drm/i915/hdmi: im... |
665 666 667 668 669 670 671 672 673 674 675 |
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 drm/i915: add enc... |
676 677 678 679 680 681 |
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 drm/i915: Fix por... |
682 |
int dotclock; |
045ac3b56 drm/i915: add enc... |
683 684 685 686 687 688 689 690 691 692 693 694 695 696 |
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 drm/i915: Fix por... |
697 698 699 700 701 702 703 704 |
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 drm/i915: Use crt... |
705 |
pipe_config->adjusted_mode.crtc_clock = dotclock; |
045ac3b56 drm/i915: add enc... |
706 |
} |
5ab432ef4 drm/i915/hdmi: co... |
707 |
static void intel_enable_hdmi(struct intel_encoder *encoder) |
7d57382e6 drm/i915: Add sup... |
708 |
{ |
5ab432ef4 drm/i915/hdmi: co... |
709 |
struct drm_device *dev = encoder->base.dev; |
7d57382e6 drm/i915: Add sup... |
710 |
struct drm_i915_private *dev_priv = dev->dev_private; |
dc0fa7181 drm/i915: remove ... |
711 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
5ab432ef4 drm/i915/hdmi: co... |
712 |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
7d57382e6 drm/i915: Add sup... |
713 |
u32 temp; |
2deed7611 drm/i915: HDMI ho... |
714 715 716 717 |
u32 enable_bits = SDVO_ENABLE; if (intel_hdmi->has_audio) enable_bits |= SDVO_AUDIO_ENABLE; |
7d57382e6 drm/i915: Add sup... |
718 |
|
b242b7f74 drm/i915: rename ... |
719 |
temp = I915_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 drm/i915: HDMI ha... |
720 |
|
7a87c2897 drm/i915: impleme... |
721 |
/* HW workaround for IBX, we need to move the port to transcoder A |
dc0fa7181 drm/i915: remove ... |
722 723 724 |
* before disabling it, so restore the transcoder select bit here. */ if (HAS_PCH_IBX(dev)) enable_bits |= SDVO_PIPE_SEL(intel_crtc->pipe); |
7a87c2897 drm/i915: impleme... |
725 |
|
d8a2d0e00 drm/i915: HDMI ha... |
726 727 728 |
/* HW workaround, need to toggle enable bit off and on for 12bpc, but * we do this anyway which shows more stable in testing. */ |
c619eed4b drm/i915: More s/... |
729 |
if (HAS_PCH_SPLIT(dev)) { |
b242b7f74 drm/i915: rename ... |
730 731 |
I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE); POSTING_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 drm/i915: HDMI ha... |
732 |
} |
5ab432ef4 drm/i915/hdmi: co... |
733 |
temp |= enable_bits; |
b242b7f74 drm/i915: rename ... |
734 735 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 drm/i915/hdmi: co... |
736 737 738 739 740 |
/* HW workaround, need to write this twice for issue that may result * in first write getting masked. */ if (HAS_PCH_SPLIT(dev)) { |
b242b7f74 drm/i915: rename ... |
741 742 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
7d57382e6 drm/i915: Add sup... |
743 |
} |
b76cf76bf drm/i915: rearran... |
744 |
} |
89b667f86 drm/i915: update ... |
745 |
|
b76cf76bf drm/i915: rearran... |
746 747 |
static void vlv_enable_hdmi(struct intel_encoder *encoder) { |
5ab432ef4 drm/i915/hdmi: co... |
748 749 750 751 752 753 754 755 |
} 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 drm/i915: HDMI - ... |
756 |
u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; |
5ab432ef4 drm/i915/hdmi: co... |
757 |
|
b242b7f74 drm/i915: rename ... |
758 |
temp = I915_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 drm/i915/hdmi: co... |
759 760 761 762 763 764 765 766 767 |
/* 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 drm/i915: rename ... |
768 769 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 drm/i915/hdmi: co... |
770 771 |
/* Again we need to write this twice. */ |
b242b7f74 drm/i915: rename ... |
772 773 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 drm/i915/hdmi: co... |
774 775 776 777 778 779 780 781 |
/* Transcoder selection bits only update * effectively on vblank. */ if (crtc) intel_wait_for_vblank(dev, pipe); else msleep(50); } |
7d57382e6 drm/i915: Add sup... |
782 |
} |
d8a2d0e00 drm/i915: HDMI ha... |
783 |
|
5ab432ef4 drm/i915/hdmi: co... |
784 785 786 787 |
/* 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 drm/i915: rename ... |
788 789 |
I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 drm/i915/hdmi: co... |
790 791 792 |
} temp &= ~enable_bits; |
d8a2d0e00 drm/i915: HDMI ha... |
793 |
|
b242b7f74 drm/i915: rename ... |
794 795 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 drm/i915: HDMI ha... |
796 797 798 799 |
/* HW workaround, need to write this twice for issue that may result * in first write getting masked. */ |
c619eed4b drm/i915: More s/... |
800 |
if (HAS_PCH_SPLIT(dev)) { |
b242b7f74 drm/i915: rename ... |
801 802 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 drm/i915: HDMI ha... |
803 |
} |
7d57382e6 drm/i915: Add sup... |
804 |
} |
7d148ef51 drm/i915: fix hdm... |
805 806 807 808 809 810 |
static int hdmi_portclock_limit(struct intel_hdmi *hdmi) { struct drm_device *dev = intel_hdmi_to_dev(hdmi); if (IS_G4X(dev)) return 165000; |
e3c335786 drm/i915/bdw: Bro... |
811 |
else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) |
7d148ef51 drm/i915: fix hdm... |
812 813 814 815 |
return 300000; else return 225000; } |
7d57382e6 drm/i915: Add sup... |
816 817 818 |
static int intel_hdmi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { |
7d148ef51 drm/i915: fix hdm... |
819 |
if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector))) |
7d57382e6 drm/i915: Add sup... |
820 821 |
return MODE_CLOCK_HIGH; if (mode->clock < 20000) |
5cbba41d2 drm: i915: correc... |
822 |
return MODE_CLOCK_LOW; |
7d57382e6 drm/i915: Add sup... |
823 824 825 826 827 828 |
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; return MODE_OK; } |
5bfe2ac00 drm/i915: add pip... |
829 830 |
bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) |
7d57382e6 drm/i915: Add sup... |
831 |
{ |
5bfe2ac00 drm/i915: add pip... |
832 833 834 |
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 drm/i915: Use crt... |
835 |
int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2; |
7d148ef51 drm/i915: fix hdm... |
836 |
int portclock_limit = hdmi_portclock_limit(intel_hdmi); |
e29c22c0c drm/i915: impleme... |
837 |
int desired_bpp; |
3685a8f38 drm/i915: Fix RGB... |
838 |
|
55bc60db5 drm/i915: Add "Au... |
839 840 841 |
if (intel_hdmi->color_range_auto) { /* See CEA-861-E - 5.1 Default Encoding Parameters */ if (intel_hdmi->has_hdmi_sink && |
18316c8c3 drm: Remove dupli... |
842 |
drm_match_cea_mode(adjusted_mode) > 1) |
4f3a8bc7b drm/i915: rename ... |
843 |
intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; |
55bc60db5 drm/i915: Add "Au... |
844 845 846 |
else intel_hdmi->color_range = 0; } |
3685a8f38 drm/i915: Fix RGB... |
847 |
if (intel_hdmi->color_range) |
50f3b016b drm/i915: add pip... |
848 |
pipe_config->limited_color_range = true; |
3685a8f38 drm/i915: Fix RGB... |
849 |
|
5bfe2ac00 drm/i915: add pip... |
850 851 |
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) pipe_config->has_pch_encoder = true; |
4e53c2e01 drm/i915: precomp... |
852 853 854 |
/* * 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 drm/i915: fixup 1... |
855 856 |
* outputs. We also need to check that the higher clock still fits * within limits. |
4e53c2e01 drm/i915: precomp... |
857 |
*/ |
7d148ef51 drm/i915: fix hdm... |
858 |
if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= portclock_limit |
325b9d048 drm/i915: fixup 1... |
859 |
&& HAS_PCH_SPLIT(dev)) { |
e29c22c0c drm/i915: impleme... |
860 861 862 |
DRM_DEBUG_KMS("picking bpc to 12 for HDMI output "); desired_bpp = 12*3; |
325b9d048 drm/i915: fixup 1... |
863 864 |
/* Need to adjust the port link by 1.5x for 12bpc. */ |
ff9a6750a drm/i915: store a... |
865 |
pipe_config->port_clock = clock_12bpc; |
4e53c2e01 drm/i915: precomp... |
866 |
} else { |
e29c22c0c drm/i915: impleme... |
867 868 869 870 871 872 873 874 875 |
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 drm/i915: precomp... |
876 |
} |
241bfc389 drm/i915: Use crt... |
877 |
if (adjusted_mode->crtc_clock > portclock_limit) { |
325b9d048 drm/i915: fixup 1... |
878 879 880 881 |
DRM_DEBUG_KMS("too high HDMI clock, rejecting mode "); return false; } |
7d57382e6 drm/i915: Add sup... |
882 883 |
return true; } |
aa93d632c drm/i915: Require... |
884 |
static enum drm_connector_status |
930a9e283 drm: Use a nondes... |
885 |
intel_hdmi_detect(struct drm_connector *connector, bool force) |
9dff6af86 drm/i915: sync hd... |
886 |
{ |
b0ea7d37a drm/i915/hdmi: Re... |
887 |
struct drm_device *dev = connector->dev; |
df0e92488 drm/i915: Make th... |
888 |
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
d63885da9 drm/i915: reset i... |
889 890 891 |
struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi); struct intel_encoder *intel_encoder = &intel_dig_port->base; |
b0ea7d37a drm/i915/hdmi: Re... |
892 |
struct drm_i915_private *dev_priv = dev->dev_private; |
f899fc64c drm/i915: use GMB... |
893 |
struct edid *edid; |
aa93d632c drm/i915: Require... |
894 |
enum drm_connector_status status = connector_status_disconnected; |
9dff6af86 drm/i915: sync hd... |
895 |
|
164c85984 drm/i915: Add som... |
896 897 898 |
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] ", connector->base.id, drm_get_connector_name(connector)); |
ea5b213ad drm/i915: Subclas... |
899 |
intel_hdmi->has_hdmi_sink = false; |
2e3d6006a drm/i915: Enable ... |
900 |
intel_hdmi->has_audio = false; |
abedc077b drm/i915: Provide... |
901 |
intel_hdmi->rgb_quant_range_selectable = false; |
f899fc64c drm/i915: use GMB... |
902 |
edid = drm_get_edid(connector, |
3bd7d9093 drm/i915/intel_i2... |
903 904 |
intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); |
2ded9e274 drm/i915: hdmi de... |
905 |
|
aa93d632c drm/i915: Require... |
906 |
if (edid) { |
be9f1c4f7 Merge commit 'kei... |
907 |
if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
aa93d632c drm/i915: Require... |
908 |
status = connector_status_connected; |
b1d7e4b41 drm/i915: add a "... |
909 910 911 |
if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); |
2e3d6006a drm/i915: Enable ... |
912 |
intel_hdmi->has_audio = drm_detect_monitor_audio(edid); |
abedc077b drm/i915: Provide... |
913 914 |
intel_hdmi->rgb_quant_range_selectable = drm_rgb_quant_range_selectable(edid); |
aa93d632c drm/i915: Require... |
915 |
} |
aa93d632c drm/i915: Require... |
916 |
kfree(edid); |
9dff6af86 drm/i915: sync hd... |
917 |
} |
30ad48b73 drm/i915: Add HDM... |
918 |
|
55b7d6e8c drm/i915/hdmi: Ad... |
919 |
if (status == connector_status_connected) { |
b1d7e4b41 drm/i915: add a "... |
920 921 922 |
if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) intel_hdmi->has_audio = (intel_hdmi->force_audio == HDMI_AUDIO_ON); |
d63885da9 drm/i915: reset i... |
923 |
intel_encoder->type = INTEL_OUTPUT_HDMI; |
55b7d6e8c drm/i915/hdmi: Ad... |
924 |
} |
2ded9e274 drm/i915: hdmi de... |
925 |
return status; |
7d57382e6 drm/i915: Add sup... |
926 927 928 929 |
} static int intel_hdmi_get_modes(struct drm_connector *connector) { |
df0e92488 drm/i915: Make th... |
930 |
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
f899fc64c drm/i915: use GMB... |
931 |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
7d57382e6 drm/i915: Add sup... |
932 933 934 935 |
/* We should parse the EDID data and find out if it's an HDMI sink so * we can send audio to it. */ |
f899fc64c drm/i915: use GMB... |
936 |
return intel_ddc_get_modes(connector, |
3bd7d9093 drm/i915/intel_i2... |
937 938 |
intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); |
7d57382e6 drm/i915: Add sup... |
939 |
} |
1aad7ac04 drm/i915: Trigger... |
940 941 942 943 944 945 946 947 948 |
static bool intel_hdmi_detect_audio(struct drm_connector *connector) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct drm_i915_private *dev_priv = connector->dev->dev_private; struct edid *edid; bool has_audio = false; edid = drm_get_edid(connector, |
3bd7d9093 drm/i915/intel_i2... |
949 950 |
intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); |
1aad7ac04 drm/i915: Trigger... |
951 952 953 |
if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) has_audio = drm_detect_monitor_audio(edid); |
1aad7ac04 drm/i915: Trigger... |
954 955 956 957 958 |
kfree(edid); } return has_audio; } |
55b7d6e8c drm/i915/hdmi: Ad... |
959 960 |
static int intel_hdmi_set_property(struct drm_connector *connector, |
ed517fbbb drm/i915: small h... |
961 962 |
struct drm_property *property, uint64_t val) |
55b7d6e8c drm/i915/hdmi: Ad... |
963 964 |
{ struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
da63a9f2e drm/i915: create ... |
965 966 |
struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi); |
e953fd7bb drm/i915: Add sup... |
967 |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
55b7d6e8c drm/i915/hdmi: Ad... |
968 |
int ret; |
662595df9 drm/i915: drm_con... |
969 |
ret = drm_object_property_set_value(&connector->base, property, val); |
55b7d6e8c drm/i915/hdmi: Ad... |
970 971 |
if (ret) return ret; |
3f43c48d3 drm/i915: Share t... |
972 |
if (property == dev_priv->force_audio_property) { |
b1d7e4b41 drm/i915: add a "... |
973 |
enum hdmi_force_audio i = val; |
1aad7ac04 drm/i915: Trigger... |
974 975 976 |
bool has_audio; if (i == intel_hdmi->force_audio) |
55b7d6e8c drm/i915/hdmi: Ad... |
977 |
return 0; |
1aad7ac04 drm/i915: Trigger... |
978 |
intel_hdmi->force_audio = i; |
55b7d6e8c drm/i915/hdmi: Ad... |
979 |
|
b1d7e4b41 drm/i915: add a "... |
980 |
if (i == HDMI_AUDIO_AUTO) |
1aad7ac04 drm/i915: Trigger... |
981 982 |
has_audio = intel_hdmi_detect_audio(connector); else |
b1d7e4b41 drm/i915: add a "... |
983 |
has_audio = (i == HDMI_AUDIO_ON); |
1aad7ac04 drm/i915: Trigger... |
984 |
|
b1d7e4b41 drm/i915: add a "... |
985 986 |
if (i == HDMI_AUDIO_OFF_DVI) intel_hdmi->has_hdmi_sink = 0; |
55b7d6e8c drm/i915/hdmi: Ad... |
987 |
|
1aad7ac04 drm/i915: Trigger... |
988 |
intel_hdmi->has_audio = has_audio; |
55b7d6e8c drm/i915/hdmi: Ad... |
989 990 |
goto done; } |
e953fd7bb drm/i915: Add sup... |
991 |
if (property == dev_priv->broadcast_rgb_property) { |
ae4edb808 drm/i915: avoid f... |
992 993 |
bool old_auto = intel_hdmi->color_range_auto; uint32_t old_range = intel_hdmi->color_range; |
55bc60db5 drm/i915: Add "Au... |
994 995 996 997 998 999 1000 1001 1002 1003 |
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 drm/i915: rename ... |
1004 |
intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; |
55bc60db5 drm/i915: Add "Au... |
1005 1006 1007 1008 |
break; default: return -EINVAL; } |
ae4edb808 drm/i915: avoid f... |
1009 1010 1011 1012 |
if (old_auto == intel_hdmi->color_range_auto && old_range == intel_hdmi->color_range) return 0; |
e953fd7bb drm/i915: Add sup... |
1013 1014 |
goto done; } |
55b7d6e8c drm/i915/hdmi: Ad... |
1015 1016 1017 |
return -EINVAL; done: |
c0c36b941 drm/i915: Return ... |
1018 1019 |
if (intel_dig_port->base.base.crtc) intel_crtc_restore_mode(intel_dig_port->base.base.crtc); |
55b7d6e8c drm/i915/hdmi: Ad... |
1020 1021 1022 |
return 0; } |
9514ac6e7 drm/i915: Move so... |
1023 |
static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) |
89b667f86 drm/i915: update ... |
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 |
{ 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); int port = vlv_dport_to_channel(dport); int pipe = intel_crtc->pipe; u32 val; if (!IS_VALLEYVIEW(dev)) return; |
89b667f86 drm/i915: update ... |
1036 |
/* Enable clock channels for this port */ |
0980a60fb drm/i915: Acquire... |
1037 |
mutex_lock(&dev_priv->dpio_lock); |
5e69f97fb drm/i915: Add add... |
1038 |
val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port)); |
89b667f86 drm/i915: update ... |
1039 1040 1041 1042 1043 1044 |
val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; |
5e69f97fb drm/i915: Add add... |
1045 |
vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val); |
89b667f86 drm/i915: update ... |
1046 1047 |
/* HDMI 1.0V-2dB */ |
5e69f97fb drm/i915: Add add... |
1048 1049 |
vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0); vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), |
89b667f86 drm/i915: update ... |
1050 |
0x2b245f5f); |
5e69f97fb drm/i915: Add add... |
1051 |
vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port), |
89b667f86 drm/i915: update ... |
1052 |
0x5578b83a); |
5e69f97fb drm/i915: Add add... |
1053 |
vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), |
89b667f86 drm/i915: update ... |
1054 |
0x0c782040); |
5e69f97fb drm/i915: Add add... |
1055 |
vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port), |
89b667f86 drm/i915: update ... |
1056 |
0x2b247878); |
5e69f97fb drm/i915: Add add... |
1057 1058 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000); vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), |
89b667f86 drm/i915: update ... |
1059 |
0x00002000); |
5e69f97fb drm/i915: Add add... |
1060 |
vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), |
89b667f86 drm/i915: update ... |
1061 1062 1063 |
DPIO_TX_OCALINIT_EN); /* Program lane clock */ |
5e69f97fb drm/i915: Add add... |
1064 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), |
89b667f86 drm/i915: update ... |
1065 |
0x00760018); |
5e69f97fb drm/i915: Add add... |
1066 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), |
89b667f86 drm/i915: update ... |
1067 |
0x00400888); |
0980a60fb drm/i915: Acquire... |
1068 |
mutex_unlock(&dev_priv->dpio_lock); |
b76cf76bf drm/i915: rearran... |
1069 1070 1071 1072 |
intel_enable_hdmi(encoder); vlv_wait_port_ready(dev_priv, port); |
89b667f86 drm/i915: update ... |
1073 |
} |
9514ac6e7 drm/i915: Move so... |
1074 |
static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) |
89b667f86 drm/i915: update ... |
1075 1076 1077 1078 |
{ 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 drm/i915: Add add... |
1079 1080 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
89b667f86 drm/i915: update ... |
1081 |
int port = vlv_dport_to_channel(dport); |
5e69f97fb drm/i915: Add add... |
1082 |
int pipe = intel_crtc->pipe; |
89b667f86 drm/i915: update ... |
1083 1084 1085 |
if (!IS_VALLEYVIEW(dev)) return; |
89b667f86 drm/i915: update ... |
1086 |
/* Program Tx lane resets to default */ |
0980a60fb drm/i915: Acquire... |
1087 |
mutex_lock(&dev_priv->dpio_lock); |
5e69f97fb drm/i915: Add add... |
1088 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), |
89b667f86 drm/i915: update ... |
1089 1090 |
DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
5e69f97fb drm/i915: Add add... |
1091 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), |
89b667f86 drm/i915: update ... |
1092 1093 1094 1095 1096 1097 |
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 */ |
5e69f97fb drm/i915: Add add... |
1098 1099 1100 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00); vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500); vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000); |
89b667f86 drm/i915: update ... |
1101 |
|
5e69f97fb drm/i915: Add add... |
1102 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), |
89b667f86 drm/i915: update ... |
1103 |
0x00002000); |
5e69f97fb drm/i915: Add add... |
1104 |
vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), |
89b667f86 drm/i915: update ... |
1105 |
DPIO_TX_OCALINIT_EN); |
0980a60fb drm/i915: Acquire... |
1106 |
mutex_unlock(&dev_priv->dpio_lock); |
89b667f86 drm/i915: update ... |
1107 |
} |
9514ac6e7 drm/i915: Move so... |
1108 |
static void vlv_hdmi_post_disable(struct intel_encoder *encoder) |
89b667f86 drm/i915: update ... |
1109 1110 1111 |
{ struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
5e69f97fb drm/i915: Add add... |
1112 1113 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
89b667f86 drm/i915: update ... |
1114 |
int port = vlv_dport_to_channel(dport); |
5e69f97fb drm/i915: Add add... |
1115 |
int pipe = intel_crtc->pipe; |
89b667f86 drm/i915: update ... |
1116 1117 1118 |
/* Reset lanes to avoid HDMI flicker (VLV w/a) */ mutex_lock(&dev_priv->dpio_lock); |
5e69f97fb drm/i915: Add add... |
1119 1120 |
vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), 0x00000000); vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060); |
89b667f86 drm/i915: update ... |
1121 1122 |
mutex_unlock(&dev_priv->dpio_lock); } |
7d57382e6 drm/i915: Add sup... |
1123 1124 |
static void intel_hdmi_destroy(struct drm_connector *connector) { |
7d57382e6 drm/i915: Add sup... |
1125 |
drm_connector_cleanup(connector); |
674e2d088 drm/i915: convert... |
1126 |
kfree(connector); |
7d57382e6 drm/i915: Add sup... |
1127 |
} |
7d57382e6 drm/i915: Add sup... |
1128 |
static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
5ab432ef4 drm/i915/hdmi: co... |
1129 |
.dpms = intel_connector_dpms, |
7d57382e6 drm/i915: Add sup... |
1130 1131 |
.detect = intel_hdmi_detect, .fill_modes = drm_helper_probe_single_connector_modes, |
55b7d6e8c drm/i915/hdmi: Ad... |
1132 |
.set_property = intel_hdmi_set_property, |
7d57382e6 drm/i915: Add sup... |
1133 1134 1135 1136 1137 1138 |
.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 drm/i915: Make th... |
1139 |
.best_encoder = intel_best_encoder, |
7d57382e6 drm/i915: Add sup... |
1140 |
}; |
7d57382e6 drm/i915: Add sup... |
1141 |
static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { |
ea5b213ad drm/i915: Subclas... |
1142 |
.destroy = intel_encoder_destroy, |
7d57382e6 drm/i915: Add sup... |
1143 |
}; |
55b7d6e8c drm/i915/hdmi: Ad... |
1144 1145 1146 |
static void intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) { |
3f43c48d3 drm/i915: Share t... |
1147 |
intel_attach_force_audio_property(connector); |
e953fd7bb drm/i915: Add sup... |
1148 |
intel_attach_broadcast_rgb_property(connector); |
55bc60db5 drm/i915: Add "Au... |
1149 |
intel_hdmi->color_range_auto = true; |
55b7d6e8c drm/i915/hdmi: Ad... |
1150 |
} |
00c09d70d drm/i915: create ... |
1151 1152 |
void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector) |
7d57382e6 drm/i915: Add sup... |
1153 |
{ |
b9cb234cb drm/i915: split i... |
1154 1155 1156 1157 |
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 drm/i915: Add sup... |
1158 |
struct drm_i915_private *dev_priv = dev->dev_private; |
174edf1f8 drm/i915: add por... |
1159 |
enum port port = intel_dig_port->port; |
373a3cf74 drm/i915: call dr... |
1160 |
|
7d57382e6 drm/i915: Add sup... |
1161 |
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
8d91104aa drm/i915: Initial... |
1162 |
DRM_MODE_CONNECTOR_HDMIA); |
7d57382e6 drm/i915: Add sup... |
1163 |
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
c3febcc43 drm/i915: allow i... |
1164 |
connector->interlace_allowed = 1; |
7d57382e6 drm/i915: Add sup... |
1165 |
connector->doublescan_allowed = 0; |
573e74adb drm/i915: Allow s... |
1166 |
connector->stereo_allowed = 1; |
66a9278ee drm/i915: simplif... |
1167 |
|
08d644add drm/i915: add por... |
1168 1169 |
switch (port) { case PORT_B: |
f899fc64c drm/i915: use GMB... |
1170 |
intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
1d843f9de DRM/I915: Add enu... |
1171 |
intel_encoder->hpd_pin = HPD_PORT_B; |
08d644add drm/i915: add por... |
1172 1173 |
break; case PORT_C: |
7ceae0a55 drm/i915: add sup... |
1174 |
intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
1d843f9de DRM/I915: Add enu... |
1175 |
intel_encoder->hpd_pin = HPD_PORT_C; |
08d644add drm/i915: add por... |
1176 1177 |
break; case PORT_D: |
7ceae0a55 drm/i915: add sup... |
1178 |
intel_hdmi->ddc_bus = GMBUS_PORT_DPD; |
1d843f9de DRM/I915: Add enu... |
1179 |
intel_encoder->hpd_pin = HPD_PORT_D; |
08d644add drm/i915: add por... |
1180 1181 |
break; case PORT_A: |
1d843f9de DRM/I915: Add enu... |
1182 |
intel_encoder->hpd_pin = HPD_PORT_A; |
08d644add drm/i915: add por... |
1183 1184 |
/* Internal port only for eDP. */ default: |
6e4c1677f drm/i915: show un... |
1185 |
BUG(); |
f8aed700c drm/i915: Set crt... |
1186 |
} |
7d57382e6 drm/i915: Add sup... |
1187 |
|
7637bfdb5 drm/i915: use VLV... |
1188 |
if (IS_VALLEYVIEW(dev)) { |
90b107c8f drm/i915: Enable ... |
1189 |
intel_hdmi->write_infoframe = vlv_write_infoframe; |
687f4d06d drm/i915: add set... |
1190 |
intel_hdmi->set_infoframes = vlv_set_infoframes; |
7637bfdb5 drm/i915: use VLV... |
1191 1192 1193 |
} else if (!HAS_PCH_SPLIT(dev)) { intel_hdmi->write_infoframe = g4x_write_infoframe; intel_hdmi->set_infoframes = g4x_set_infoframes; |
22b8bf17c drm/i915: use HAS... |
1194 |
} else if (HAS_DDI(dev)) { |
8c5f5f7c4 drm/i915: add new... |
1195 |
intel_hdmi->write_infoframe = hsw_write_infoframe; |
687f4d06d drm/i915: add set... |
1196 |
intel_hdmi->set_infoframes = hsw_set_infoframes; |
fdf1250aa drm/i915: split i... |
1197 1198 |
} else if (HAS_PCH_IBX(dev)) { intel_hdmi->write_infoframe = ibx_write_infoframe; |
687f4d06d drm/i915: add set... |
1199 |
intel_hdmi->set_infoframes = ibx_set_infoframes; |
fdf1250aa drm/i915: split i... |
1200 1201 |
} else { intel_hdmi->write_infoframe = cpt_write_infoframe; |
687f4d06d drm/i915: add set... |
1202 |
intel_hdmi->set_infoframes = cpt_set_infoframes; |
64a8fc014 drm/i915: fix ILK... |
1203 |
} |
45187ace9 drm/i915/hdmi: sp... |
1204 |
|
affa93544 drm/i915: add HAS... |
1205 |
if (HAS_DDI(dev)) |
bcbc889bc drm/i915: add int... |
1206 1207 1208 |
intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; else intel_connector->get_hw_state = intel_connector_get_hw_state; |
b9cb234cb drm/i915: split i... |
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 |
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 drm/i915: rename ... |
1224 |
void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) |
b9cb234cb drm/i915: split i... |
1225 1226 1227 |
{ struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; |
b9cb234cb drm/i915: split i... |
1228 |
struct intel_connector *intel_connector; |
b14c5679d drm/i915: use poi... |
1229 |
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); |
b9cb234cb drm/i915: split i... |
1230 1231 |
if (!intel_dig_port) return; |
b14c5679d drm/i915: use poi... |
1232 |
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); |
b9cb234cb drm/i915: split i... |
1233 1234 1235 1236 1237 1238 |
if (!intel_connector) { kfree(intel_dig_port); return; } intel_encoder = &intel_dig_port->base; |
b9cb234cb drm/i915: split i... |
1239 1240 1241 |
drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS); |
00c09d70d drm/i915: create ... |
1242 |
|
5bfe2ac00 drm/i915: add pip... |
1243 |
intel_encoder->compute_config = intel_hdmi_compute_config; |
c59423a3d drm/i915/hdmi: us... |
1244 |
intel_encoder->mode_set = intel_hdmi_mode_set; |
00c09d70d drm/i915: create ... |
1245 1246 |
intel_encoder->disable = intel_disable_hdmi; intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
045ac3b56 drm/i915: add enc... |
1247 |
intel_encoder->get_config = intel_hdmi_get_config; |
89b667f86 drm/i915: update ... |
1248 |
if (IS_VALLEYVIEW(dev)) { |
9514ac6e7 drm/i915: Move so... |
1249 1250 |
intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; intel_encoder->pre_enable = vlv_hdmi_pre_enable; |
b76cf76bf drm/i915: rearran... |
1251 |
intel_encoder->enable = vlv_enable_hdmi; |
9514ac6e7 drm/i915: Move so... |
1252 |
intel_encoder->post_disable = vlv_hdmi_post_disable; |
b76cf76bf drm/i915: rearran... |
1253 1254 |
} else { intel_encoder->enable = intel_enable_hdmi; |
89b667f86 drm/i915: update ... |
1255 |
} |
5ab432ef4 drm/i915/hdmi: co... |
1256 |
|
b9cb234cb drm/i915: split i... |
1257 1258 1259 |
intel_encoder->type = INTEL_OUTPUT_HDMI; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->cloneable = false; |
7d57382e6 drm/i915: Add sup... |
1260 |
|
174edf1f8 drm/i915: add por... |
1261 |
intel_dig_port->port = port; |
b242b7f74 drm/i915: rename ... |
1262 |
intel_dig_port->hdmi.hdmi_reg = hdmi_reg; |
b9cb234cb drm/i915: split i... |
1263 |
intel_dig_port->dp.output_reg = 0; |
55b7d6e8c drm/i915/hdmi: Ad... |
1264 |
|
b9cb234cb drm/i915: split i... |
1265 |
intel_hdmi_init_connector(intel_dig_port, intel_connector); |
7d57382e6 drm/i915: Add sup... |
1266 |
} |