Rev 3746 | Rev 5060 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3746 | Rev 4104 | ||
---|---|---|---|
Line 27... | Line 27... | ||
27 | */ |
27 | */ |
Line 28... | Line 28... | ||
28 | 28 | ||
29 | #include |
29 | #include |
30 | #include |
30 | #include |
- | 31 | #include |
|
31 | #include |
32 | #include |
32 | #include |
33 | #include |
33 | #include |
34 | #include |
34 | #include |
35 | #include |
35 | #include "intel_drv.h" |
36 | #include "intel_drv.h" |
Line 64... | Line 65... | ||
64 | static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) |
65 | static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) |
65 | { |
66 | { |
66 | return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base); |
67 | return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base); |
67 | } |
68 | } |
Line 68... | Line 69... | ||
68 | 69 | ||
69 | void intel_dip_infoframe_csum(struct dip_infoframe *frame) |
70 | static u32 g4x_infoframe_index(enum hdmi_infoframe_type type) |
70 | { |
- | |
71 | uint8_t *data = (uint8_t *)frame; |
- | |
72 | uint8_t sum = 0; |
- | |
73 | unsigned i; |
- | |
74 | - | ||
75 | frame->checksum = 0; |
- | |
76 | frame->ecc = 0; |
- | |
77 | - | ||
78 | for (i = 0; i < frame->len + DIP_HEADER_SIZE; i++) |
- | |
79 | sum += data[i]; |
- | |
80 | - | ||
81 | frame->checksum = 0x100 - sum; |
- | |
82 | } |
- | |
83 | - | ||
84 | static u32 g4x_infoframe_index(struct dip_infoframe *frame) |
- | |
85 | { |
71 | { |
86 | switch (frame->type) { |
72 | switch (type) { |
87 | case DIP_TYPE_AVI: |
73 | case HDMI_INFOFRAME_TYPE_AVI: |
88 | return VIDEO_DIP_SELECT_AVI; |
74 | return VIDEO_DIP_SELECT_AVI; |
89 | case DIP_TYPE_SPD: |
75 | case HDMI_INFOFRAME_TYPE_SPD: |
- | 76 | return VIDEO_DIP_SELECT_SPD; |
|
- | 77 | case HDMI_INFOFRAME_TYPE_VENDOR: |
|
90 | return VIDEO_DIP_SELECT_SPD; |
78 | return VIDEO_DIP_SELECT_VENDOR; |
91 | default: |
79 | default: |
92 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
80 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
93 | return 0; |
81 | return 0; |
94 | } |
82 | } |
Line 95... | Line 83... | ||
95 | } |
83 | } |
96 | 84 | ||
97 | static u32 g4x_infoframe_enable(struct dip_infoframe *frame) |
85 | static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type) |
98 | { |
86 | { |
99 | switch (frame->type) { |
87 | switch (type) { |
100 | case DIP_TYPE_AVI: |
88 | case HDMI_INFOFRAME_TYPE_AVI: |
101 | return VIDEO_DIP_ENABLE_AVI; |
89 | return VIDEO_DIP_ENABLE_AVI; |
- | 90 | case HDMI_INFOFRAME_TYPE_SPD: |
|
- | 91 | return VIDEO_DIP_ENABLE_SPD; |
|
102 | case DIP_TYPE_SPD: |
92 | case HDMI_INFOFRAME_TYPE_VENDOR: |
103 | return VIDEO_DIP_ENABLE_SPD; |
93 | return VIDEO_DIP_ENABLE_VENDOR; |
104 | default: |
94 | default: |
105 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
95 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
106 | return 0; |
96 | return 0; |
Line 107... | Line 97... | ||
107 | } |
97 | } |
108 | } |
98 | } |
109 | 99 | ||
110 | static u32 hsw_infoframe_enable(struct dip_infoframe *frame) |
100 | static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type) |
111 | { |
101 | { |
112 | switch (frame->type) { |
102 | switch (type) { |
113 | case DIP_TYPE_AVI: |
103 | case HDMI_INFOFRAME_TYPE_AVI: |
- | 104 | return VIDEO_DIP_ENABLE_AVI_HSW; |
|
- | 105 | case HDMI_INFOFRAME_TYPE_SPD: |
|
114 | return VIDEO_DIP_ENABLE_AVI_HSW; |
106 | return VIDEO_DIP_ENABLE_SPD_HSW; |
115 | case DIP_TYPE_SPD: |
107 | case HDMI_INFOFRAME_TYPE_VENDOR: |
116 | return VIDEO_DIP_ENABLE_SPD_HSW; |
108 | return VIDEO_DIP_ENABLE_VS_HSW; |
117 | default: |
109 | default: |
118 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
110 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
Line 119... | Line 111... | ||
119 | return 0; |
111 | return 0; |
120 | } |
112 | } |
121 | } |
113 | } |
122 | 114 | ||
123 | static u32 hsw_infoframe_data_reg(struct dip_infoframe *frame, |
115 | static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type, |
124 | enum transcoder cpu_transcoder) |
116 | enum transcoder cpu_transcoder) |
125 | { |
117 | { |
126 | switch (frame->type) { |
118 | switch (type) { |
- | 119 | case HDMI_INFOFRAME_TYPE_AVI: |
|
- | 120 | return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); |
|
127 | case DIP_TYPE_AVI: |
121 | case HDMI_INFOFRAME_TYPE_SPD: |
128 | return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); |
122 | return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); |
129 | case DIP_TYPE_SPD: |
123 | case HDMI_INFOFRAME_TYPE_VENDOR: |
130 | return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); |
124 | return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder); |
131 | default: |
125 | default: |
Line 132... | Line 126... | ||
132 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type); |
126 | DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
133 | return 0; |
127 | return 0; |
- | 128 | } |
|
134 | } |
129 | } |
135 | } |
130 | |
136 | 131 | static void g4x_write_infoframe(struct drm_encoder *encoder, |
|
137 | static void g4x_write_infoframe(struct drm_encoder *encoder, |
132 | enum hdmi_infoframe_type type, |
138 | struct dip_infoframe *frame) |
133 | const uint8_t *frame, ssize_t len) |
139 | { |
134 | { |
Line 140... | Line 135... | ||
140 | uint32_t *data = (uint32_t *)frame; |
135 | uint32_t *data = (uint32_t *)frame; |
Line 141... | Line 136... | ||
141 | struct drm_device *dev = encoder->dev; |
136 | struct drm_device *dev = encoder->dev; |
142 | struct drm_i915_private *dev_priv = dev->dev_private; |
137 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 143... | Line 138... | ||
143 | u32 val = I915_READ(VIDEO_DIP_CTL); |
138 | u32 val = I915_READ(VIDEO_DIP_CTL); |
Line 144... | Line 139... | ||
144 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
139 | int i; |
Line 145... | Line 140... | ||
145 | 140 | ||
146 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
141 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
Line 160... | Line 155... | ||
160 | /* Write every possible data byte to force correct ECC calculation. */ |
155 | /* Write every possible data byte to force correct ECC calculation. */ |
161 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
156 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
162 | I915_WRITE(VIDEO_DIP_DATA, 0); |
157 | I915_WRITE(VIDEO_DIP_DATA, 0); |
163 | mmiowb(); |
158 | mmiowb(); |
Line 164... | Line 159... | ||
164 | 159 | ||
165 | val |= g4x_infoframe_enable(frame); |
160 | val |= g4x_infoframe_enable(type); |
166 | val &= ~VIDEO_DIP_FREQ_MASK; |
161 | val &= ~VIDEO_DIP_FREQ_MASK; |
Line 167... | Line 162... | ||
167 | val |= VIDEO_DIP_FREQ_VSYNC; |
162 | val |= VIDEO_DIP_FREQ_VSYNC; |
168 | 163 | ||
169 | I915_WRITE(VIDEO_DIP_CTL, val); |
164 | I915_WRITE(VIDEO_DIP_CTL, val); |
Line 170... | Line 165... | ||
170 | POSTING_READ(VIDEO_DIP_CTL); |
165 | POSTING_READ(VIDEO_DIP_CTL); |
171 | } |
166 | } |
- | 167 | ||
172 | 168 | static void ibx_write_infoframe(struct drm_encoder *encoder, |
|
173 | static void ibx_write_infoframe(struct drm_encoder *encoder, |
169 | enum hdmi_infoframe_type type, |
174 | struct dip_infoframe *frame) |
170 | const uint8_t *frame, ssize_t len) |
175 | { |
171 | { |
176 | uint32_t *data = (uint32_t *)frame; |
172 | uint32_t *data = (uint32_t *)frame; |
177 | struct drm_device *dev = encoder->dev; |
173 | struct drm_device *dev = encoder->dev; |
178 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
179 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
174 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 180... | Line 175... | ||
180 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
175 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
Line 181... | Line 176... | ||
181 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
176 | int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
182 | u32 val = I915_READ(reg); |
177 | u32 val = I915_READ(reg); |
Line 183... | Line 178... | ||
183 | 178 | ||
Line 184... | Line 179... | ||
184 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
179 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
Line 185... | Line 180... | ||
185 | 180 | ||
186 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
181 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
Line 198... | Line 193... | ||
198 | /* Write every possible data byte to force correct ECC calculation. */ |
193 | /* Write every possible data byte to force correct ECC calculation. */ |
199 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
194 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
200 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
195 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
201 | mmiowb(); |
196 | mmiowb(); |
Line 202... | Line 197... | ||
202 | 197 | ||
203 | val |= g4x_infoframe_enable(frame); |
198 | val |= g4x_infoframe_enable(type); |
204 | val &= ~VIDEO_DIP_FREQ_MASK; |
199 | val &= ~VIDEO_DIP_FREQ_MASK; |
Line 205... | Line 200... | ||
205 | val |= VIDEO_DIP_FREQ_VSYNC; |
200 | val |= VIDEO_DIP_FREQ_VSYNC; |
206 | 201 | ||
207 | I915_WRITE(reg, val); |
202 | I915_WRITE(reg, val); |
Line 208... | Line 203... | ||
208 | POSTING_READ(reg); |
203 | POSTING_READ(reg); |
209 | } |
204 | } |
- | 205 | ||
210 | 206 | static void cpt_write_infoframe(struct drm_encoder *encoder, |
|
211 | static void cpt_write_infoframe(struct drm_encoder *encoder, |
207 | enum hdmi_infoframe_type type, |
212 | struct dip_infoframe *frame) |
208 | const uint8_t *frame, ssize_t len) |
213 | { |
209 | { |
214 | uint32_t *data = (uint32_t *)frame; |
210 | uint32_t *data = (uint32_t *)frame; |
215 | struct drm_device *dev = encoder->dev; |
211 | struct drm_device *dev = encoder->dev; |
216 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
217 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
212 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 218... | Line 213... | ||
218 | int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
213 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
Line 219... | Line 214... | ||
219 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
214 | int i, reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
220 | u32 val = I915_READ(reg); |
215 | u32 val = I915_READ(reg); |
Line 221... | Line 216... | ||
221 | 216 | ||
222 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
217 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
223 | 218 | ||
224 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
219 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
Line 225... | Line 220... | ||
225 | val |= g4x_infoframe_index(frame); |
220 | val |= g4x_infoframe_index(type); |
Line 226... | Line 221... | ||
226 | 221 | ||
227 | /* The DIP control register spec says that we need to update the AVI |
222 | /* The DIP control register spec says that we need to update the AVI |
Line 239... | Line 234... | ||
239 | /* Write every possible data byte to force correct ECC calculation. */ |
234 | /* Write every possible data byte to force correct ECC calculation. */ |
240 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
235 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
241 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
236 | I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
242 | mmiowb(); |
237 | mmiowb(); |
Line 243... | Line 238... | ||
243 | 238 | ||
244 | val |= g4x_infoframe_enable(frame); |
239 | val |= g4x_infoframe_enable(type); |
245 | val &= ~VIDEO_DIP_FREQ_MASK; |
240 | val &= ~VIDEO_DIP_FREQ_MASK; |
Line 246... | Line 241... | ||
246 | val |= VIDEO_DIP_FREQ_VSYNC; |
241 | val |= VIDEO_DIP_FREQ_VSYNC; |
247 | 242 | ||
248 | I915_WRITE(reg, val); |
243 | I915_WRITE(reg, val); |
Line 249... | Line 244... | ||
249 | POSTING_READ(reg); |
244 | POSTING_READ(reg); |
250 | } |
245 | } |
- | 246 | ||
251 | 247 | static void vlv_write_infoframe(struct drm_encoder *encoder, |
|
252 | static void vlv_write_infoframe(struct drm_encoder *encoder, |
248 | enum hdmi_infoframe_type type, |
253 | struct dip_infoframe *frame) |
249 | const uint8_t *frame, ssize_t len) |
254 | { |
250 | { |
255 | uint32_t *data = (uint32_t *)frame; |
251 | uint32_t *data = (uint32_t *)frame; |
256 | struct drm_device *dev = encoder->dev; |
252 | struct drm_device *dev = encoder->dev; |
257 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
258 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
253 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 259... | Line 254... | ||
259 | int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
254 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
Line 260... | Line 255... | ||
260 | unsigned i, len = DIP_HEADER_SIZE + frame->len; |
255 | int i, reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
261 | u32 val = I915_READ(reg); |
256 | u32 val = I915_READ(reg); |
Line 262... | Line 257... | ||
262 | 257 | ||
Line 263... | Line 258... | ||
263 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
258 | WARN(!(val & VIDEO_DIP_ENABLE), "Writing DIP with CTL reg disabled\n"); |
Line 264... | Line 259... | ||
264 | 259 | ||
265 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
260 | val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ |
Line 277... | Line 272... | ||
277 | /* Write every possible data byte to force correct ECC calculation. */ |
272 | /* Write every possible data byte to force correct ECC calculation. */ |
278 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
273 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
279 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
274 | I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), 0); |
280 | mmiowb(); |
275 | mmiowb(); |
Line 281... | Line 276... | ||
281 | 276 | ||
282 | val |= g4x_infoframe_enable(frame); |
277 | val |= g4x_infoframe_enable(type); |
283 | val &= ~VIDEO_DIP_FREQ_MASK; |
278 | val &= ~VIDEO_DIP_FREQ_MASK; |
Line 284... | Line 279... | ||
284 | val |= VIDEO_DIP_FREQ_VSYNC; |
279 | val |= VIDEO_DIP_FREQ_VSYNC; |
285 | 280 | ||
286 | I915_WRITE(reg, val); |
281 | I915_WRITE(reg, val); |
Line 287... | Line 282... | ||
287 | POSTING_READ(reg); |
282 | POSTING_READ(reg); |
288 | } |
283 | } |
- | 284 | ||
289 | 285 | static void hsw_write_infoframe(struct drm_encoder *encoder, |
|
290 | static void hsw_write_infoframe(struct drm_encoder *encoder, |
286 | enum hdmi_infoframe_type type, |
291 | struct dip_infoframe *frame) |
287 | const uint8_t *frame, ssize_t len) |
292 | { |
288 | { |
293 | uint32_t *data = (uint32_t *)frame; |
289 | uint32_t *data = (uint32_t *)frame; |
294 | struct drm_device *dev = encoder->dev; |
290 | struct drm_device *dev = encoder->dev; |
295 | struct drm_i915_private *dev_priv = dev->dev_private; |
291 | struct drm_i915_private *dev_priv = dev->dev_private; |
296 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
292 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
297 | u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
293 | u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
Line -... | Line 294... | ||
- | 294 | u32 data_reg; |
|
- | 295 | int i; |
|
298 | u32 data_reg = hsw_infoframe_data_reg(frame, intel_crtc->config.cpu_transcoder); |
296 | u32 val = I915_READ(ctl_reg); |
299 | unsigned int i, len = DIP_HEADER_SIZE + frame->len; |
297 | |
Line 300... | Line 298... | ||
300 | u32 val = I915_READ(ctl_reg); |
298 | data_reg = hsw_infoframe_data_reg(type, |
301 | 299 | intel_crtc->config.cpu_transcoder); |
|
Line 302... | Line 300... | ||
302 | if (data_reg == 0) |
300 | if (data_reg == 0) |
303 | return; |
301 | return; |
304 | 302 | ||
Line 313... | Line 311... | ||
313 | /* Write every possible data byte to force correct ECC calculation. */ |
311 | /* Write every possible data byte to force correct ECC calculation. */ |
314 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
312 | for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
315 | I915_WRITE(data_reg + i, 0); |
313 | I915_WRITE(data_reg + i, 0); |
316 | mmiowb(); |
314 | mmiowb(); |
Line 317... | Line 315... | ||
317 | 315 | ||
318 | val |= hsw_infoframe_enable(frame); |
316 | val |= hsw_infoframe_enable(type); |
319 | I915_WRITE(ctl_reg, val); |
317 | I915_WRITE(ctl_reg, val); |
320 | POSTING_READ(ctl_reg); |
318 | POSTING_READ(ctl_reg); |
Line -... | Line 319... | ||
- | 319 | } |
|
- | 320 | ||
- | 321 | /* |
|
- | 322 | * The data we write to the DIP data buffer registers is 1 byte bigger than the |
|
- | 323 | * HDMI infoframe size because of an ECC/reserved byte at position 3 (starting |
|
- | 324 | * at 0). It's also a byte used by DisplayPort so the same DIP registers can be |
|
- | 325 | * used for both technologies. |
|
- | 326 | * |
|
- | 327 | * DW0: Reserved/ECC/DP | HB2 | HB1 | HB0 |
|
- | 328 | * DW1: DB3 | DB2 | DB1 | DB0 |
|
- | 329 | * DW2: DB7 | DB6 | DB5 | DB4 |
|
- | 330 | * DW3: ... |
|
- | 331 | * |
|
- | 332 | * (HB is Header Byte, DB is Data Byte) |
|
- | 333 | * |
|
- | 334 | * The hdmi pack() functions don't know about that hardware specific hole so we |
|
- | 335 | * trick them by giving an offset into the buffer and moving back the header |
|
321 | } |
336 | * bytes by one. |
322 | 337 | */ |
|
323 | static void intel_set_infoframe(struct drm_encoder *encoder, |
338 | static void intel_write_infoframe(struct drm_encoder *encoder, |
324 | struct dip_infoframe *frame) |
339 | union hdmi_infoframe *frame) |
- | 340 | { |
|
- | 341 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
|
- | 342 | uint8_t buffer[VIDEO_DIP_DATA_SIZE]; |
|
- | 343 | ssize_t len; |
|
- | 344 | ||
- | 345 | /* see comment above for the reason for this offset */ |
|
- | 346 | len = hdmi_infoframe_pack(frame, buffer + 1, sizeof(buffer) - 1); |
|
- | 347 | if (len < 0) |
|
- | 348 | return; |
|
- | 349 | ||
- | 350 | /* Insert the 'hole' (see big comment above) at position 3 */ |
|
- | 351 | buffer[0] = buffer[1]; |
|
- | 352 | buffer[1] = buffer[2]; |
|
- | 353 | buffer[2] = buffer[3]; |
|
Line 325... | Line -... | ||
325 | { |
- | |
326 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
354 | buffer[3] = 0; |
327 | 355 | len++; |
|
Line 328... | Line 356... | ||
328 | intel_dip_infoframe_csum(frame); |
356 | |
329 | intel_hdmi->write_infoframe(encoder, frame); |
357 | intel_hdmi->write_infoframe(encoder, frame->any.type, buffer, len); |
330 | } |
358 | } |
331 | 359 | ||
332 | static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |
360 | static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |
333 | struct drm_display_mode *adjusted_mode) |
361 | struct drm_display_mode *adjusted_mode) |
334 | { |
- | |
335 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
- | |
336 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
- | |
337 | struct dip_infoframe avi_if = { |
362 | { |
Line 338... | Line 363... | ||
338 | .type = DIP_TYPE_AVI, |
363 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
- | 364 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
|
- | 365 | union hdmi_infoframe frame; |
|
339 | .ver = DIP_VERSION_AVI, |
366 | int ret; |
- | 367 | ||
- | 368 | ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, |
|
Line 340... | Line 369... | ||
340 | .len = DIP_LEN_AVI, |
369 | adjusted_mode); |
341 | }; |
370 | if (ret < 0) { |
- | 371 | DRM_ERROR("couldn't fill AVI infoframe\n"); |
|
342 | 372 | return; |
|
343 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) |
373 | } |
- | 374 | ||
344 | avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2; |
375 | if (intel_hdmi->rgb_quant_range_selectable) { |
345 | 376 | if (intel_crtc->config.limited_color_range) |
|
Line 346... | Line -... | ||
346 | if (intel_hdmi->rgb_quant_range_selectable) { |
- | |
347 | if (intel_crtc->config.limited_color_range) |
- | |
348 | avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED; |
377 | frame.avi.quantization_range = |
349 | else |
378 | HDMI_QUANTIZATION_RANGE_LIMITED; |
Line 350... | Line 379... | ||
350 | avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL; |
379 | else |
351 | } |
380 | frame.avi.quantization_range = |
352 | 381 | HDMI_QUANTIZATION_RANGE_FULL; |
|
- | 382 | } |
|
- | 383 | ||
- | 384 | intel_write_infoframe(encoder, &frame); |
|
- | 385 | } |
|
- | 386 | ||
- | 387 | static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) |
|
- | 388 | { |
|
- | 389 | union hdmi_infoframe frame; |
|
- | 390 | int ret; |
|
- | 391 | ||
- | 392 | ret = hdmi_spd_infoframe_init(&frame.spd, "Intel", "Integrated gfx"); |
|
- | 393 | if (ret < 0) { |
|
- | 394 | DRM_ERROR("couldn't fill SPD infoframe\n"); |
|
- | 395 | return; |
|
- | 396 | } |
|
- | 397 | ||
- | 398 | frame.spd.sdi = HDMI_SPD_SDI_PC; |
|
- | 399 | ||
- | 400 | intel_write_infoframe(encoder, &frame); |
|
Line 353... | Line 401... | ||
353 | avi_if.body.avi.VIC = drm_match_cea_mode(adjusted_mode); |
401 | } |
354 | 402 | ||
355 | intel_set_infoframe(encoder, &avi_if); |
403 | static void |
356 | } |
404 | intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder, |
357 | - | ||
358 | static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder) |
- | |
359 | { |
- | |
Line 360... | Line 405... | ||
360 | struct dip_infoframe spd_if; |
405 | struct drm_display_mode *adjusted_mode) |
361 | 406 | { |
|
Line 362... | Line 407... | ||
362 | memset(&spd_if, 0, sizeof(spd_if)); |
407 | union hdmi_infoframe frame; |
363 | spd_if.type = DIP_TYPE_SPD; |
408 | int ret; |
364 | spd_if.ver = DIP_VERSION_SPD; |
409 | |
Line 430... | Line 475... | ||
430 | I915_WRITE(reg, val); |
475 | I915_WRITE(reg, val); |
431 | POSTING_READ(reg); |
476 | POSTING_READ(reg); |
Line 432... | Line 477... | ||
432 | 477 | ||
433 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
478 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
- | 479 | intel_hdmi_set_spd_infoframe(encoder); |
|
434 | intel_hdmi_set_spd_infoframe(encoder); |
480 | intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
Line 435... | Line 481... | ||
435 | } |
481 | } |
436 | 482 | ||
437 | static void ibx_set_infoframes(struct drm_encoder *encoder, |
483 | static void ibx_set_infoframes(struct drm_encoder *encoder, |
Line 491... | Line 537... | ||
491 | I915_WRITE(reg, val); |
537 | I915_WRITE(reg, val); |
492 | POSTING_READ(reg); |
538 | POSTING_READ(reg); |
Line 493... | Line 539... | ||
493 | 539 | ||
494 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
540 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
- | 541 | intel_hdmi_set_spd_infoframe(encoder); |
|
495 | intel_hdmi_set_spd_infoframe(encoder); |
542 | intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
Line 496... | Line 543... | ||
496 | } |
543 | } |
497 | 544 | ||
498 | static void cpt_set_infoframes(struct drm_encoder *encoder, |
545 | static void cpt_set_infoframes(struct drm_encoder *encoder, |
Line 526... | Line 573... | ||
526 | I915_WRITE(reg, val); |
573 | I915_WRITE(reg, val); |
527 | POSTING_READ(reg); |
574 | POSTING_READ(reg); |
Line 528... | Line 575... | ||
528 | 575 | ||
529 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
576 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
- | 577 | intel_hdmi_set_spd_infoframe(encoder); |
|
530 | intel_hdmi_set_spd_infoframe(encoder); |
578 | intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
Line 531... | Line 579... | ||
531 | } |
579 | } |
532 | 580 | ||
533 | static void vlv_set_infoframes(struct drm_encoder *encoder, |
581 | static void vlv_set_infoframes(struct drm_encoder *encoder, |
Line 560... | Line 608... | ||
560 | I915_WRITE(reg, val); |
608 | I915_WRITE(reg, val); |
561 | POSTING_READ(reg); |
609 | POSTING_READ(reg); |
Line 562... | Line 610... | ||
562 | 610 | ||
563 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
611 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
- | 612 | intel_hdmi_set_spd_infoframe(encoder); |
|
564 | intel_hdmi_set_spd_infoframe(encoder); |
613 | intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
Line 565... | Line 614... | ||
565 | } |
614 | } |
566 | 615 | ||
567 | static void hsw_set_infoframes(struct drm_encoder *encoder, |
616 | static void hsw_set_infoframes(struct drm_encoder *encoder, |
Line 587... | Line 636... | ||
587 | I915_WRITE(reg, val); |
636 | I915_WRITE(reg, val); |
588 | POSTING_READ(reg); |
637 | POSTING_READ(reg); |
Line 589... | Line 638... | ||
589 | 638 | ||
590 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
639 | intel_hdmi_set_avi_infoframe(encoder, adjusted_mode); |
- | 640 | intel_hdmi_set_spd_infoframe(encoder); |
|
591 | intel_hdmi_set_spd_infoframe(encoder); |
641 | intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
Line 592... | Line 642... | ||
592 | } |
642 | } |
593 | - | ||
594 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, |
- | |
595 | struct drm_display_mode *mode, |
643 | |
596 | struct drm_display_mode *adjusted_mode) |
644 | static void intel_hdmi_mode_set(struct intel_encoder *encoder) |
597 | { |
645 | { |
598 | struct drm_device *dev = encoder->dev; |
646 | struct drm_device *dev = encoder->base.dev; |
599 | struct drm_i915_private *dev_priv = dev->dev_private; |
647 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | 648 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
|
600 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
649 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
Line 601... | Line 650... | ||
601 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
650 | struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode; |
602 | u32 hdmi_val; |
651 | u32 hdmi_val; |
603 | 652 | ||
604 | hdmi_val = SDVO_ENCODING_HDMI; |
653 | hdmi_val = SDVO_ENCODING_HDMI; |
605 | if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev)) |
654 | if (!HAS_PCH_SPLIT(dev)) |
606 | hdmi_val |= intel_hdmi->color_range; |
655 | hdmi_val |= intel_hdmi->color_range; |
607 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
656 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
Line 608... | Line 657... | ||
608 | hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; |
657 | hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; |
609 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
658 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
610 | hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH; |
659 | hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH; |
611 | 660 | ||
Line 612... | Line 661... | ||
612 | if (intel_crtc->config.pipe_bpp > 24) |
661 | if (crtc->config.pipe_bpp > 24) |
613 | hdmi_val |= HDMI_COLOR_FORMAT_12bpc; |
662 | hdmi_val |= HDMI_COLOR_FORMAT_12bpc; |
614 | else |
663 | else |
Line 615... | Line 664... | ||
615 | hdmi_val |= SDVO_COLOR_FORMAT_8bpc; |
664 | hdmi_val |= SDVO_COLOR_FORMAT_8bpc; |
616 | 665 | ||
617 | /* Required on CPT */ |
666 | /* Required on CPT */ |
618 | if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) |
667 | if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev)) |
619 | hdmi_val |= HDMI_MODE_SELECT_HDMI; |
668 | hdmi_val |= HDMI_MODE_SELECT_HDMI; |
620 | 669 | ||
621 | if (intel_hdmi->has_audio) { |
670 | if (intel_hdmi->has_audio) { |
Line 622... | Line 671... | ||
622 | DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", |
671 | DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", |
623 | pipe_name(intel_crtc->pipe)); |
672 | pipe_name(crtc->pipe)); |
624 | hdmi_val |= SDVO_AUDIO_ENABLE; |
673 | hdmi_val |= SDVO_AUDIO_ENABLE; |
625 | hdmi_val |= HDMI_MODE_SELECT_HDMI; |
674 | hdmi_val |= HDMI_MODE_SELECT_HDMI; |
Line 626... | Line 675... | ||
626 | intel_write_eld(encoder, adjusted_mode); |
675 | intel_write_eld(&encoder->base, adjusted_mode); |
627 | } |
676 | } |
Line 628... | Line 677... | ||
628 | 677 | ||
629 | if (HAS_PCH_CPT(dev)) |
678 | if (HAS_PCH_CPT(dev)) |
Line 630... | Line 679... | ||
630 | hdmi_val |= SDVO_PIPE_SEL_CPT(intel_crtc->pipe); |
679 | hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); |
631 | else |
680 | else |
632 | hdmi_val |= SDVO_PIPE_SEL(intel_crtc->pipe); |
681 | hdmi_val |= SDVO_PIPE_SEL(crtc->pipe); |
Line 656... | Line 705... | ||
656 | *pipe = PORT_TO_PIPE(tmp); |
705 | *pipe = PORT_TO_PIPE(tmp); |
Line 657... | Line 706... | ||
657 | 706 | ||
658 | return true; |
707 | return true; |
Line -... | Line 708... | ||
- | 708 | } |
|
- | 709 | ||
- | 710 | static void intel_hdmi_get_config(struct intel_encoder *encoder, |
|
- | 711 | struct intel_crtc_config *pipe_config) |
|
- | 712 | { |
|
- | 713 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
|
- | 714 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
|
- | 715 | u32 tmp, flags = 0; |
|
- | 716 | ||
- | 717 | tmp = I915_READ(intel_hdmi->hdmi_reg); |
|
- | 718 | ||
- | 719 | if (tmp & SDVO_HSYNC_ACTIVE_HIGH) |
|
- | 720 | flags |= DRM_MODE_FLAG_PHSYNC; |
|
- | 721 | else |
|
- | 722 | flags |= DRM_MODE_FLAG_NHSYNC; |
|
- | 723 | ||
- | 724 | if (tmp & SDVO_VSYNC_ACTIVE_HIGH) |
|
- | 725 | flags |= DRM_MODE_FLAG_PVSYNC; |
|
- | 726 | else |
|
- | 727 | flags |= DRM_MODE_FLAG_NVSYNC; |
|
- | 728 | ||
- | 729 | pipe_config->adjusted_mode.flags |= flags; |
|
659 | } |
730 | } |
660 | 731 | ||
661 | static void intel_enable_hdmi(struct intel_encoder *encoder) |
732 | static void intel_enable_hdmi(struct intel_encoder *encoder) |
662 | { |
733 | { |
663 | struct drm_device *dev = encoder->base.dev; |
734 | struct drm_device *dev = encoder->base.dev; |
Line 697... | Line 768... | ||
697 | I915_WRITE(intel_hdmi->hdmi_reg, temp); |
768 | I915_WRITE(intel_hdmi->hdmi_reg, temp); |
698 | POSTING_READ(intel_hdmi->hdmi_reg); |
769 | POSTING_READ(intel_hdmi->hdmi_reg); |
699 | } |
770 | } |
700 | } |
771 | } |
Line -... | Line 772... | ||
- | 772 | ||
- | 773 | static void vlv_enable_hdmi(struct intel_encoder *encoder) |
|
- | 774 | { |
|
- | 775 | } |
|
701 | 776 | ||
702 | static void intel_disable_hdmi(struct intel_encoder *encoder) |
777 | static void intel_disable_hdmi(struct intel_encoder *encoder) |
703 | { |
778 | { |
704 | struct drm_device *dev = encoder->base.dev; |
779 | struct drm_device *dev = encoder->base.dev; |
705 | struct drm_i915_private *dev_priv = dev->dev_private; |
780 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 753... | Line 828... | ||
753 | I915_WRITE(intel_hdmi->hdmi_reg, temp); |
828 | I915_WRITE(intel_hdmi->hdmi_reg, temp); |
754 | POSTING_READ(intel_hdmi->hdmi_reg); |
829 | POSTING_READ(intel_hdmi->hdmi_reg); |
755 | } |
830 | } |
756 | } |
831 | } |
Line -... | Line 832... | ||
- | 832 | ||
- | 833 | static int hdmi_portclock_limit(struct intel_hdmi *hdmi) |
|
- | 834 | { |
|
- | 835 | struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
|
- | 836 | ||
- | 837 | if (IS_G4X(dev)) |
|
- | 838 | return 165000; |
|
- | 839 | else if (IS_HASWELL(dev)) |
|
- | 840 | return 300000; |
|
- | 841 | else |
|
- | 842 | return 225000; |
|
- | 843 | } |
|
757 | 844 | ||
758 | static int intel_hdmi_mode_valid(struct drm_connector *connector, |
845 | static int intel_hdmi_mode_valid(struct drm_connector *connector, |
759 | struct drm_display_mode *mode) |
846 | struct drm_display_mode *mode) |
760 | { |
847 | { |
761 | if (mode->clock > 165000) |
848 | if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector))) |
762 | return MODE_CLOCK_HIGH; |
849 | return MODE_CLOCK_HIGH; |
763 | if (mode->clock < 20000) |
850 | if (mode->clock < 20000) |
Line 764... | Line 851... | ||
764 | return MODE_CLOCK_LOW; |
851 | return MODE_CLOCK_LOW; |
Line 773... | Line 860... | ||
773 | struct intel_crtc_config *pipe_config) |
860 | struct intel_crtc_config *pipe_config) |
774 | { |
861 | { |
775 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
862 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
776 | struct drm_device *dev = encoder->base.dev; |
863 | struct drm_device *dev = encoder->base.dev; |
777 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
864 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
- | 865 | int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2; |
|
- | 866 | int portclock_limit = hdmi_portclock_limit(intel_hdmi); |
|
- | 867 | int desired_bpp; |
|
Line 778... | Line 868... | ||
778 | 868 | ||
779 | if (intel_hdmi->color_range_auto) { |
869 | if (intel_hdmi->color_range_auto) { |
780 | /* See CEA-861-E - 5.1 Default Encoding Parameters */ |
870 | /* See CEA-861-E - 5.1 Default Encoding Parameters */ |
781 | if (intel_hdmi->has_hdmi_sink && |
871 | if (intel_hdmi->has_hdmi_sink && |
Line 792... | Line 882... | ||
792 | pipe_config->has_pch_encoder = true; |
882 | pipe_config->has_pch_encoder = true; |
Line 793... | Line 883... | ||
793 | 883 | ||
794 | /* |
884 | /* |
795 | * HDMI is either 12 or 8, so if the display lets 10bpc sneak |
885 | * HDMI is either 12 or 8, so if the display lets 10bpc sneak |
- | 886 | * through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi |
|
796 | * through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi |
887 | * outputs. We also need to check that the higher clock still fits |
797 | * outputs. |
888 | * within limits. |
798 | */ |
889 | */ |
- | 890 | if (pipe_config->pipe_bpp > 8*3 && clock_12bpc <= portclock_limit |
|
799 | if (pipe_config->pipe_bpp > 8*3 && HAS_PCH_SPLIT(dev)) { |
891 | && HAS_PCH_SPLIT(dev)) { |
- | 892 | DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); |
|
- | 893 | desired_bpp = 12*3; |
|
- | 894 | ||
800 | DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n"); |
895 | /* Need to adjust the port link by 1.5x for 12bpc. */ |
801 | pipe_config->pipe_bpp = 12*3; |
896 | pipe_config->port_clock = clock_12bpc; |
802 | } else { |
897 | } else { |
- | 898 | DRM_DEBUG_KMS("picking bpc to 8 for HDMI output\n"); |
|
- | 899 | desired_bpp = 8*3; |
|
- | 900 | } |
|
- | 901 | ||
- | 902 | if (!pipe_config->bw_constrained) { |
|
803 | DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n"); |
903 | DRM_DEBUG_KMS("forcing pipe bpc to %i for HDMI\n", desired_bpp); |
- | 904 | pipe_config->pipe_bpp = desired_bpp; |
|
- | 905 | } |
|
- | 906 | ||
- | 907 | if (adjusted_mode->clock > portclock_limit) { |
|
- | 908 | DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n"); |
|
804 | pipe_config->pipe_bpp = 8*3; |
909 | return false; |
Line 805... | Line 910... | ||
805 | } |
910 | } |
806 | 911 | ||
Line 817... | Line 922... | ||
817 | struct intel_encoder *intel_encoder = &intel_dig_port->base; |
922 | struct intel_encoder *intel_encoder = &intel_dig_port->base; |
818 | struct drm_i915_private *dev_priv = dev->dev_private; |
923 | struct drm_i915_private *dev_priv = dev->dev_private; |
819 | struct edid *edid; |
924 | struct edid *edid; |
820 | enum drm_connector_status status = connector_status_disconnected; |
925 | enum drm_connector_status status = connector_status_disconnected; |
Line -... | Line 926... | ||
- | 926 | ||
- | 927 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
|
- | 928 | connector->base.id, drm_get_connector_name(connector)); |
|
821 | 929 | ||
822 | intel_hdmi->has_hdmi_sink = false; |
930 | intel_hdmi->has_hdmi_sink = false; |
823 | intel_hdmi->has_audio = false; |
931 | intel_hdmi->has_audio = false; |
824 | intel_hdmi->rgb_quant_range_selectable = false; |
932 | intel_hdmi->rgb_quant_range_selectable = false; |
825 | edid = drm_get_edid(connector, |
933 | edid = drm_get_edid(connector, |
Line 953... | Line 1061... | ||
953 | intel_crtc_restore_mode(intel_dig_port->base.base.crtc); |
1061 | intel_crtc_restore_mode(intel_dig_port->base.base.crtc); |
Line 954... | Line 1062... | ||
954 | 1062 | ||
955 | return 0; |
1063 | return 0; |
Line -... | Line 1064... | ||
- | 1064 | } |
|
- | 1065 | ||
- | 1066 | static void intel_hdmi_pre_enable(struct intel_encoder *encoder) |
|
- | 1067 | { |
|
- | 1068 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
|
- | 1069 | struct drm_device *dev = encoder->base.dev; |
|
- | 1070 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 1071 | struct intel_crtc *intel_crtc = |
|
- | 1072 | to_intel_crtc(encoder->base.crtc); |
|
- | 1073 | int port = vlv_dport_to_channel(dport); |
|
- | 1074 | int pipe = intel_crtc->pipe; |
|
- | 1075 | u32 val; |
|
- | 1076 | ||
- | 1077 | if (!IS_VALLEYVIEW(dev)) |
|
- | 1078 | return; |
|
- | 1079 | ||
- | 1080 | /* Enable clock channels for this port */ |
|
- | 1081 | mutex_lock(&dev_priv->dpio_lock); |
|
- | 1082 | val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port)); |
|
- | 1083 | val = 0; |
|
- | 1084 | if (pipe) |
|
- | 1085 | val |= (1<<21); |
|
- | 1086 | else |
|
- | 1087 | val &= ~(1<<21); |
|
- | 1088 | val |= 0x001000c4; |
|
- | 1089 | vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val); |
|
- | 1090 | ||
- | 1091 | /* HDMI 1.0V-2dB */ |
|
- | 1092 | vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0); |
|
- | 1093 | vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), |
|
- | 1094 | 0x2b245f5f); |
|
- | 1095 | vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port), |
|
- | 1096 | 0x5578b83a); |
|
- | 1097 | vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), |
|
- | 1098 | 0x0c782040); |
|
- | 1099 | vlv_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(port), |
|
- | 1100 | 0x2b247878); |
|
- | 1101 | vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000); |
|
- | 1102 | vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), |
|
- | 1103 | 0x00002000); |
|
- | 1104 | vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), |
|
- | 1105 | DPIO_TX_OCALINIT_EN); |
|
- | 1106 | ||
- | 1107 | /* Program lane clock */ |
|
- | 1108 | vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port), |
|
- | 1109 | 0x00760018); |
|
- | 1110 | vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port), |
|
- | 1111 | 0x00400888); |
|
- | 1112 | mutex_unlock(&dev_priv->dpio_lock); |
|
- | 1113 | ||
- | 1114 | intel_enable_hdmi(encoder); |
|
- | 1115 | ||
- | 1116 | vlv_wait_port_ready(dev_priv, port); |
|
- | 1117 | } |
|
- | 1118 | ||
- | 1119 | static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder) |
|
- | 1120 | { |
|
- | 1121 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
|
- | 1122 | struct drm_device *dev = encoder->base.dev; |
|
- | 1123 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 1124 | int port = vlv_dport_to_channel(dport); |
|
- | 1125 | ||
- | 1126 | if (!IS_VALLEYVIEW(dev)) |
|
- | 1127 | return; |
|
- | 1128 | ||
- | 1129 | /* Program Tx lane resets to default */ |
|
- | 1130 | mutex_lock(&dev_priv->dpio_lock); |
|
- | 1131 | vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), |
|
- | 1132 | DPIO_PCS_TX_LANE2_RESET | |
|
- | 1133 | DPIO_PCS_TX_LANE1_RESET); |
|
- | 1134 | vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), |
|
- | 1135 | DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | |
|
- | 1136 | DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | |
|
- | 1137 | (1< |
|
- | 1138 | DPIO_PCS_CLK_SOFT_RESET); |
|
- | 1139 | ||
- | 1140 | /* Fix up inter-pair skew failure */ |
|
- | 1141 | vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00); |
|
- | 1142 | vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500); |
|
- | 1143 | vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000); |
|
- | 1144 | ||
- | 1145 | vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), |
|
- | 1146 | 0x00002000); |
|
- | 1147 | vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), |
|
- | 1148 | DPIO_TX_OCALINIT_EN); |
|
- | 1149 | mutex_unlock(&dev_priv->dpio_lock); |
|
- | 1150 | } |
|
- | 1151 | ||
- | 1152 | static void intel_hdmi_post_disable(struct intel_encoder *encoder) |
|
- | 1153 | { |
|
- | 1154 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
|
- | 1155 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
|
- | 1156 | int port = vlv_dport_to_channel(dport); |
|
- | 1157 | ||
- | 1158 | /* Reset lanes to avoid HDMI flicker (VLV w/a) */ |
|
- | 1159 | mutex_lock(&dev_priv->dpio_lock); |
|
- | 1160 | vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), 0x00000000); |
|
- | 1161 | vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), 0x00e00060); |
|
- | 1162 | mutex_unlock(&dev_priv->dpio_lock); |
|
956 | } |
1163 | } |
957 | 1164 | ||
958 | static void intel_hdmi_destroy(struct drm_connector *connector) |
1165 | static void intel_hdmi_destroy(struct drm_connector *connector) |
959 | { |
1166 | { |
960 | drm_sysfs_connector_remove(connector); |
1167 | drm_sysfs_connector_remove(connector); |
961 | drm_connector_cleanup(connector); |
1168 | drm_connector_cleanup(connector); |
Line 962... | Line -... | ||
962 | kfree(connector); |
- | |
963 | } |
- | |
964 | - | ||
965 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { |
- | |
966 | .mode_set = intel_hdmi_mode_set, |
1169 | kfree(connector); |
967 | }; |
1170 | } |
968 | 1171 | ||
969 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
1172 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
970 | .dpms = intel_connector_dpms, |
1173 | .dpms = intel_connector_dpms, |
Line 1068... | Line 1271... | ||
1068 | 1271 | ||
1069 | void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) |
1272 | void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) |
1070 | { |
1273 | { |
1071 | struct intel_digital_port *intel_dig_port; |
1274 | struct intel_digital_port *intel_dig_port; |
1072 | struct intel_encoder *intel_encoder; |
- | |
1073 | struct drm_encoder *encoder; |
1275 | struct intel_encoder *intel_encoder; |
Line 1074... | Line 1276... | ||
1074 | struct intel_connector *intel_connector; |
1276 | struct intel_connector *intel_connector; |
1075 | 1277 | ||
1076 | intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); |
1278 | intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); |
Line 1082... | Line 1284... | ||
1082 | kfree(intel_dig_port); |
1284 | kfree(intel_dig_port); |
1083 | return; |
1285 | return; |
1084 | } |
1286 | } |
Line 1085... | Line 1287... | ||
1085 | 1287 | ||
1086 | intel_encoder = &intel_dig_port->base; |
- | |
Line 1087... | Line 1288... | ||
1087 | encoder = &intel_encoder->base; |
1288 | intel_encoder = &intel_dig_port->base; |
1088 | 1289 | ||
1089 | drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, |
- | |
Line 1090... | Line 1290... | ||
1090 | DRM_MODE_ENCODER_TMDS); |
1290 | drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, |
1091 | drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); |
1291 | DRM_MODE_ENCODER_TMDS); |
1092 | 1292 | ||
1093 | intel_encoder->compute_config = intel_hdmi_compute_config; |
1293 | intel_encoder->compute_config = intel_hdmi_compute_config; |
- | 1294 | intel_encoder->mode_set = intel_hdmi_mode_set; |
|
- | 1295 | intel_encoder->disable = intel_disable_hdmi; |
|
- | 1296 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
|
- | 1297 | intel_encoder->get_config = intel_hdmi_get_config; |
|
- | 1298 | if (IS_VALLEYVIEW(dev)) { |
|
- | 1299 | intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable; |
|
- | 1300 | intel_encoder->pre_enable = intel_hdmi_pre_enable; |
|
- | 1301 | intel_encoder->enable = vlv_enable_hdmi; |
|
- | 1302 | intel_encoder->post_disable = intel_hdmi_post_disable; |
|
Line 1094... | Line 1303... | ||
1094 | intel_encoder->enable = intel_enable_hdmi; |
1303 | } else { |
1095 | intel_encoder->disable = intel_disable_hdmi; |
1304 | intel_encoder->enable = intel_enable_hdmi; |
1096 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
1305 | } |