Rev 2342 | Rev 3480 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2342 | Rev 3031 | ||
---|---|---|---|
Line 26... | Line 26... | ||
26 | * Jesse Barnes |
26 | * Jesse Barnes |
27 | */ |
27 | */ |
Line 28... | Line 28... | ||
28 | 28 | ||
29 | #include |
29 | #include |
30 | #include |
30 | #include |
31 | //#include |
31 | #include |
32 | #include "drmP.h" |
- | |
33 | #include "drm.h" |
32 | #include |
34 | #include "drm_crtc.h" |
33 | #include |
35 | #include "drm_edid.h" |
34 | #include |
36 | #include "intel_drv.h" |
35 | #include "intel_drv.h" |
37 | #include "i915_drm.h" |
36 | #include |
Line 38... | Line 37... | ||
38 | #include "i915_drv.h" |
37 | #include "i915_drv.h" |
39 | 38 | ||
40 | struct intel_hdmi { |
- | |
41 | struct intel_encoder base; |
39 | static void |
42 | u32 sdvox_reg; |
40 | assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) |
43 | int ddc_bus; |
- | |
44 | uint32_t color_range; |
- | |
45 | bool has_hdmi_sink; |
- | |
46 | bool has_audio; |
41 | { |
47 | int force_audio; |
42 | struct drm_device *dev = intel_hdmi->base.base.dev; |
48 | void (*write_infoframe)(struct drm_encoder *encoder, |
- | |
Line -... | Line 43... | ||
- | 43 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 44 | uint32_t enabled_bits; |
|
- | 45 | ||
- | 46 | enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; |
|
- | 47 | ||
- | 48 | WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits, |
|
49 | struct dip_infoframe *frame); |
49 | "HDMI port enabled, expecting disabled\n"); |
50 | }; |
50 | } |
51 | 51 | ||
52 | static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
52 | struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
Line 53... | Line 53... | ||
53 | { |
53 | { |
Line 73... | Line 73... | ||
73 | sum += data[i]; |
73 | sum += data[i]; |
Line 74... | Line 74... | ||
74 | 74 | ||
75 | frame->checksum = 0x100 - sum; |
75 | frame->checksum = 0x100 - sum; |
Line 76... | Line 76... | ||
76 | } |
76 | } |
77 | 77 | ||
78 | static u32 intel_infoframe_index(struct dip_infoframe *frame) |
- | |
79 | { |
- | |
80 | u32 flags = 0; |
78 | static u32 g4x_infoframe_index(struct dip_infoframe *frame) |
81 | 79 | { |
|
82 | switch (frame->type) { |
80 | switch (frame->type) { |
83 | case DIP_TYPE_AVI: |
- | |
84 | flags |= VIDEO_DIP_SELECT_AVI; |
81 | case DIP_TYPE_AVI: |
85 | break; |
82 | return VIDEO_DIP_SELECT_AVI; |
86 | case DIP_TYPE_SPD: |
- | |
87 | flags |= VIDEO_DIP_SELECT_SPD; |
83 | case DIP_TYPE_SPD: |
88 | break; |
84 | return VIDEO_DIP_SELECT_SPD; |
89 | default: |
85 | default: |
90 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
86 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
91 | break; |
- | |
92 | } |
- | |
93 | 87 | return 0; |
|
Line 94... | Line 88... | ||
94 | return flags; |
88 | } |
95 | } |
89 | } |
- | 90 | ||
- | 91 | static u32 g4x_infoframe_enable(struct dip_infoframe *frame) |
|
- | 92 | { |
|
- | 93 | switch (frame->type) { |
|
- | 94 | case DIP_TYPE_AVI: |
|
- | 95 | return VIDEO_DIP_ENABLE_AVI; |
|
- | 96 | case DIP_TYPE_SPD: |
|
96 | 97 | return VIDEO_DIP_ENABLE_SPD; |
|
- | 98 | default: |
|
- | 99 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
|
Line -... | Line 100... | ||
- | 100 | return 0; |
|
- | 101 | } |
|
97 | static u32 intel_infoframe_flags(struct dip_infoframe *frame) |
102 | } |
98 | { |
103 | |
99 | u32 flags = 0; |
104 | static u32 hsw_infoframe_enable(struct dip_infoframe *frame) |
100 | - | ||
101 | switch (frame->type) { |
105 | { |
102 | case DIP_TYPE_AVI: |
106 | switch (frame->type) { |
103 | flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC; |
- | |
104 | break; |
107 | case DIP_TYPE_AVI: |
105 | case DIP_TYPE_SPD: |
108 | return VIDEO_DIP_ENABLE_AVI_HSW; |
106 | flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_VSYNC; |
109 | case DIP_TYPE_SPD: |
- | 110 | return VIDEO_DIP_ENABLE_SPD_HSW; |
|
107 | break; |
111 | default: |
Line -... | Line 112... | ||
- | 112 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
|
- | 113 | return 0; |
|
- | 114 | } |
|
- | 115 | } |
|
- | 116 | ||
- | 117 | static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, enum pipe pipe) |
|
- | 118 | { |
|
- | 119 | switch (frame->type) { |
|
- | 120 | case DIP_TYPE_AVI: |
|
108 | default: |
121 | return HSW_TVIDEO_DIP_AVI_DATA(pipe); |
- | 122 | case DIP_TYPE_SPD: |
|
109 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
123 | return HSW_TVIDEO_DIP_SPD_DATA(pipe); |
Line 110... | Line 124... | ||
110 | break; |
124 | default: |
111 | } |
125 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
112 | 126 | return 0; |
|
113 | return flags; |
127 | } |
114 | } |
128 | } |
115 | 129 | ||
116 | static void i9xx_write_infoframe(struct drm_encoder *encoder, |
- | |
117 | struct dip_infoframe *frame) |
130 | static void g4x_write_infoframe(struct drm_encoder *encoder, |
118 | { |
131 | struct dip_infoframe *frame) |
Line -... | Line 132... | ||
- | 132 | { |
|
Line 119... | Line 133... | ||
119 | uint32_t *data = (uint32_t *)frame; |
133 | uint32_t *data = (uint32_t *)frame; |
120 | struct drm_device *dev = encoder->dev; |
- | |
121 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
122 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
- | |
123 | u32 port, flags, val = I915_READ(VIDEO_DIP_CTL); |
- | |
124 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
- | |
125 | - | ||
126 | - | ||
127 | /* XXX first guess at handling video port, is this corrent? */ |
134 | struct drm_device *dev = encoder->dev; |
Line 128... | Line 135... | ||
128 | if (intel_hdmi->sdvox_reg == SDVOB) |
135 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 129... | Line 136... | ||
129 | port = VIDEO_DIP_PORT_B; |
136 | u32 val = I915_READ(VIDEO_DIP_CTL); |
Line -... | Line 137... | ||
- | 137 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
|
130 | else if (intel_hdmi->sdvox_reg == SDVOC) |
138 | |
131 | port = VIDEO_DIP_PORT_C; |
139 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
132 | else |
140 | |
133 | return; |
141 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
- | 142 | val |= g4x_infoframe_index(frame); |
|
- | 143 | ||
- | 144 | val &= ~g4x_infoframe_enable(frame); |
|
- | 145 | ||
Line 134... | Line 146... | ||
134 | 146 | I915_WRITE(VIDEO_DIP_CTL, val); |
|
- | 147 | ||
- | 148 | mmiowb(); |
|
Line 135... | Line 149... | ||
135 | flags = intel_infoframe_index(frame); |
149 | for (i = 0; i < len; i += 4) { |
- | 150 | I915_WRITE(VIDEO_DIP_DATA, *data); |
|
136 | 151 | data++; |
|
Line 137... | Line 152... | ||
137 | val &= ~VIDEO_DIP_SELECT_MASK; |
152 | } |
138 | 153 | /* Write every possible data byte to force correct ECC calculation. */ |
|
139 | I915_WRITE(VIDEO_DIP_CTL, val | port | flags); |
154 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
140 | 155 | I915_WRITE(VIDEO_DIP_DATA, 0); |
|
141 | for (i = 0; i < len; i += 4) { |
156 | mmiowb(); |
142 | I915_WRITE(VIDEO_DIP_DATA, *data); |
157 | |
143 | data++; |
- | |
144 | } |
158 | val |= g4x_infoframe_enable(frame); |
145 | 159 | val &= ~VIDEO_DIP_FREQ_MASK; |
|
146 | flags |= intel_infoframe_flags(frame); |
160 | val |= VIDEO_DIP_FREQ_VSYNC; |
147 | 161 | ||
- | 162 | I915_WRITE(VIDEO_DIP_CTL, val); |
|
- | 163 | POSTING_READ(VIDEO_DIP_CTL); |
|
- | 164 | } |
|
- | 165 | ||
- | 166 | static void ibx_write_infoframe(struct drm_encoder *encoder, |
|
- | 167 | struct dip_infoframe *frame) |
|
- | 168 | { |
|
- | 169 | uint32_t *data = (uint32_t *)frame; |
|
- | 170 | struct drm_device *dev = encoder->dev; |
|
- | 171 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 172 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 173 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
|
- | 174 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
|
- | 175 | u32 val = I915_READ(reg); |
|
- | 176 | ||
- | 177 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
|
- | 178 | ||
- | 179 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
|
- | 180 | val |= g4x_infoframe_index(frame); |
|
- | 181 | ||
- | 182 | val &= ~g4x_infoframe_enable(frame); |
|
- | 183 | ||
- | 184 | I915_WRITE(reg, val); |
|
Line -... | Line 185... | ||
- | 185 | ||
- | 186 | mmiowb(); |
|
- | 187 | for (i = 0; i < len; i += 4) { |
|
- | 188 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
|
- | 189 | data++; |
|
- | 190 | } |
|
- | 191 | /* Write every possible data byte to force correct ECC calculation. */ |
|
- | 192 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
|
- | 193 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
|
- | 194 | mmiowb(); |
|
- | 195 | ||
148 | I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags); |
196 | val |= g4x_infoframe_enable(frame); |
- | 197 | val &= ~VIDEO_DIP_FREQ_MASK; |
|
- | 198 | val |= VIDEO_DIP_FREQ_VSYNC; |
|
Line 149... | Line 199... | ||
149 | } |
199 | |
Line 150... | Line 200... | ||
150 | 200 | I915_WRITE(reg, val); |
|
- | 201 | POSTING_READ(reg); |
|
Line -... | Line 202... | ||
- | 202 | } |
|
151 | static void ironlake_write_infoframe(struct drm_encoder *encoder, |
203 | |
- | 204 | static void cpt_write_infoframe(struct drm_encoder *encoder, |
|
- | 205 | struct dip_infoframe *frame) |
|
Line -... | Line 206... | ||
- | 206 | { |
|
- | 207 | uint32_t *data = (uint32_t *)frame; |
|
- | 208 | struct drm_device *dev = encoder->dev; |
|
152 | struct dip_infoframe *frame) |
209 | struct drm_i915_private *dev_priv = dev->dev_private; |
153 | { |
210 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
154 | uint32_t *data = (uint32_t *)frame; |
211 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
155 | struct drm_device *dev = encoder->dev; |
212 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
- | 213 | u32 val = I915_READ(reg); |
|
- | 214 | ||
- | 215 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
|
- | 216 | ||
Line 156... | Line 217... | ||
156 | struct drm_i915_private *dev_priv = dev->dev_private; |
217 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
- | 218 | val |= g4x_infoframe_index(frame); |
|
- | 219 | ||
Line 157... | Line 220... | ||
157 | struct drm_crtc *crtc = encoder->crtc; |
220 | /* The DIP control register spec says that we need to update the AVI |
- | 221 | * infoframe without clearing its enable bit */ |
|
158 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
222 | if (frame->type != DIP_TYPE_AVI) |
- | 223 | val &= ~g4x_infoframe_enable(frame); |
|
159 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
224 | |
160 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
225 | I915_WRITE(reg, val); |
161 | u32 flags, val = I915_READ(reg); |
226 | |
- | 227 | mmiowb(); |
|
- | 228 | for (i = 0; i < len; i += 4) { |
|
- | 229 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
|
162 | 230 | data++; |
|
- | 231 | } |
|
- | 232 | /* Write every possible data byte to force correct ECC calculation. */ |
|
- | 233 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
|
- | 234 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
|
- | 235 | mmiowb(); |
|
Line -... | Line 236... | ||
- | 236 | ||
- | 237 | val |= g4x_infoframe_enable(frame); |
|
- | 238 | val &= ~VIDEO_DIP_FREQ_MASK; |
|
- | 239 | val |= VIDEO_DIP_FREQ_VSYNC; |
|
- | 240 | ||
- | 241 | I915_WRITE(reg, val); |
|
- | 242 | POSTING_READ(reg); |
|
- | 243 | } |
|
163 | intel_wait_for_vblank(dev, intel_crtc->pipe); |
244 | |
- | 245 | static void vlv_write_infoframe(struct drm_encoder *encoder, |
|
- | 246 | struct dip_infoframe *frame) |
|
- | 247 | { |
|
- | 248 | uint32_t *data = (uint32_t *)frame; |
|
- | 249 | struct drm_device *dev = encoder->dev; |
|
- | 250 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 251 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 252 | int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
|
- | 253 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
|
- | 254 | u32 val = I915_READ(reg); |
|
- | 255 | ||
- | 256 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
|
- | 257 | ||
- | 258 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
|
- | 259 | val |= g4x_infoframe_index(frame); |
|
- | 260 | ||
- | 261 | val &= ~g4x_infoframe_enable(frame); |
|
- | 262 | ||
- | 263 | I915_WRITE(reg, val); |
|
- | 264 | ||
- | 265 | mmiowb(); |
|
- | 266 | for (i = 0; i < len; i += 4) { |
|
- | 267 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
|
- | 268 | data++; |
|
- | 269 | } |
|
- | 270 | /* Write every possible data byte to force correct ECC calculation. */ |
|
- | 271 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
|
- | 272 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
|
- | 273 | mmiowb(); |
|
164 | 274 | ||
Line -... | Line 275... | ||
- | 275 | val |= g4x_infoframe_enable(frame); |
|
- | 276 | val &= ~VIDEO_DIP_FREQ_MASK; |
|
- | 277 | val |= VIDEO_DIP_FREQ_VSYNC; |
|
- | 278 | ||
- | 279 | I915_WRITE(reg, val); |
|
- | 280 | POSTING_READ(reg); |
|
- | 281 | } |
|
- | 282 | ||
- | 283 | static void hsw_write_infoframe(struct drm_encoder *encoder, |
|
- | 284 | struct dip_infoframe *frame) |
|
- | 285 | { |
|
- | 286 | uint32_t *data = (uint32_t *)frame; |
|
- | 287 | struct drm_device *dev = encoder->dev; |
|
- | 288 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 289 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 290 | u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); |
|
- | 291 | u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->pipe); |
|
- | 292 | unsigned int i, len = DIP_HEADER_SIZE + frame->len; |
|
- | 293 | u32 val = I915_READ(ctl_reg); |
|
- | 294 | ||
- | 295 | if (data_reg == 0) |
|
- | 296 | return; |
|
- | 297 | ||
165 | flags = intel_infoframe_index(frame); |
298 | val &= ~hsw_infoframe_enable(frame); |
166 | 299 | I915_WRITE(ctl_reg, val); |
|
167 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
300 | |
Line 168... | Line 301... | ||
168 | 301 | mmiowb(); |
|
- | 302 | for (i = 0; i < len; i += 4) { |
|
169 | I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); |
303 | I915_WRITE(data_reg + i, *data); |
170 | 304 | data++; |
|
171 | for (i = 0; i < len; i += 4) { |
305 | } |
172 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); |
306 | /* Write every possible data byte to force correct ECC calculation. */ |
173 | data++; |
307 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
174 | } |
308 | I915_WRITE(data_reg + i, 0); |
Line -... | Line 309... | ||
- | 309 | mmiowb(); |
|
- | 310 | ||
- | 311 | val |= hsw_infoframe_enable(frame); |
|
175 | 312 | I915_WRITE(ctl_reg, val); |
|
176 | flags |= intel_infoframe_flags(frame); |
313 | POSTING_READ(ctl_reg); |
Line 177... | Line 314... | ||
177 | 314 | } |
|
178 | I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); |
315 | |
Line 213... | Line 350... | ||
213 | spd_if.body.spd.sdi = DIP_SPD_PC; |
350 | spd_if.body.spd.sdi = DIP_SPD_PC; |
Line 214... | Line 351... | ||
214 | 351 | ||
215 | intel_set_infoframe(encoder, &spd_if); |
352 | intel_set_infoframe(encoder, &spd_if); |
Line -... | Line 353... | ||
- | 353 | } |
|
- | 354 | ||
- | 355 | static void g4x_set_infoframes(struct drm_encoder *encoder, |
|
- | 356 | struct drm_display_mode *adjusted_mode) |
|
- | 357 | { |
|
- | 358 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
|
- | 359 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
- | 360 | u32 reg = VIDEO_DIP_CTL; |
|
- | 361 | u32 val = I915_READ(reg); |
|
- | 362 | u32 port; |
|
- | 363 | ||
- | 364 | assert_hdmi_port_disabled(intel_hdmi); |
|
- | 365 | ||
- | 366 | /* If the registers were not initialized yet, they might be zeroes, |
|
- | 367 | * which means we're selecting the AVI DIP and we're setting its |
|
- | 368 | * frequency to once. This seems to really confuse the HW and make |
|
- | 369 | * things stop working (the register spec says the AVI always needs to |
|
- | 370 | * be sent every VSync). So here we avoid writing to the register more |
|
- | 371 | * than we need and also explicitly select the AVI DIP and explicitly |
|
- | 372 | * set its frequency to every VSync. Avoiding to write it twice seems to |
|
- | 373 | * be enough to solve the problem, but being defensive shouldn't hurt us |
|
- | 374 | * either. */ |
|
- | 375 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; |
|
- | 376 | ||
- | 377 | if (!intel_hdmi->has_hdmi_sink) { |
|
- | 378 | if (!(val & VIDEO_DIP_ENABLE)) |
|
- | 379 | return; |
|
- | 380 | val &= ~VIDEO_DIP_ENABLE; |
|
- | 381 | I915_WRITE(reg, val); |
|
- | 382 | POSTING_READ(reg); |
|
- | 383 | return; |
|
- | 384 | } |
|
- | 385 | ||
- | 386 | switch (intel_hdmi->sdvox_reg) { |
|
- | 387 | case SDVOB: |
|
- | 388 | port = VIDEO_DIP_PORT_B; |
|
- | 389 | break; |
|
- | 390 | case SDVOC: |
|
- | 391 | port = VIDEO_DIP_PORT_C; |
|
- | 392 | break; |
|
- | 393 | default: |
|
- | 394 | BUG(); |
|
- | 395 | return; |
|
- | 396 | } |
|
- | 397 | ||
- | 398 | if (port != (val & VIDEO_DIP_PORT_MASK)) { |
|
- | 399 | if (val & VIDEO_DIP_ENABLE) { |
|
- | 400 | val &= ~VIDEO_DIP_ENABLE; |
|
- | 401 | I915_WRITE(reg, val); |
|
- | 402 | POSTING_READ(reg); |
|
- | 403 | } |
|
- | 404 | val &= ~VIDEO_DIP_PORT_MASK; |
|
- | 405 | val |= port; |
|
- | 406 | } |
|
- | 407 | ||
- | 408 | val |= VIDEO_DIP_ENABLE; |
|
- | 409 | val &= ~VIDEO_DIP_ENABLE_VENDOR; |
|
- | 410 | ||
- | 411 | I915_WRITE(reg, val); |
|
- | 412 | POSTING_READ(reg); |
|
- | 413 | ||
- | 414 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
|
- | 415 | intel_hdmi_set_spd_infoframe(encoder); |
|
- | 416 | } |
|
- | 417 | ||
- | 418 | static void ibx_set_infoframes(struct drm_encoder *encoder, |
|
- | 419 | struct drm_display_mode *adjusted_mode) |
|
- | 420 | { |
|
- | 421 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
|
- | 422 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 423 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
- | 424 | u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
|
- | 425 | u32 val = I915_READ(reg); |
|
- | 426 | u32 port; |
|
- | 427 | ||
- | 428 | assert_hdmi_port_disabled(intel_hdmi); |
|
- | 429 | ||
- | 430 | /* See the big comment in g4x_set_infoframes() */ |
|
- | 431 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; |
|
- | 432 | ||
- | 433 | if (!intel_hdmi->has_hdmi_sink) { |
|
- | 434 | if (!(val & VIDEO_DIP_ENABLE)) |
|
- | 435 | return; |
|
- | 436 | val &= ~VIDEO_DIP_ENABLE; |
|
- | 437 | I915_WRITE(reg, val); |
|
- | 438 | POSTING_READ(reg); |
|
- | 439 | return; |
|
- | 440 | } |
|
- | 441 | ||
- | 442 | switch (intel_hdmi->sdvox_reg) { |
|
- | 443 | case HDMIB: |
|
- | 444 | port = VIDEO_DIP_PORT_B; |
|
- | 445 | break; |
|
- | 446 | case HDMIC: |
|
- | 447 | port = VIDEO_DIP_PORT_C; |
|
- | 448 | break; |
|
- | 449 | case HDMID: |
|
- | 450 | port = VIDEO_DIP_PORT_D; |
|
- | 451 | break; |
|
- | 452 | default: |
|
- | 453 | BUG(); |
|
- | 454 | return; |
|
- | 455 | } |
|
- | 456 | ||
- | 457 | if (port != (val & VIDEO_DIP_PORT_MASK)) { |
|
- | 458 | if (val & VIDEO_DIP_ENABLE) { |
|
- | 459 | val &= ~VIDEO_DIP_ENABLE; |
|
- | 460 | I915_WRITE(reg, val); |
|
- | 461 | POSTING_READ(reg); |
|
- | 462 | } |
|
- | 463 | val &= ~VIDEO_DIP_PORT_MASK; |
|
- | 464 | val |= port; |
|
- | 465 | } |
|
- | 466 | ||
- | 467 | val |= VIDEO_DIP_ENABLE; |
|
- | 468 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
|
- | 469 | VIDEO_DIP_ENABLE_GCP); |
|
- | 470 | ||
- | 471 | I915_WRITE(reg, val); |
|
- | 472 | POSTING_READ(reg); |
|
- | 473 | ||
- | 474 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
|
- | 475 | intel_hdmi_set_spd_infoframe(encoder); |
|
- | 476 | } |
|
- | 477 | ||
- | 478 | static void cpt_set_infoframes(struct drm_encoder *encoder, |
|
- | 479 | struct drm_display_mode *adjusted_mode) |
|
- | 480 | { |
|
- | 481 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
|
- | 482 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 483 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
- | 484 | u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
|
- | 485 | u32 val = I915_READ(reg); |
|
- | 486 | ||
- | 487 | assert_hdmi_port_disabled(intel_hdmi); |
|
- | 488 | ||
- | 489 | /* See the big comment in g4x_set_infoframes() */ |
|
- | 490 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; |
|
- | 491 | ||
- | 492 | if (!intel_hdmi->has_hdmi_sink) { |
|
- | 493 | if (!(val & VIDEO_DIP_ENABLE)) |
|
- | 494 | return; |
|
- | 495 | val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI); |
|
- | 496 | I915_WRITE(reg, val); |
|
- | 497 | POSTING_READ(reg); |
|
- | 498 | return; |
|
- | 499 | } |
|
- | 500 | ||
- | 501 | /* Set both together, unset both together: see the spec. */ |
|
- | 502 | val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; |
|
- | 503 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
|
- | 504 | VIDEO_DIP_ENABLE_GCP); |
|
- | 505 | ||
- | 506 | I915_WRITE(reg, val); |
|
- | 507 | POSTING_READ(reg); |
|
- | 508 | ||
- | 509 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
|
- | 510 | intel_hdmi_set_spd_infoframe(encoder); |
|
- | 511 | } |
|
- | 512 | ||
- | 513 | static void vlv_set_infoframes(struct drm_encoder *encoder, |
|
- | 514 | struct drm_display_mode *adjusted_mode) |
|
- | 515 | { |
|
- | 516 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
|
- | 517 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 518 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
- | 519 | u32 reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
|
- | 520 | u32 val = I915_READ(reg); |
|
- | 521 | ||
- | 522 | assert_hdmi_port_disabled(intel_hdmi); |
|
- | 523 | ||
- | 524 | /* See the big comment in g4x_set_infoframes() */ |
|
- | 525 | val |= VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC; |
|
- | 526 | ||
- | 527 | if (!intel_hdmi->has_hdmi_sink) { |
|
- | 528 | if (!(val & VIDEO_DIP_ENABLE)) |
|
- | 529 | return; |
|
- | 530 | val &= ~VIDEO_DIP_ENABLE; |
|
- | 531 | I915_WRITE(reg, val); |
|
- | 532 | POSTING_READ(reg); |
|
- | 533 | return; |
|
- | 534 | } |
|
- | 535 | ||
- | 536 | val |= VIDEO_DIP_ENABLE; |
|
- | 537 | val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
|
- | 538 | VIDEO_DIP_ENABLE_GCP); |
|
- | 539 | ||
- | 540 | I915_WRITE(reg, val); |
|
- | 541 | POSTING_READ(reg); |
|
- | 542 | ||
- | 543 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
|
- | 544 | intel_hdmi_set_spd_infoframe(encoder); |
|
- | 545 | } |
|
- | 546 | ||
- | 547 | static void hsw_set_infoframes(struct drm_encoder *encoder, |
|
- | 548 | struct drm_display_mode *adjusted_mode) |
|
- | 549 | { |
|
- | 550 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
|
- | 551 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 552 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
- | 553 | u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->pipe); |
|
- | 554 | u32 val = I915_READ(reg); |
|
- | 555 | ||
- | 556 | assert_hdmi_port_disabled(intel_hdmi); |
|
- | 557 | ||
- | 558 | if (!intel_hdmi->has_hdmi_sink) { |
|
- | 559 | I915_WRITE(reg, 0); |
|
- | 560 | POSTING_READ(reg); |
|
- | 561 | return; |
|
- | 562 | } |
|
- | 563 | ||
- | 564 | val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW | |
|
- | 565 | VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); |
|
- | 566 | ||
- | 567 | I915_WRITE(reg, val); |
|
- | 568 | POSTING_READ(reg); |
|
- | 569 | ||
- | 570 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
|
- | 571 | intel_hdmi_set_spd_infoframe(encoder); |
|
216 | } |
572 | } |
217 | 573 | ||
218 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, |
574 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, |
219 | struct drm_display_mode *mode, |
575 | struct drm_display_mode *mode, |
220 | struct drm_display_mode *adjusted_mode) |
576 | struct drm_display_mode *adjusted_mode) |
221 | { |
577 | { |
222 | struct drm_device *dev = encoder->dev; |
- | |
223 | struct drm_i915_private *dev_priv = dev->dev_private; |
578 | struct drm_device *dev = encoder->dev; |
224 | struct drm_crtc *crtc = encoder->crtc; |
579 | struct drm_i915_private *dev_priv = dev->dev_private; |
225 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
580 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
Line 226... | Line 581... | ||
226 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
581 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
227 | u32 sdvox; |
582 | u32 sdvox; |
228 | 583 | ||
229 | sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; |
584 | sdvox = SDVO_ENCODING_HDMI; |
230 | if (!HAS_PCH_SPLIT(dev)) |
585 | if (!HAS_PCH_SPLIT(dev)) |
231 | sdvox |= intel_hdmi->color_range; |
586 | sdvox |= intel_hdmi->color_range; |
Line 251... | Line 606... | ||
251 | intel_write_eld(encoder, adjusted_mode); |
606 | intel_write_eld(encoder, adjusted_mode); |
252 | } |
607 | } |
Line 253... | Line 608... | ||
253 | 608 | ||
254 | if (HAS_PCH_CPT(dev)) |
609 | if (HAS_PCH_CPT(dev)) |
255 | sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); |
610 | sdvox |= PORT_TRANS_SEL_CPT(intel_crtc->pipe); |
256 | else if (intel_crtc->pipe == 1) |
611 | else if (intel_crtc->pipe == PIPE_B) |
Line 257... | Line 612... | ||
257 | sdvox |= SDVO_PIPE_B_SELECT; |
612 | sdvox |= SDVO_PIPE_B_SELECT; |
258 | 613 | ||
Line 259... | Line -... | ||
259 | I915_WRITE(intel_hdmi->sdvox_reg, sdvox); |
- | |
260 | POSTING_READ(intel_hdmi->sdvox_reg); |
614 | I915_WRITE(intel_hdmi->sdvox_reg, sdvox); |
261 | 615 | POSTING_READ(intel_hdmi->sdvox_reg); |
|
Line 262... | Line 616... | ||
262 | intel_hdmi_set_avi_infoframe(encoder); |
616 | |
- | 617 | intel_hdmi->set_infoframes(encoder, adjusted_mode); |
|
263 | intel_hdmi_set_spd_infoframe(encoder); |
618 | } |
264 | } |
619 | |
265 | 620 | static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, |
|
266 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) |
621 | enum pipe *pipe) |
- | 622 | { |
|
- | 623 | struct drm_device *dev = encoder->base.dev; |
|
- | 624 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 625 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
|
- | 626 | u32 tmp; |
|
- | 627 | ||
- | 628 | tmp = I915_READ(intel_hdmi->sdvox_reg); |
|
- | 629 | ||
- | 630 | if (!(tmp & SDVO_ENABLE)) |
|
- | 631 | return false; |
|
- | 632 | ||
- | 633 | if (HAS_PCH_CPT(dev)) |
|
- | 634 | *pipe = PORT_TO_PIPE_CPT(tmp); |
|
- | 635 | else |
|
- | 636 | *pipe = PORT_TO_PIPE(tmp); |
|
- | 637 | ||
- | 638 | return true; |
|
- | 639 | } |
|
- | 640 | ||
- | 641 | static void intel_enable_hdmi(struct intel_encoder *encoder) |
|
267 | { |
642 | { |
268 | struct drm_device *dev = encoder->dev; |
643 | struct drm_device *dev = encoder->base.dev; |
Line 269... | Line 644... | ||
269 | struct drm_i915_private *dev_priv = dev->dev_private; |
644 | struct drm_i915_private *dev_priv = dev->dev_private; |
270 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
645 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
Line 271... | Line 646... | ||
271 | u32 temp; |
646 | u32 temp; |
Line -... | Line 647... | ||
- | 647 | u32 enable_bits = SDVO_ENABLE; |
|
- | 648 | ||
- | 649 | if (intel_hdmi->has_audio) |
|
- | 650 | enable_bits |= SDVO_AUDIO_ENABLE; |
|
- | 651 | ||
- | 652 | temp = I915_READ(intel_hdmi->sdvox_reg); |
|
- | 653 | ||
- | 654 | /* HW workaround for IBX, we need to move the port to transcoder A |
|
- | 655 | * before disabling it. */ |
|
- | 656 | if (HAS_PCH_IBX(dev)) { |
|
- | 657 | struct drm_crtc *crtc = encoder->base.crtc; |
|
272 | u32 enable_bits = SDVO_ENABLE; |
658 | int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; |
273 | 659 | ||
274 | if (intel_hdmi->has_audio) |
660 | /* Restore the transcoder select bit. */ |
275 | enable_bits |= SDVO_AUDIO_ENABLE; |
661 | if (pipe == PIPE_B) |
276 | 662 | enable_bits |= SDVO_PIPE_B_SELECT; |
|
277 | temp = I915_READ(intel_hdmi->sdvox_reg); |
663 | } |
278 | 664 | ||
Line 279... | Line -... | ||
279 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but |
- | |
280 | * we do this anyway which shows more stable in testing. |
- | |
281 | */ |
- | |
282 | if (HAS_PCH_SPLIT(dev)) { |
665 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but |
- | 666 | * we do this anyway which shows more stable in testing. |
|
- | 667 | */ |
|
- | 668 | if (HAS_PCH_SPLIT(dev)) { |
|
- | 669 | I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE); |
|
- | 670 | POSTING_READ(intel_hdmi->sdvox_reg); |
|
- | 671 | } |
|
- | 672 | ||
- | 673 | temp |= enable_bits; |
|
- | 674 | ||
- | 675 | I915_WRITE(intel_hdmi->sdvox_reg, temp); |
|
283 | I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE); |
676 | POSTING_READ(intel_hdmi->sdvox_reg); |
- | 677 | ||
- | 678 | /* HW workaround, need to write this twice for issue that may result |
|
- | 679 | * in first write getting masked. |
|
- | 680 | */ |
|
- | 681 | if (HAS_PCH_SPLIT(dev)) { |
|
- | 682 | I915_WRITE(intel_hdmi->sdvox_reg, temp); |
|
- | 683 | POSTING_READ(intel_hdmi->sdvox_reg); |
|
- | 684 | } |
|
- | 685 | } |
|
- | 686 | ||
- | 687 | static void intel_disable_hdmi(struct intel_encoder *encoder) |
|
- | 688 | { |
|
- | 689 | struct drm_device *dev = encoder->base.dev; |
|
- | 690 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 691 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
|
- | 692 | u32 temp; |
|
- | 693 | u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; |
|
- | 694 | ||
- | 695 | temp = I915_READ(intel_hdmi->sdvox_reg); |
|
- | 696 | ||
- | 697 | /* HW workaround for IBX, we need to move the port to transcoder A |
|
- | 698 | * before disabling it. */ |
|
- | 699 | if (HAS_PCH_IBX(dev)) { |
|
- | 700 | struct drm_crtc *crtc = encoder->base.crtc; |
|
- | 701 | int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; |
|
- | 702 | ||
- | 703 | if (temp & SDVO_PIPE_B_SELECT) { |
|
- | 704 | temp &= ~SDVO_PIPE_B_SELECT; |
|
- | 705 | I915_WRITE(intel_hdmi->sdvox_reg, temp); |
|
- | 706 | POSTING_READ(intel_hdmi->sdvox_reg); |
|
- | 707 | ||
- | 708 | /* Again we need to write this twice. */ |
|
- | 709 | I915_WRITE(intel_hdmi->sdvox_reg, temp); |
|
- | 710 | POSTING_READ(intel_hdmi->sdvox_reg); |
|
- | 711 | ||
- | 712 | /* Transcoder selection bits only update |
|
- | 713 | * effectively on vblank. */ |
|
- | 714 | if (crtc) |
|
- | 715 | intel_wait_for_vblank(dev, pipe); |
|
- | 716 | else |
|
- | 717 | msleep(50); |
|
- | 718 | } |
|
- | 719 | } |
|
- | 720 | ||
- | 721 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but |
|
Line 284... | Line 722... | ||
284 | POSTING_READ(intel_hdmi->sdvox_reg); |
722 | * we do this anyway which shows more stable in testing. |
285 | } |
723 | */ |
Line 286... | Line 724... | ||
286 | 724 | if (HAS_PCH_SPLIT(dev)) { |
|
Line 315... | Line 753... | ||
315 | 753 | ||
316 | return MODE_OK; |
754 | return MODE_OK; |
Line 317... | Line 755... | ||
317 | } |
755 | } |
318 | 756 | ||
319 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, |
757 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, |
320 | struct drm_display_mode *mode, |
758 | const struct drm_display_mode *mode, |
321 | struct drm_display_mode *adjusted_mode) |
759 | struct drm_display_mode *adjusted_mode) |
322 | { |
760 | { |
Line -... | Line 761... | ||
- | 761 | return true; |
|
- | 762 | } |
|
- | 763 | ||
- | 764 | static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi) |
|
- | 765 | { |
|
- | 766 | struct drm_device *dev = intel_hdmi->base.base.dev; |
|
- | 767 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 768 | uint32_t bit; |
|
- | 769 | ||
- | 770 | switch (intel_hdmi->sdvox_reg) { |
|
- | 771 | case SDVOB: |
|
- | 772 | bit = HDMIB_HOTPLUG_LIVE_STATUS; |
|
- | 773 | break; |
|
- | 774 | case SDVOC: |
|
- | 775 | bit = HDMIC_HOTPLUG_LIVE_STATUS; |
|
- | 776 | break; |
|
- | 777 | default: |
|
- | 778 | bit = 0; |
|
- | 779 | break; |
|
- | 780 | } |
|
- | 781 | ||
323 | return true; |
782 | return I915_READ(PORT_HOTPLUG_STAT) & bit; |
324 | } |
783 | } |
325 | 784 | ||
326 | static enum drm_connector_status |
785 | static enum drm_connector_status |
327 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
786 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
328 | { |
787 | { |
329 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
788 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
Line -... | Line 789... | ||
- | 789 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
|
- | 790 | struct edid *edid; |
|
- | 791 | enum drm_connector_status status = connector_status_disconnected; |
|
330 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
792 | |
331 | struct edid *edid; |
793 | if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) |
332 | enum drm_connector_status status = connector_status_disconnected; |
794 | return status; |
- | 795 | ||
333 | 796 | intel_hdmi->has_hdmi_sink = false; |
|
Line 334... | Line 797... | ||
334 | intel_hdmi->has_hdmi_sink = false; |
797 | intel_hdmi->has_audio = false; |
335 | intel_hdmi->has_audio = false; |
798 | edid = drm_get_edid(connector, |
336 | edid = drm_get_edid(connector, |
799 | intel_gmbus_get_adapter(dev_priv, |
- | 800 | intel_hdmi->ddc_bus)); |
|
- | 801 | ||
337 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); |
802 | if (edid) { |
338 | 803 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
|
339 | if (edid) { |
804 | status = connector_status_connected; |
340 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
- | |
341 | status = connector_status_connected; |
805 | if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) |
342 | intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); |
806 | intel_hdmi->has_hdmi_sink = |
Line 343... | Line 807... | ||
343 | intel_hdmi->has_audio = drm_detect_monitor_audio(edid); |
807 | drm_detect_hdmi_monitor(edid); |
- | 808 | intel_hdmi->has_audio = drm_detect_monitor_audio(edid); |
|
344 | } |
809 | } |
345 | connector->display_info.raw_edid = NULL; |
810 | kfree(edid); |
346 | kfree(edid); |
811 | } |
Line 347... | Line 812... | ||
347 | } |
812 | |
348 | 813 | if (status == connector_status_connected) { |
|
Line 362... | Line 827... | ||
362 | /* We should parse the EDID data and find out if it's an HDMI sink so |
827 | /* We should parse the EDID data and find out if it's an HDMI sink so |
363 | * we can send audio to it. |
828 | * we can send audio to it. |
364 | */ |
829 | */ |
Line 365... | Line 830... | ||
365 | 830 | ||
- | 831 | return intel_ddc_get_modes(connector, |
|
366 | return intel_ddc_get_modes(connector, |
832 | intel_gmbus_get_adapter(dev_priv, |
367 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); |
833 | intel_hdmi->ddc_bus)); |
Line 368... | Line 834... | ||
368 | } |
834 | } |
369 | 835 | ||
370 | static bool |
836 | static bool |
Line 374... | Line 840... | ||
374 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
840 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
375 | struct edid *edid; |
841 | struct edid *edid; |
376 | bool has_audio = false; |
842 | bool has_audio = false; |
Line 377... | Line 843... | ||
377 | 843 | ||
- | 844 | edid = drm_get_edid(connector, |
|
378 | edid = drm_get_edid(connector, |
845 | intel_gmbus_get_adapter(dev_priv, |
379 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); |
846 | intel_hdmi->ddc_bus)); |
380 | if (edid) { |
847 | if (edid) { |
381 | if (edid->input & DRM_EDID_INPUT_DIGITAL) |
848 | if (edid->input & DRM_EDID_INPUT_DIGITAL) |
382 | has_audio = drm_detect_monitor_audio(edid); |
- | |
383 | - | ||
384 | connector->display_info.raw_edid = NULL; |
849 | has_audio = drm_detect_monitor_audio(edid); |
385 | kfree(edid); |
850 | kfree(edid); |
Line 386... | Line 851... | ||
386 | } |
851 | } |
387 | 852 | ||
Line 400... | Line 865... | ||
400 | ret = drm_connector_property_set_value(connector, property, val); |
865 | ret = drm_connector_property_set_value(connector, property, val); |
401 | if (ret) |
866 | if (ret) |
402 | return ret; |
867 | return ret; |
403 | #if 0 |
868 | #if 0 |
404 | if (property == dev_priv->force_audio_property) { |
869 | if (property == dev_priv->force_audio_property) { |
405 | int i = val; |
870 | enum hdmi_force_audio i = val; |
406 | bool has_audio; |
871 | bool has_audio; |
Line 407... | Line 872... | ||
407 | 872 | ||
408 | if (i == intel_hdmi->force_audio) |
873 | if (i == intel_hdmi->force_audio) |
Line 409... | Line 874... | ||
409 | return 0; |
874 | return 0; |
Line 410... | Line 875... | ||
410 | 875 | ||
411 | intel_hdmi->force_audio = i; |
876 | intel_hdmi->force_audio = i; |
412 | 877 | ||
413 | if (i == 0) |
878 | if (i == HDMI_AUDIO_AUTO) |
Line 414... | Line 879... | ||
414 | has_audio = intel_hdmi_detect_audio(connector); |
879 | has_audio = intel_hdmi_detect_audio(connector); |
415 | else |
880 | else |
Line 416... | Line 881... | ||
416 | has_audio = i > 0; |
881 | has_audio = (i == HDMI_AUDIO_ON); |
417 | 882 | ||
418 | if (has_audio == intel_hdmi->has_audio) |
883 | if (i == HDMI_AUDIO_OFF_DVI) |
- | 884 | intel_hdmi->has_hdmi_sink = 0; |
|
Line 419... | Line 885... | ||
419 | return 0; |
885 | |
420 | 886 | intel_hdmi->has_audio = has_audio; |
|
421 | intel_hdmi->has_audio = has_audio; |
887 | goto done; |
Line 422... | Line 888... | ||
422 | goto done; |
888 | } |
423 | } |
889 | #endif |
424 | 890 | ||
425 | if (property == dev_priv->broadcast_rgb_property) { |
891 | if (property == dev_priv->broadcast_rgb_property) { |
426 | if (val == !!intel_hdmi->color_range) |
892 | if (val == !!intel_hdmi->color_range) |
Line 427... | Line 893... | ||
427 | return 0; |
893 | return 0; |
428 | 894 | ||
429 | intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; |
895 | intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; |
430 | goto done; |
896 | goto done; |
431 | } |
897 | } |
432 | #endif |
- | |
433 | return -EINVAL; |
898 | |
Line 434... | Line 899... | ||
434 | 899 | return -EINVAL; |
|
435 | done: |
900 | |
Line 448... | Line 913... | ||
448 | drm_sysfs_connector_remove(connector); |
913 | drm_sysfs_connector_remove(connector); |
449 | drm_connector_cleanup(connector); |
914 | drm_connector_cleanup(connector); |
450 | kfree(connector); |
915 | kfree(connector); |
451 | } |
916 | } |
Line -... | Line 917... | ||
- | 917 | ||
- | 918 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = { |
|
- | 919 | .mode_fixup = intel_hdmi_mode_fixup, |
|
- | 920 | .mode_set = intel_ddi_mode_set, |
|
- | 921 | .disable = intel_encoder_noop, |
|
- | 922 | }; |
|
452 | 923 | ||
453 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { |
- | |
454 | .dpms = intel_hdmi_dpms, |
924 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { |
455 | .mode_fixup = intel_hdmi_mode_fixup, |
- | |
456 | .prepare = intel_encoder_prepare, |
925 | .mode_fixup = intel_hdmi_mode_fixup, |
457 | .mode_set = intel_hdmi_mode_set, |
926 | .mode_set = intel_hdmi_mode_set, |
458 | .commit = intel_encoder_commit, |
927 | .disable = intel_encoder_noop, |
Line 459... | Line 928... | ||
459 | }; |
928 | }; |
460 | 929 | ||
461 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
930 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
462 | .dpms = drm_helper_connector_dpms, |
931 | .dpms = intel_connector_dpms, |
463 | .detect = intel_hdmi_detect, |
932 | .detect = intel_hdmi_detect, |
464 | .fill_modes = drm_helper_probe_single_connector_modes, |
933 | .fill_modes = drm_helper_probe_single_connector_modes, |
465 | .set_property = intel_hdmi_set_property, |
934 | .set_property = intel_hdmi_set_property, |
Line 481... | Line 950... | ||
481 | { |
950 | { |
482 | intel_attach_force_audio_property(connector); |
951 | intel_attach_force_audio_property(connector); |
483 | intel_attach_broadcast_rgb_property(connector); |
952 | intel_attach_broadcast_rgb_property(connector); |
484 | } |
953 | } |
Line 485... | Line 954... | ||
485 | 954 | ||
486 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) |
955 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port) |
487 | { |
956 | { |
488 | struct drm_i915_private *dev_priv = dev->dev_private; |
957 | struct drm_i915_private *dev_priv = dev->dev_private; |
489 | struct drm_connector *connector; |
958 | struct drm_connector *connector; |
490 | struct intel_encoder *intel_encoder; |
959 | struct intel_encoder *intel_encoder; |
491 | struct intel_connector *intel_connector; |
960 | struct intel_connector *intel_connector; |
492 | struct intel_hdmi *intel_hdmi; |
- | |
Line 493... | Line 961... | ||
493 | int i; |
961 | struct intel_hdmi *intel_hdmi; |
494 | 962 | ||
495 | intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); |
963 | intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL); |
Line 512... | Line 980... | ||
512 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
980 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
Line 513... | Line 981... | ||
513 | 981 | ||
Line 514... | Line 982... | ||
514 | intel_encoder->type = INTEL_OUTPUT_HDMI; |
982 | intel_encoder->type = INTEL_OUTPUT_HDMI; |
515 | 983 | ||
516 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
984 | connector->polled = DRM_CONNECTOR_POLL_HPD; |
517 | connector->interlace_allowed = 0; |
985 | connector->interlace_allowed = 1; |
Line 518... | Line -... | ||
518 | connector->doublescan_allowed = 0; |
- | |
519 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
- | |
520 | 986 | connector->doublescan_allowed = 0; |
|
- | 987 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
|
521 | /* Set up the DDC bus. */ |
988 | |
522 | if (sdvox_reg == SDVOB) { |
- | |
523 | intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); |
989 | intel_encoder->cloneable = false; |
524 | intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
- | |
525 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; |
990 | |
526 | } else if (sdvox_reg == SDVOC) { |
- | |
527 | intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); |
- | |
528 | intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
- | |
529 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; |
991 | intel_hdmi->ddi_port = port; |
530 | } else if (sdvox_reg == HDMIB) { |
992 | switch (port) { |
531 | intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); |
993 | case PORT_B: |
532 | intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
994 | intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
533 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; |
995 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; |
534 | } else if (sdvox_reg == HDMIC) { |
996 | break; |
535 | intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); |
997 | case PORT_C: |
536 | intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
998 | intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
537 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; |
999 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; |
538 | } else if (sdvox_reg == HDMID) { |
1000 | break; |
- | 1001 | case PORT_D: |
|
- | 1002 | intel_hdmi->ddc_bus = GMBUS_PORT_DPD; |
|
- | 1003 | dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; |
|
- | 1004 | break; |
|
- | 1005 | case PORT_A: |
|
539 | intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); |
1006 | /* Internal port only for eDP. */ |
Line 540... | Line 1007... | ||
540 | intel_hdmi->ddc_bus = GMBUS_PORT_DPD; |
1007 | default: |
Line 541... | Line 1008... | ||
541 | dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; |
1008 | BUG(); |
542 | } |
1009 | } |
- | 1010 | ||
- | 1011 | intel_hdmi->sdvox_reg = sdvox_reg; |
|
- | 1012 | ||
- | 1013 | if (!HAS_PCH_SPLIT(dev)) { |
|
543 | 1014 | intel_hdmi->write_infoframe = g4x_write_infoframe; |
|
- | 1015 | intel_hdmi->set_infoframes = g4x_set_infoframes; |
|
- | 1016 | } else if (IS_VALLEYVIEW(dev)) { |
|
- | 1017 | intel_hdmi->write_infoframe = vlv_write_infoframe; |
|
- | 1018 | intel_hdmi->set_infoframes = vlv_set_infoframes; |
|
- | 1019 | } else if (IS_HASWELL(dev)) { |
|
- | 1020 | intel_hdmi->write_infoframe = hsw_write_infoframe; |
|
- | 1021 | intel_hdmi->set_infoframes = hsw_set_infoframes; |
|
- | 1022 | } else if (HAS_PCH_IBX(dev)) { |
|
- | 1023 | intel_hdmi->write_infoframe = ibx_write_infoframe; |
|
- | 1024 | intel_hdmi->set_infoframes = ibx_set_infoframes; |
|
- | 1025 | } else { |
|
- | 1026 | intel_hdmi->write_infoframe = cpt_write_infoframe; |
|
- | 1027 | intel_hdmi->set_infoframes = cpt_set_infoframes; |
|
- | 1028 | } |
|
- | 1029 | ||
- | 1030 | if (IS_HASWELL(dev)) { |
|
544 | intel_hdmi->sdvox_reg = sdvox_reg; |
1031 | intel_encoder->enable = intel_enable_ddi; |
- | 1032 | intel_encoder->disable = intel_disable_ddi; |
|
- | 1033 | intel_encoder->get_hw_state = intel_ddi_get_hw_state; |
|
545 | 1034 | drm_encoder_helper_add(&intel_encoder->base, |
|
546 | if (!HAS_PCH_SPLIT(dev)) { |
1035 | &intel_hdmi_helper_funcs_hsw); |
547 | intel_hdmi->write_infoframe = i9xx_write_infoframe; |
1036 | } else { |
548 | I915_WRITE(VIDEO_DIP_CTL, 0); |
1037 | intel_encoder->enable = intel_enable_hdmi; |
- | 1038 | intel_encoder->disable = intel_disable_hdmi; |
|
Line 549... | Line -... | ||
549 | } else { |
- | |
Line 550... | Line 1039... | ||
550 | intel_hdmi->write_infoframe = ironlake_write_infoframe; |
1039 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
Line 551... | Line 1040... | ||
551 | for_each_pipe(i) |
1040 | drm_encoder_helper_add(&intel_encoder->base, |
552 | I915_WRITE(TVIDEO_DIP_CTL(i), 0); |
1041 | &intel_hdmi_helper_funcs); |