Blame view
drivers/gpu/drm/i915/intel_hdmi.c
39.3 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, |
a57c774ab drm/i915: Reorgan... |
111 112 |
enum transcoder cpu_transcoder, struct drm_i915_private *dev_priv) |
2da8af540 drm/i915: impleme... |
113 |
{ |
178f736ab drm/i915/hdmi: Ch... |
114 115 |
switch (type) { case HDMI_INFOFRAME_TYPE_AVI: |
7d9bcebe1 drm/i915: Use cpu... |
116 |
return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); |
178f736ab drm/i915/hdmi: Ch... |
117 |
case HDMI_INFOFRAME_TYPE_SPD: |
7d9bcebe1 drm/i915: Use cpu... |
118 |
return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); |
c8bb75aff drm/i915/hdmi: Wr... |
119 120 |
case HDMI_INFOFRAME_TYPE_VENDOR: return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder); |
2da8af540 drm/i915: impleme... |
121 |
default: |
178f736ab drm/i915/hdmi: Ch... |
122 123 |
DRM_DEBUG_DRIVER("unknown info frame type %d ", type); |
2da8af540 drm/i915: impleme... |
124 125 126 |
return 0; } } |
a3da1df7b drm/i915: s/i9xx_... |
127 |
static void g4x_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
128 |
enum hdmi_infoframe_type type, |
fff638676 drm/i915: Don't c... |
129 |
const void *frame, ssize_t len) |
45187ace9 drm/i915/hdmi: sp... |
130 |
{ |
fff638676 drm/i915: Don't c... |
131 |
const uint32_t *data = frame; |
3c17fe4b8 i915: enable AVI ... |
132 133 |
struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
22509ec86 drm/i915: change ... |
134 |
u32 val = I915_READ(VIDEO_DIP_CTL); |
178f736ab drm/i915/hdmi: Ch... |
135 |
int i; |
3c17fe4b8 i915: enable AVI ... |
136 |
|
822974aea drm/i915: enable ... |
137 138 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
1d4f85ac2 drm/i915: start w... |
139 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
140 |
val |= g4x_infoframe_index(type); |
22509ec86 drm/i915: change ... |
141 |
|
178f736ab drm/i915/hdmi: Ch... |
142 |
val &= ~g4x_infoframe_enable(type); |
45187ace9 drm/i915/hdmi: sp... |
143 |
|
22509ec86 drm/i915: change ... |
144 |
I915_WRITE(VIDEO_DIP_CTL, val); |
3c17fe4b8 i915: enable AVI ... |
145 |
|
9d9740f09 drm/i915: add som... |
146 |
mmiowb(); |
45187ace9 drm/i915/hdmi: sp... |
147 |
for (i = 0; i < len; i += 4) { |
3c17fe4b8 i915: enable AVI ... |
148 149 150 |
I915_WRITE(VIDEO_DIP_DATA, *data); data++; } |
adf00b26d 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 drm/i915: add som... |
154 |
mmiowb(); |
3c17fe4b8 i915: enable AVI ... |
155 |
|
178f736ab drm/i915/hdmi: Ch... |
156 |
val |= g4x_infoframe_enable(type); |
60c5ea2dd drm/i915: mask th... |
157 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
158 |
val |= VIDEO_DIP_FREQ_VSYNC; |
45187ace9 drm/i915/hdmi: sp... |
159 |
|
22509ec86 drm/i915: change ... |
160 |
I915_WRITE(VIDEO_DIP_CTL, val); |
9d9740f09 drm/i915: add som... |
161 |
POSTING_READ(VIDEO_DIP_CTL); |
3c17fe4b8 i915: enable AVI ... |
162 |
} |
fdf1250aa drm/i915: split i... |
163 |
static void ibx_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
164 |
enum hdmi_infoframe_type type, |
fff638676 drm/i915: Don't c... |
165 |
const void *frame, ssize_t len) |
fdf1250aa drm/i915: split i... |
166 |
{ |
fff638676 drm/i915: Don't c... |
167 |
const uint32_t *data = frame; |
fdf1250aa drm/i915: split i... |
168 169 |
struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
ed517fbbb drm/i915: small h... |
170 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
178f736ab drm/i915/hdmi: Ch... |
171 |
int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
fdf1250aa drm/i915: split i... |
172 |
u32 val = I915_READ(reg); |
822974aea drm/i915: enable ... |
173 174 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
fdf1250aa drm/i915: split i... |
175 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
176 |
val |= g4x_infoframe_index(type); |
fdf1250aa drm/i915: split i... |
177 |
|
178f736ab drm/i915/hdmi: Ch... |
178 |
val &= ~g4x_infoframe_enable(type); |
fdf1250aa drm/i915: split i... |
179 180 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
181 |
mmiowb(); |
fdf1250aa 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 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 drm/i915: add som... |
189 |
mmiowb(); |
fdf1250aa drm/i915: split i... |
190 |
|
178f736ab drm/i915/hdmi: Ch... |
191 |
val |= g4x_infoframe_enable(type); |
fdf1250aa drm/i915: split i... |
192 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
193 |
val |= VIDEO_DIP_FREQ_VSYNC; |
fdf1250aa drm/i915: split i... |
194 195 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
196 |
POSTING_READ(reg); |
fdf1250aa drm/i915: split i... |
197 198 199 |
} static void cpt_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
200 |
enum hdmi_infoframe_type type, |
fff638676 drm/i915: Don't c... |
201 |
const void *frame, ssize_t len) |
b055c8f3e drm/i915/hdmi: se... |
202 |
{ |
fff638676 drm/i915: Don't c... |
203 |
const uint32_t *data = frame; |
b055c8f3e drm/i915/hdmi: se... |
204 205 |
struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
ed517fbbb drm/i915: small h... |
206 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
178f736ab drm/i915/hdmi: Ch... |
207 |
int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
22509ec86 drm/i915: change ... |
208 |
u32 val = I915_READ(reg); |
b055c8f3e drm/i915/hdmi: se... |
209 |
|
822974aea drm/i915: enable ... |
210 211 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
64a8fc014 drm/i915: fix ILK... |
212 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
213 |
val |= g4x_infoframe_index(type); |
45187ace9 drm/i915/hdmi: sp... |
214 |
|
ecb978515 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 drm/i915/hdmi: Ch... |
217 218 |
if (type != HDMI_INFOFRAME_TYPE_AVI) val &= ~g4x_infoframe_enable(type); |
ecb978515 drm/i915: disable... |
219 |
|
22509ec86 drm/i915: change ... |
220 |
I915_WRITE(reg, val); |
45187ace9 drm/i915/hdmi: sp... |
221 |
|
9d9740f09 drm/i915: add som... |
222 |
mmiowb(); |
45187ace9 drm/i915/hdmi: sp... |
223 |
for (i = 0; i < len; i += 4) { |
b055c8f3e drm/i915/hdmi: se... |
224 225 226 |
I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } |
adf00b26d 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 drm/i915: add som... |
230 |
mmiowb(); |
b055c8f3e drm/i915/hdmi: se... |
231 |
|
178f736ab drm/i915/hdmi: Ch... |
232 |
val |= g4x_infoframe_enable(type); |
60c5ea2dd drm/i915: mask th... |
233 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
234 |
val |= VIDEO_DIP_FREQ_VSYNC; |
45187ace9 drm/i915/hdmi: sp... |
235 |
|
22509ec86 drm/i915: change ... |
236 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
237 |
POSTING_READ(reg); |
45187ace9 drm/i915/hdmi: sp... |
238 |
} |
90b107c8f drm/i915: Enable ... |
239 240 |
static void vlv_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
241 |
enum hdmi_infoframe_type type, |
fff638676 drm/i915: Don't c... |
242 |
const void *frame, ssize_t len) |
90b107c8f drm/i915: Enable ... |
243 |
{ |
fff638676 drm/i915: Don't c... |
244 |
const uint32_t *data = frame; |
90b107c8f drm/i915: Enable ... |
245 246 |
struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; |
ed517fbbb drm/i915: small h... |
247 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
178f736ab drm/i915/hdmi: Ch... |
248 |
int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
22509ec86 drm/i915: change ... |
249 |
u32 val = I915_READ(reg); |
90b107c8f drm/i915: Enable ... |
250 |
|
822974aea drm/i915: enable ... |
251 252 |
WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled "); |
90b107c8f drm/i915: Enable ... |
253 |
val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
178f736ab drm/i915/hdmi: Ch... |
254 |
val |= g4x_infoframe_index(type); |
22509ec86 drm/i915: change ... |
255 |
|
178f736ab drm/i915/hdmi: Ch... |
256 |
val &= ~g4x_infoframe_enable(type); |
90b107c8f drm/i915: Enable ... |
257 |
|
22509ec86 drm/i915: change ... |
258 |
I915_WRITE(reg, val); |
90b107c8f drm/i915: Enable ... |
259 |
|
9d9740f09 drm/i915: add som... |
260 |
mmiowb(); |
90b107c8f 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 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 drm/i915: add som... |
268 |
mmiowb(); |
90b107c8f drm/i915: Enable ... |
269 |
|
178f736ab drm/i915/hdmi: Ch... |
270 |
val |= g4x_infoframe_enable(type); |
60c5ea2dd drm/i915: mask th... |
271 |
val &= ~VIDEO_DIP_FREQ_MASK; |
4b24c9331 drm/i915: replace... |
272 |
val |= VIDEO_DIP_FREQ_VSYNC; |
90b107c8f drm/i915: Enable ... |
273 |
|
22509ec86 drm/i915: change ... |
274 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
275 |
POSTING_READ(reg); |
90b107c8f drm/i915: Enable ... |
276 |
} |
8c5f5f7c4 drm/i915: add new... |
277 |
static void hsw_write_infoframe(struct drm_encoder *encoder, |
178f736ab drm/i915/hdmi: Ch... |
278 |
enum hdmi_infoframe_type type, |
fff638676 drm/i915: Don't c... |
279 |
const void *frame, ssize_t len) |
8c5f5f7c4 drm/i915: add new... |
280 |
{ |
fff638676 drm/i915: Don't c... |
281 |
const uint32_t *data = frame; |
2da8af540 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 drm/i915: move cp... |
285 |
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
178f736ab drm/i915/hdmi: Ch... |
286 287 |
u32 data_reg; int i; |
2da8af540 drm/i915: impleme... |
288 |
u32 val = I915_READ(ctl_reg); |
8c5f5f7c4 drm/i915: add new... |
289 |
|
178f736ab drm/i915/hdmi: Ch... |
290 |
data_reg = hsw_infoframe_data_reg(type, |
a57c774ab drm/i915: Reorgan... |
291 292 |
intel_crtc->config.cpu_transcoder, dev_priv); |
2da8af540 drm/i915: impleme... |
293 294 |
if (data_reg == 0) return; |
178f736ab drm/i915/hdmi: Ch... |
295 |
val &= ~hsw_infoframe_enable(type); |
2da8af540 drm/i915: impleme... |
296 |
I915_WRITE(ctl_reg, val); |
9d9740f09 drm/i915: add som... |
297 |
mmiowb(); |
2da8af540 drm/i915: impleme... |
298 299 300 301 |
for (i = 0; i < len; i += 4) { I915_WRITE(data_reg + i, *data); data++; } |
adf00b26d 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 drm/i915: add som... |
305 |
mmiowb(); |
8c5f5f7c4 drm/i915: add new... |
306 |
|
178f736ab drm/i915/hdmi: Ch... |
307 |
val |= hsw_infoframe_enable(type); |
2da8af540 drm/i915: impleme... |
308 |
I915_WRITE(ctl_reg, val); |
9d9740f09 drm/i915: add som... |
309 |
POSTING_READ(ctl_reg); |
8c5f5f7c4 drm/i915: add new... |
310 |
} |
5adaea799 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 drm/i915/hmdi: Re... |
328 329 |
static void intel_write_infoframe(struct drm_encoder *encoder, union hdmi_infoframe *frame) |
45187ace9 drm/i915/hdmi: sp... |
330 331 |
{ struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
5adaea799 drm/i915/hdmi: Po... |
332 333 |
uint8_t buffer[VIDEO_DIP_DATA_SIZE]; ssize_t len; |
45187ace9 drm/i915/hdmi: sp... |
334 |
|
5adaea799 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 drm/i915/hdmi: sp... |
346 |
|
5adaea799 drm/i915/hdmi: Po... |
347 |
intel_hdmi->write_infoframe(encoder, frame->any.type, buffer, len); |
45187ace9 drm/i915/hdmi: sp... |
348 |
} |
687f4d06d drm/i915: add set... |
349 |
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |
c846b6194 drm/i915: make DB... |
350 |
struct drm_display_mode *adjusted_mode) |
45187ace9 drm/i915/hdmi: sp... |
351 |
{ |
abedc077b drm/i915: Provide... |
352 |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
50f3b016b drm/i915: add pip... |
353 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
5adaea799 drm/i915/hdmi: Po... |
354 355 |
union hdmi_infoframe frame; int ret; |
45187ace9 drm/i915/hdmi: sp... |
356 |
|
5adaea799 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 drm/i915: make DB... |
364 |
|
abedc077b drm/i915: Provide... |
365 |
if (intel_hdmi->rgb_quant_range_selectable) { |
50f3b016b drm/i915: add pip... |
366 |
if (intel_crtc->config.limited_color_range) |
5adaea799 drm/i915/hdmi: Po... |
367 368 |
frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED; |
abedc077b drm/i915: Provide... |
369 |
else |
5adaea799 drm/i915/hdmi: Po... |
370 371 |
frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL; |
abedc077b drm/i915: Provide... |
372 |
} |
9198ee5b9 drm/i915/hmdi: Re... |
373 |
intel_write_infoframe(encoder, &frame); |
b055c8f3e drm/i915/hdmi: se... |
374 |
} |
687f4d06d drm/i915: add set... |
375 |
static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) |
c0864cb39 drm/i915/hdmi: HD... |
376 |
{ |
5adaea799 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 drm/i915/hdmi: HD... |
386 |
|
5adaea799 drm/i915/hdmi: Po... |
387 |
frame.spd.sdi = HDMI_SPD_SDI_PC; |
c0864cb39 drm/i915/hdmi: HD... |
388 |
|
9198ee5b9 drm/i915/hmdi: Re... |
389 |
intel_write_infoframe(encoder, &frame); |
c0864cb39 drm/i915/hdmi: HD... |
390 |
} |
c8bb75aff 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 drm/i915: add set... |
405 406 407 |
static void g4x_set_infoframes(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { |
0c14c7f95 drm/i915: properl... |
408 |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
69fde0a61 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 drm/i915: properl... |
411 412 |
u32 reg = VIDEO_DIP_CTL; u32 val = I915_READ(reg); |
822cdc529 drm/i915: Convert... |
413 |
u32 port = VIDEO_DIP_PORT(intel_dig_port->port); |
0c14c7f95 drm/i915: properl... |
414 |
|
afba01889 drm/i915: ensure ... |
415 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 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 drm/i915: add som... |
432 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
433 434 |
return; } |
72b78c9d1 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 drm/i915: add som... |
439 |
POSTING_READ(reg); |
72b78c9d1 drm/i915: disable... |
440 441 442 443 |
} val &= ~VIDEO_DIP_PORT_MASK; val |= port; } |
822974aea drm/i915: enable ... |
444 |
val |= VIDEO_DIP_ENABLE; |
0dd87d208 drm/i915: explici... |
445 |
val &= ~VIDEO_DIP_ENABLE_VENDOR; |
822974aea drm/i915: enable ... |
446 |
|
f278d9721 drm/i915: only se... |
447 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
448 |
POSTING_READ(reg); |
f278d9721 drm/i915: only se... |
449 |
|
687f4d06d drm/i915: add set... |
450 451 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
452 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d 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 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 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 drm/i915: properl... |
462 463 |
u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); u32 val = I915_READ(reg); |
822cdc529 drm/i915: Convert... |
464 |
u32 port = VIDEO_DIP_PORT(intel_dig_port->port); |
0c14c7f95 drm/i915: properl... |
465 |
|
afba01889 drm/i915: ensure ... |
466 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 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 drm/i915: add som... |
475 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
476 477 |
return; } |
72b78c9d1 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 drm/i915: add som... |
482 |
POSTING_READ(reg); |
72b78c9d1 drm/i915: disable... |
483 484 485 486 |
} val &= ~VIDEO_DIP_PORT_MASK; val |= port; } |
822974aea drm/i915: enable ... |
487 |
val |= VIDEO_DIP_ENABLE; |
0dd87d208 drm/i915: explici... |
488 489 |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); |
822974aea drm/i915: enable ... |
490 |
|
f278d9721 drm/i915: only se... |
491 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
492 |
POSTING_READ(reg); |
f278d9721 drm/i915: only se... |
493 |
|
687f4d06d drm/i915: add set... |
494 495 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
496 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d 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 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 drm/i915: ensure ... |
507 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 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 drm/i915: add som... |
516 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
517 518 |
return; } |
822974aea drm/i915: enable ... |
519 520 |
/* Set both together, unset both together: see the spec. */ val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; |
0dd87d208 drm/i915: explici... |
521 522 |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); |
822974aea drm/i915: enable ... |
523 524 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
525 |
POSTING_READ(reg); |
822974aea drm/i915: enable ... |
526 |
|
687f4d06d drm/i915: add set... |
527 528 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
529 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d 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 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 drm/i915: ensure ... |
540 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 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 drm/i915: add som... |
549 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
550 551 |
return; } |
822974aea drm/i915: enable ... |
552 |
val |= VIDEO_DIP_ENABLE; |
0dd87d208 drm/i915: explici... |
553 554 |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); |
822974aea drm/i915: enable ... |
555 556 |
I915_WRITE(reg, val); |
9d9740f09 drm/i915: add som... |
557 |
POSTING_READ(reg); |
822974aea drm/i915: enable ... |
558 |
|
687f4d06d drm/i915: add set... |
559 560 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
561 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d 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 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 drm/i915: move cp... |
570 |
u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
0dd87d208 drm/i915: explici... |
571 |
u32 val = I915_READ(reg); |
0c14c7f95 drm/i915: properl... |
572 |
|
afba01889 drm/i915: ensure ... |
573 |
assert_hdmi_port_disabled(intel_hdmi); |
0c14c7f95 drm/i915: properl... |
574 575 |
if (!intel_hdmi->has_hdmi_sink) { I915_WRITE(reg, 0); |
9d9740f09 drm/i915: add som... |
576 |
POSTING_READ(reg); |
0c14c7f95 drm/i915: properl... |
577 578 |
return; } |
0dd87d208 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 drm/i915: add som... |
583 |
POSTING_READ(reg); |
0dd87d208 drm/i915: explici... |
584 |
|
687f4d06d drm/i915: add set... |
585 586 |
intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); intel_hdmi_set_spd_infoframe(encoder); |
c8bb75aff drm/i915/hdmi: Wr... |
587 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
687f4d06d drm/i915: add set... |
588 |
} |
c59423a3d drm/i915/hdmi: us... |
589 |
static void intel_hdmi_mode_set(struct intel_encoder *encoder) |
7d57382e6 drm/i915: Add sup... |
590 |
{ |
c59423a3d drm/i915/hdmi: us... |
591 |
struct drm_device *dev = encoder->base.dev; |
7d57382e6 drm/i915: Add sup... |
592 |
struct drm_i915_private *dev_priv = dev->dev_private; |
c59423a3d 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 drm/i915: rename ... |
596 |
u32 hdmi_val; |
7d57382e6 drm/i915: Add sup... |
597 |
|
b242b7f74 drm/i915: rename ... |
598 |
hdmi_val = SDVO_ENCODING_HDMI; |
2af2c4909 Revert "drm/i915:... |
599 |
if (!HAS_PCH_SPLIT(dev)) |
b242b7f74 drm/i915: rename ... |
600 |
hdmi_val |= intel_hdmi->color_range; |
b599c0bca drm/i915/hdmi: Se... |
601 |
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
b242b7f74 drm/i915: rename ... |
602 |
hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; |
b599c0bca drm/i915/hdmi: Se... |
603 |
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
b242b7f74 drm/i915: rename ... |
604 |
hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH; |
7d57382e6 drm/i915: Add sup... |
605 |
|
c59423a3d drm/i915/hdmi: us... |
606 |
if (crtc->config.pipe_bpp > 24) |
4f3a8bc7b drm/i915: rename ... |
607 |
hdmi_val |= HDMI_COLOR_FORMAT_12bpc; |
020f6704b drm/i915: use pip... |
608 |
else |
4f3a8bc7b drm/i915: rename ... |
609 |
hdmi_val |= SDVO_COLOR_FORMAT_8bpc; |
020f6704b drm/i915: use pip... |
610 |
|
2e3d6006a drm/i915: Enable ... |
611 612 |
/* Required on CPT */ if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) |
dc0fa7181 drm/i915: remove ... |
613 |
hdmi_val |= HDMI_MODE_SELECT_HDMI; |
2e3d6006a drm/i915: Enable ... |
614 |
|
3c17fe4b8 i915: enable AVI ... |
615 |
if (intel_hdmi->has_audio) { |
e0dac65ed drm/i915: pass EL... |
616 617 |
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c ", |
c59423a3d drm/i915/hdmi: us... |
618 |
pipe_name(crtc->pipe)); |
b242b7f74 drm/i915: rename ... |
619 |
hdmi_val |= SDVO_AUDIO_ENABLE; |
dc0fa7181 drm/i915: remove ... |
620 |
hdmi_val |= HDMI_MODE_SELECT_HDMI; |
c59423a3d drm/i915/hdmi: us... |
621 |
intel_write_eld(&encoder->base, adjusted_mode); |
3c17fe4b8 i915: enable AVI ... |
622 |
} |
7d57382e6 drm/i915: Add sup... |
623 |
|
75770564c drm/i915: use tra... |
624 |
if (HAS_PCH_CPT(dev)) |
c59423a3d drm/i915/hdmi: us... |
625 |
hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); |
dc0fa7181 drm/i915: remove ... |
626 |
else |
c59423a3d drm/i915/hdmi: us... |
627 |
hdmi_val |= SDVO_PIPE_SEL(crtc->pipe); |
7d57382e6 drm/i915: Add sup... |
628 |
|
b242b7f74 drm/i915: rename ... |
629 630 |
I915_WRITE(intel_hdmi->hdmi_reg, hdmi_val); POSTING_READ(intel_hdmi->hdmi_reg); |
3c17fe4b8 i915: enable AVI ... |
631 |
|
c59423a3d drm/i915/hdmi: us... |
632 |
intel_hdmi->set_infoframes(&encoder->base, adjusted_mode); |
7d57382e6 drm/i915: Add sup... |
633 |
} |
85234cdc2 drm/i915/hdmi: im... |
634 635 |
static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) |
7d57382e6 drm/i915: Add sup... |
636 |
{ |
85234cdc2 drm/i915/hdmi: im... |
637 |
struct drm_device *dev = encoder->base.dev; |
7d57382e6 drm/i915: Add sup... |
638 |
struct drm_i915_private *dev_priv = dev->dev_private; |
85234cdc2 drm/i915/hdmi: im... |
639 |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
6d129beac drm/i915: check p... |
640 |
enum intel_display_power_domain power_domain; |
85234cdc2 drm/i915/hdmi: im... |
641 |
u32 tmp; |
6d129beac 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 drm/i915: rename ... |
645 |
tmp = I915_READ(intel_hdmi->hdmi_reg); |
85234cdc2 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 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 drm/i915: Fix por... |
663 |
int dotclock; |
045ac3b56 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 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 drm/i915: Use crt... |
686 |
pipe_config->adjusted_mode.crtc_clock = dotclock; |
045ac3b56 drm/i915: add enc... |
687 |
} |
5ab432ef4 drm/i915/hdmi: co... |
688 |
static void intel_enable_hdmi(struct intel_encoder *encoder) |
7d57382e6 drm/i915: Add sup... |
689 |
{ |
5ab432ef4 drm/i915/hdmi: co... |
690 |
struct drm_device *dev = encoder->base.dev; |
7d57382e6 drm/i915: Add sup... |
691 |
struct drm_i915_private *dev_priv = dev->dev_private; |
dc0fa7181 drm/i915: remove ... |
692 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
5ab432ef4 drm/i915/hdmi: co... |
693 |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
7d57382e6 drm/i915: Add sup... |
694 |
u32 temp; |
2deed7611 drm/i915: HDMI ho... |
695 696 697 698 |
u32 enable_bits = SDVO_ENABLE; if (intel_hdmi->has_audio) enable_bits |= SDVO_AUDIO_ENABLE; |
7d57382e6 drm/i915: Add sup... |
699 |
|
b242b7f74 drm/i915: rename ... |
700 |
temp = I915_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 drm/i915: HDMI ha... |
701 |
|
7a87c2897 drm/i915: impleme... |
702 |
/* HW workaround for IBX, we need to move the port to transcoder A |
dc0fa7181 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 drm/i915: impleme... |
706 |
|
d8a2d0e00 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 drm/i915: More s/... |
710 |
if (HAS_PCH_SPLIT(dev)) { |
b242b7f74 drm/i915: rename ... |
711 712 |
I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE); POSTING_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 drm/i915: HDMI ha... |
713 |
} |
5ab432ef4 drm/i915/hdmi: co... |
714 |
temp |= enable_bits; |
b242b7f74 drm/i915: rename ... |
715 716 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 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 drm/i915: rename ... |
722 723 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
7d57382e6 drm/i915: Add sup... |
724 |
} |
b76cf76bf drm/i915: rearran... |
725 |
} |
89b667f86 drm/i915: update ... |
726 |
|
b76cf76bf drm/i915: rearran... |
727 728 |
static void vlv_enable_hdmi(struct intel_encoder *encoder) { |
5ab432ef4 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 drm/i915: HDMI - ... |
737 |
u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; |
5ab432ef4 drm/i915/hdmi: co... |
738 |
|
b242b7f74 drm/i915: rename ... |
739 |
temp = I915_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 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 drm/i915: rename ... |
749 750 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 drm/i915/hdmi: co... |
751 752 |
/* Again we need to write this twice. */ |
b242b7f74 drm/i915: rename ... |
753 754 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 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 drm/i915: Add sup... |
763 |
} |
d8a2d0e00 drm/i915: HDMI ha... |
764 |
|
5ab432ef4 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 drm/i915: rename ... |
769 770 |
I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE); POSTING_READ(intel_hdmi->hdmi_reg); |
5ab432ef4 drm/i915/hdmi: co... |
771 772 773 |
} temp &= ~enable_bits; |
d8a2d0e00 drm/i915: HDMI ha... |
774 |
|
b242b7f74 drm/i915: rename ... |
775 776 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 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 drm/i915: More s/... |
781 |
if (HAS_PCH_SPLIT(dev)) { |
b242b7f74 drm/i915: rename ... |
782 783 |
I915_WRITE(intel_hdmi->hdmi_reg, temp); POSTING_READ(intel_hdmi->hdmi_reg); |
d8a2d0e00 drm/i915: HDMI ha... |
784 |
} |
7d57382e6 drm/i915: Add sup... |
785 |
} |
40478455f drm/i915: Allow u... |
786 |
static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit) |
7d148ef51 drm/i915: fix hdm... |
787 788 |
{ struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
40478455f drm/i915: Allow u... |
789 |
if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev)) |
7d148ef51 drm/i915: fix hdm... |
790 |
return 165000; |
e3c335786 drm/i915/bdw: Bro... |
791 |
else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) |
7d148ef51 drm/i915: fix hdm... |
792 793 794 795 |
return 300000; else return 225000; } |
c19de8eb6 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 drm/i915: Add sup... |
799 |
{ |
40478455f drm/i915: Allow u... |
800 801 |
if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector), true)) |
7d57382e6 drm/i915: Add sup... |
802 803 |
return MODE_CLOCK_HIGH; if (mode->clock < 20000) |
5cbba41d2 drm: i915: correc... |
804 |
return MODE_CLOCK_LOW; |
7d57382e6 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 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 drm/i915: add pip... |
834 835 |
bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) |
7d57382e6 drm/i915: Add sup... |
836 |
{ |
5bfe2ac00 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 drm/i915: Use crt... |
840 |
int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2; |
40478455f drm/i915: Allow u... |
841 |
int portclock_limit = hdmi_portclock_limit(intel_hdmi, false); |
e29c22c0c drm/i915: impleme... |
842 |
int desired_bpp; |
3685a8f38 drm/i915: Fix RGB... |
843 |
|
55bc60db5 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 drm: Remove dupli... |
847 |
drm_match_cea_mode(adjusted_mode) > 1) |
4f3a8bc7b drm/i915: rename ... |
848 |
intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; |
55bc60db5 drm/i915: Add "Au... |
849 850 851 |
else intel_hdmi->color_range = 0; } |
3685a8f38 drm/i915: Fix RGB... |
852 |
if (intel_hdmi->color_range) |
50f3b016b drm/i915: add pip... |
853 |
pipe_config->limited_color_range = true; |
3685a8f38 drm/i915: Fix RGB... |
854 |
|
5bfe2ac00 drm/i915: add pip... |
855 856 |
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) pipe_config->has_pch_encoder = true; |
4e53c2e01 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 drm/i915: fixup 1... |
860 861 |
* outputs. We also need to check that the higher clock still fits * within limits. |
4e53c2e01 drm/i915: precomp... |
862 |
*/ |
6375b768a drm/i915: Reject ... |
863 |
if (pipe_config->pipe_bpp > 8*3 && intel_hdmi->has_hdmi_sink && |
718006329 drm/i915: Don't u... |
864 865 |
clock_12bpc <= portclock_limit && hdmi_12bpc_possible(encoder->new_crtc)) { |
e29c22c0c drm/i915: impleme... |
866 867 868 |
DRM_DEBUG_KMS("picking bpc to 12 for HDMI output "); desired_bpp = 12*3; |
325b9d048 drm/i915: fixup 1... |
869 870 |
/* Need to adjust the port link by 1.5x for 12bpc. */ |
ff9a6750a drm/i915: store a... |
871 |
pipe_config->port_clock = clock_12bpc; |
4e53c2e01 drm/i915: precomp... |
872 |
} else { |
e29c22c0c 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 drm/i915: precomp... |
882 |
} |
241bfc389 drm/i915: Use crt... |
883 |
if (adjusted_mode->crtc_clock > portclock_limit) { |
325b9d048 drm/i915: fixup 1... |
884 885 886 887 |
DRM_DEBUG_KMS("too high HDMI clock, rejecting mode "); return false; } |
7d57382e6 drm/i915: Add sup... |
888 889 |
return true; } |
aa93d632c drm/i915: Require... |
890 |
static enum drm_connector_status |
930a9e283 drm: Use a nondes... |
891 |
intel_hdmi_detect(struct drm_connector *connector, bool force) |
9dff6af86 drm/i915: sync hd... |
892 |
{ |
b0ea7d37a drm/i915/hdmi: Re... |
893 |
struct drm_device *dev = connector->dev; |
df0e92488 drm/i915: Make th... |
894 |
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
d63885da9 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 drm/i915/hdmi: Re... |
898 |
struct drm_i915_private *dev_priv = dev->dev_private; |
f899fc64c drm/i915: use GMB... |
899 |
struct edid *edid; |
671dedd21 drm/i915: get por... |
900 |
enum intel_display_power_domain power_domain; |
aa93d632c drm/i915: Require... |
901 |
enum drm_connector_status status = connector_status_disconnected; |
9dff6af86 drm/i915: sync hd... |
902 |
|
164c85984 drm/i915: Add som... |
903 904 905 |
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] ", connector->base.id, drm_get_connector_name(connector)); |
671dedd21 drm/i915: get por... |
906 907 |
power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); |
ea5b213ad drm/i915: Subclas... |
908 |
intel_hdmi->has_hdmi_sink = false; |
2e3d6006a drm/i915: Enable ... |
909 |
intel_hdmi->has_audio = false; |
abedc077b drm/i915: Provide... |
910 |
intel_hdmi->rgb_quant_range_selectable = false; |
f899fc64c drm/i915: use GMB... |
911 |
edid = drm_get_edid(connector, |
3bd7d9093 drm/i915/intel_i2... |
912 913 |
intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); |
2ded9e274 drm/i915: hdmi de... |
914 |
|
aa93d632c drm/i915: Require... |
915 |
if (edid) { |
be9f1c4f7 Merge commit 'kei... |
916 |
if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
aa93d632c drm/i915: Require... |
917 |
status = connector_status_connected; |
b1d7e4b41 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 drm/i915: Enable ... |
921 |
intel_hdmi->has_audio = drm_detect_monitor_audio(edid); |
abedc077b drm/i915: Provide... |
922 923 |
intel_hdmi->rgb_quant_range_selectable = drm_rgb_quant_range_selectable(edid); |
aa93d632c drm/i915: Require... |
924 |
} |
aa93d632c drm/i915: Require... |
925 |
kfree(edid); |
9dff6af86 drm/i915: sync hd... |
926 |
} |
30ad48b73 drm/i915: Add HDM... |
927 |
|
55b7d6e8c drm/i915/hdmi: Ad... |
928 |
if (status == connector_status_connected) { |
b1d7e4b41 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 drm/i915: reset i... |
932 |
intel_encoder->type = INTEL_OUTPUT_HDMI; |
55b7d6e8c drm/i915/hdmi: Ad... |
933 |
} |
671dedd21 drm/i915: get por... |
934 |
intel_display_power_put(dev_priv, power_domain); |
2ded9e274 drm/i915: hdmi de... |
935 |
return status; |
7d57382e6 drm/i915: Add sup... |
936 937 938 939 |
} static int intel_hdmi_get_modes(struct drm_connector *connector) { |
671dedd21 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 drm/i915: use GMB... |
942 |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
671dedd21 drm/i915: get por... |
943 944 |
enum intel_display_power_domain power_domain; int ret; |
7d57382e6 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 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 drm/i915/intel_i2... |
953 954 |
intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); |
671dedd21 drm/i915: get por... |
955 956 957 958 |
intel_display_power_put(dev_priv, power_domain); return ret; |
7d57382e6 drm/i915: Add sup... |
959 |
} |
1aad7ac04 drm/i915: Trigger... |
960 961 962 |
static bool intel_hdmi_detect_audio(struct drm_connector *connector) { |
671dedd21 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 drm/i915: Trigger... |
965 |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
671dedd21 drm/i915: get por... |
966 |
enum intel_display_power_domain power_domain; |
1aad7ac04 drm/i915: Trigger... |
967 968 |
struct edid *edid; bool has_audio = false; |
671dedd21 drm/i915: get por... |
969 970 |
power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); |
1aad7ac04 drm/i915: Trigger... |
971 |
edid = drm_get_edid(connector, |
3bd7d9093 drm/i915/intel_i2... |
972 973 |
intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); |
1aad7ac04 drm/i915: Trigger... |
974 975 976 |
if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) has_audio = drm_detect_monitor_audio(edid); |
1aad7ac04 drm/i915: Trigger... |
977 978 |
kfree(edid); } |
671dedd21 drm/i915: get por... |
979 |
intel_display_power_put(dev_priv, power_domain); |
1aad7ac04 drm/i915: Trigger... |
980 981 |
return has_audio; } |
55b7d6e8c drm/i915/hdmi: Ad... |
982 983 |
static int intel_hdmi_set_property(struct drm_connector *connector, |
ed517fbbb drm/i915: small h... |
984 985 |
struct drm_property *property, uint64_t val) |
55b7d6e8c drm/i915/hdmi: Ad... |
986 987 |
{ struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
da63a9f2e drm/i915: create ... |
988 989 |
struct intel_digital_port *intel_dig_port = hdmi_to_dig_port(intel_hdmi); |
e953fd7bb drm/i915: Add sup... |
990 |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
55b7d6e8c drm/i915/hdmi: Ad... |
991 |
int ret; |
662595df9 drm/i915: drm_con... |
992 |
ret = drm_object_property_set_value(&connector->base, property, val); |
55b7d6e8c drm/i915/hdmi: Ad... |
993 994 |
if (ret) return ret; |
3f43c48d3 drm/i915: Share t... |
995 |
if (property == dev_priv->force_audio_property) { |
b1d7e4b41 drm/i915: add a "... |
996 |
enum hdmi_force_audio i = val; |
1aad7ac04 drm/i915: Trigger... |
997 998 999 |
bool has_audio; if (i == intel_hdmi->force_audio) |
55b7d6e8c drm/i915/hdmi: Ad... |
1000 |
return 0; |
1aad7ac04 drm/i915: Trigger... |
1001 |
intel_hdmi->force_audio = i; |
55b7d6e8c drm/i915/hdmi: Ad... |
1002 |
|
b1d7e4b41 drm/i915: add a "... |
1003 |
if (i == HDMI_AUDIO_AUTO) |
1aad7ac04 drm/i915: Trigger... |
1004 1005 |
has_audio = intel_hdmi_detect_audio(connector); else |
b1d7e4b41 drm/i915: add a "... |
1006 |
has_audio = (i == HDMI_AUDIO_ON); |
1aad7ac04 drm/i915: Trigger... |
1007 |
|
b1d7e4b41 drm/i915: add a "... |
1008 1009 |
if (i == HDMI_AUDIO_OFF_DVI) intel_hdmi->has_hdmi_sink = 0; |
55b7d6e8c drm/i915/hdmi: Ad... |
1010 |
|
1aad7ac04 drm/i915: Trigger... |
1011 |
intel_hdmi->has_audio = has_audio; |
55b7d6e8c drm/i915/hdmi: Ad... |
1012 1013 |
goto done; } |
e953fd7bb drm/i915: Add sup... |
1014 |
if (property == dev_priv->broadcast_rgb_property) { |
ae4edb808 drm/i915: avoid f... |
1015 1016 |
bool old_auto = intel_hdmi->color_range_auto; uint32_t old_range = intel_hdmi->color_range; |
55bc60db5 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 drm/i915: rename ... |
1027 |
intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; |
55bc60db5 drm/i915: Add "Au... |
1028 1029 1030 1031 |
break; default: return -EINVAL; } |
ae4edb808 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 drm/i915: Add sup... |
1036 1037 |
goto done; } |
55b7d6e8c drm/i915/hdmi: Ad... |
1038 1039 1040 |
return -EINVAL; done: |
c0c36b941 drm/i915: Return ... |
1041 1042 |
if (intel_dig_port->base.base.crtc) intel_crtc_restore_mode(intel_dig_port->base.base.crtc); |
55b7d6e8c drm/i915/hdmi: Ad... |
1043 1044 1045 |
return 0; } |
9514ac6e7 drm/i915: Move so... |
1046 |
static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) |
89b667f86 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 drm/i915/vlv: Mak... |
1053 |
enum dpio_channel port = vlv_dport_to_channel(dport); |
89b667f86 drm/i915: update ... |
1054 1055 1056 1057 1058 |
int pipe = intel_crtc->pipe; u32 val; if (!IS_VALLEYVIEW(dev)) return; |
89b667f86 drm/i915: update ... |
1059 |
/* Enable clock channels for this port */ |
0980a60fb drm/i915: Acquire... |
1060 |
mutex_lock(&dev_priv->dpio_lock); |
ab3c759a0 drm/i915/vlv: Ren... |
1061 |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port)); |
89b667f86 drm/i915: update ... |
1062 1063 1064 1065 1066 1067 |
val = 0; if (pipe) val |= (1<<21); else val &= ~(1<<21); val |= 0x001000c4; |
ab3c759a0 drm/i915/vlv: Ren... |
1068 |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val); |
89b667f86 drm/i915: update ... |
1069 1070 |
/* HDMI 1.0V-2dB */ |
ab3c759a0 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 drm/i915: update ... |
1079 1080 |
/* Program lane clock */ |
ab3c759a0 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 drm/i915: Acquire... |
1083 |
mutex_unlock(&dev_priv->dpio_lock); |
b76cf76bf drm/i915: rearran... |
1084 1085 |
intel_enable_hdmi(encoder); |
e4607fcfb drm/i915/vlv: Mak... |
1086 |
vlv_wait_port_ready(dev_priv, dport); |
89b667f86 drm/i915: update ... |
1087 |
} |
9514ac6e7 drm/i915: Move so... |
1088 |
static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) |
89b667f86 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 drm/i915: Add add... |
1093 1094 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
e4607fcfb drm/i915/vlv: Mak... |
1095 |
enum dpio_channel port = vlv_dport_to_channel(dport); |
5e69f97fb drm/i915: Add add... |
1096 |
int pipe = intel_crtc->pipe; |
89b667f86 drm/i915: update ... |
1097 1098 1099 |
if (!IS_VALLEYVIEW(dev)) return; |
89b667f86 drm/i915: update ... |
1100 |
/* Program Tx lane resets to default */ |
0980a60fb drm/i915: Acquire... |
1101 |
mutex_lock(&dev_priv->dpio_lock); |
ab3c759a0 drm/i915/vlv: Ren... |
1102 |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), |
89b667f86 drm/i915: update ... |
1103 1104 |
DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
ab3c759a0 drm/i915/vlv: Ren... |
1105 |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), |
89b667f86 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 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 drm/i915: Acquire... |
1118 |
mutex_unlock(&dev_priv->dpio_lock); |
89b667f86 drm/i915: update ... |
1119 |
} |
9514ac6e7 drm/i915: Move so... |
1120 |
static void vlv_hdmi_post_disable(struct intel_encoder *encoder) |
89b667f86 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 drm/i915: Add add... |
1124 1125 |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
e4607fcfb drm/i915/vlv: Mak... |
1126 |
enum dpio_channel port = vlv_dport_to_channel(dport); |
5e69f97fb drm/i915: Add add... |
1127 |
int pipe = intel_crtc->pipe; |
89b667f86 drm/i915: update ... |
1128 1129 1130 |
/* Reset lanes to avoid HDMI flicker (VLV w/a) */ mutex_lock(&dev_priv->dpio_lock); |
ab3c759a0 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 drm/i915: update ... |
1133 1134 |
mutex_unlock(&dev_priv->dpio_lock); } |
7d57382e6 drm/i915: Add sup... |
1135 1136 |
static void intel_hdmi_destroy(struct drm_connector *connector) { |
7d57382e6 drm/i915: Add sup... |
1137 |
drm_connector_cleanup(connector); |
674e2d088 drm/i915: convert... |
1138 |
kfree(connector); |
7d57382e6 drm/i915: Add sup... |
1139 |
} |
7d57382e6 drm/i915: Add sup... |
1140 |
static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
5ab432ef4 drm/i915/hdmi: co... |
1141 |
.dpms = intel_connector_dpms, |
7d57382e6 drm/i915: Add sup... |
1142 1143 |
.detect = intel_hdmi_detect, .fill_modes = drm_helper_probe_single_connector_modes, |
55b7d6e8c drm/i915/hdmi: Ad... |
1144 |
.set_property = intel_hdmi_set_property, |
7d57382e6 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 drm/i915: Make th... |
1151 |
.best_encoder = intel_best_encoder, |
7d57382e6 drm/i915: Add sup... |
1152 |
}; |
7d57382e6 drm/i915: Add sup... |
1153 |
static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { |
ea5b213ad drm/i915: Subclas... |
1154 |
.destroy = intel_encoder_destroy, |
7d57382e6 drm/i915: Add sup... |
1155 |
}; |
55b7d6e8c drm/i915/hdmi: Ad... |
1156 1157 1158 |
static void intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) { |
3f43c48d3 drm/i915: Share t... |
1159 |
intel_attach_force_audio_property(connector); |
e953fd7bb drm/i915: Add sup... |
1160 |
intel_attach_broadcast_rgb_property(connector); |
55bc60db5 drm/i915: Add "Au... |
1161 |
intel_hdmi->color_range_auto = true; |
55b7d6e8c drm/i915/hdmi: Ad... |
1162 |
} |
00c09d70d drm/i915: create ... |
1163 1164 |
void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector) |
7d57382e6 drm/i915: Add sup... |
1165 |
{ |
b9cb234cb 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 drm/i915: Add sup... |
1170 |
struct drm_i915_private *dev_priv = dev->dev_private; |
174edf1f8 drm/i915: add por... |
1171 |
enum port port = intel_dig_port->port; |
373a3cf74 drm/i915: call dr... |
1172 |
|
7d57382e6 drm/i915: Add sup... |
1173 |
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
8d91104aa drm/i915: Initial... |
1174 |
DRM_MODE_CONNECTOR_HDMIA); |
7d57382e6 drm/i915: Add sup... |
1175 |
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
c3febcc43 drm/i915: allow i... |
1176 |
connector->interlace_allowed = 1; |
7d57382e6 drm/i915: Add sup... |
1177 |
connector->doublescan_allowed = 0; |
573e74adb drm/i915: Allow s... |
1178 |
connector->stereo_allowed = 1; |
66a9278ee drm/i915: simplif... |
1179 |
|
08d644add drm/i915: add por... |
1180 1181 |
switch (port) { case PORT_B: |
f899fc64c drm/i915: use GMB... |
1182 |
intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
1d843f9de DRM/I915: Add enu... |
1183 |
intel_encoder->hpd_pin = HPD_PORT_B; |
08d644add drm/i915: add por... |
1184 1185 |
break; case PORT_C: |
7ceae0a55 drm/i915: add sup... |
1186 |
intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
1d843f9de DRM/I915: Add enu... |
1187 |
intel_encoder->hpd_pin = HPD_PORT_C; |
08d644add drm/i915: add por... |
1188 1189 |
break; case PORT_D: |
7ceae0a55 drm/i915: add sup... |
1190 |
intel_hdmi->ddc_bus = GMBUS_PORT_DPD; |
1d843f9de DRM/I915: Add enu... |
1191 |
intel_encoder->hpd_pin = HPD_PORT_D; |
08d644add drm/i915: add por... |
1192 1193 |
break; case PORT_A: |
1d843f9de DRM/I915: Add enu... |
1194 |
intel_encoder->hpd_pin = HPD_PORT_A; |
08d644add drm/i915: add por... |
1195 1196 |
/* Internal port only for eDP. */ default: |
6e4c1677f drm/i915: show un... |
1197 |
BUG(); |
f8aed700c drm/i915: Set crt... |
1198 |
} |
7d57382e6 drm/i915: Add sup... |
1199 |
|
7637bfdb5 drm/i915: use VLV... |
1200 |
if (IS_VALLEYVIEW(dev)) { |
90b107c8f drm/i915: Enable ... |
1201 |
intel_hdmi->write_infoframe = vlv_write_infoframe; |
687f4d06d drm/i915: add set... |
1202 |
intel_hdmi->set_infoframes = vlv_set_infoframes; |
7637bfdb5 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 drm/i915: use HAS... |
1206 |
} else if (HAS_DDI(dev)) { |
8c5f5f7c4 drm/i915: add new... |
1207 |
intel_hdmi->write_infoframe = hsw_write_infoframe; |
687f4d06d drm/i915: add set... |
1208 |
intel_hdmi->set_infoframes = hsw_set_infoframes; |
fdf1250aa drm/i915: split i... |
1209 1210 |
} else if (HAS_PCH_IBX(dev)) { intel_hdmi->write_infoframe = ibx_write_infoframe; |
687f4d06d drm/i915: add set... |
1211 |
intel_hdmi->set_infoframes = ibx_set_infoframes; |
fdf1250aa drm/i915: split i... |
1212 1213 |
} else { intel_hdmi->write_infoframe = cpt_write_infoframe; |
687f4d06d drm/i915: add set... |
1214 |
intel_hdmi->set_infoframes = cpt_set_infoframes; |
64a8fc014 drm/i915: fix ILK... |
1215 |
} |
45187ace9 drm/i915/hdmi: sp... |
1216 |
|
affa93544 drm/i915: add HAS... |
1217 |
if (HAS_DDI(dev)) |
bcbc889bc 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 drm/i915: add unr... |
1221 |
intel_connector->unregister = intel_connector_unregister; |
b9cb234cb 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 drm/i915: rename ... |
1237 |
void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) |
b9cb234cb drm/i915: split i... |
1238 1239 1240 |
{ struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; |
b9cb234cb drm/i915: split i... |
1241 |
struct intel_connector *intel_connector; |
b14c5679d drm/i915: use poi... |
1242 |
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); |
b9cb234cb drm/i915: split i... |
1243 1244 |
if (!intel_dig_port) return; |
b14c5679d drm/i915: use poi... |
1245 |
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); |
b9cb234cb 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 drm/i915: split i... |
1252 1253 1254 |
drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS); |
00c09d70d drm/i915: create ... |
1255 |
|
5bfe2ac00 drm/i915: add pip... |
1256 |
intel_encoder->compute_config = intel_hdmi_compute_config; |
c59423a3d drm/i915/hdmi: us... |
1257 |
intel_encoder->mode_set = intel_hdmi_mode_set; |
00c09d70d drm/i915: create ... |
1258 1259 |
intel_encoder->disable = intel_disable_hdmi; intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
045ac3b56 drm/i915: add enc... |
1260 |
intel_encoder->get_config = intel_hdmi_get_config; |
89b667f86 drm/i915: update ... |
1261 |
if (IS_VALLEYVIEW(dev)) { |
9514ac6e7 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 drm/i915: rearran... |
1264 |
intel_encoder->enable = vlv_enable_hdmi; |
9514ac6e7 drm/i915: Move so... |
1265 |
intel_encoder->post_disable = vlv_hdmi_post_disable; |
b76cf76bf drm/i915: rearran... |
1266 1267 |
} else { intel_encoder->enable = intel_enable_hdmi; |
89b667f86 drm/i915: update ... |
1268 |
} |
5ab432ef4 drm/i915/hdmi: co... |
1269 |
|
b9cb234cb drm/i915: split i... |
1270 1271 |
intel_encoder->type = INTEL_OUTPUT_HDMI; intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
301ea74a5 drm/i915: Allow H... |
1272 |
intel_encoder->cloneable = 1 << INTEL_OUTPUT_ANALOG; |
c6f1495d4 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 drm/i915: Add sup... |
1280 |
|
174edf1f8 drm/i915: add por... |
1281 |
intel_dig_port->port = port; |
b242b7f74 drm/i915: rename ... |
1282 |
intel_dig_port->hdmi.hdmi_reg = hdmi_reg; |
b9cb234cb drm/i915: split i... |
1283 |
intel_dig_port->dp.output_reg = 0; |
55b7d6e8c drm/i915/hdmi: Ad... |
1284 |
|
b9cb234cb drm/i915: split i... |
1285 |
intel_hdmi_init_connector(intel_dig_port, intel_connector); |
7d57382e6 drm/i915: Add sup... |
1286 |
} |