drm/i915: Use chipset-specific irq installers
[pandora-kernel.git] / drivers / gpu / drm / i915 / intel_hdmi.c
1 /*
2  * Copyright 2006 Dave Airlie <airlied@linux.ie>
3  * Copyright © 2006-2009 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *      Eric Anholt <eric@anholt.net>
26  *      Jesse Barnes <jesse.barnes@intel.com>
27  */
28
29 #include <linux/i2c.h>
30 #include <linux/slab.h>
31 #include <linux/delay.h>
32 #include "drmP.h"
33 #include "drm.h"
34 #include "drm_crtc.h"
35 #include "drm_edid.h"
36 #include "intel_drv.h"
37 #include "i915_drm.h"
38 #include "i915_drv.h"
39
40 struct intel_hdmi {
41         struct intel_encoder base;
42         u32 sdvox_reg;
43         int ddc_bus;
44         uint32_t color_range;
45         bool has_hdmi_sink;
46         bool has_audio;
47         int force_audio;
48 };
49
50 static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
51 {
52         return container_of(encoder, struct intel_hdmi, base.base);
53 }
54
55 static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
56 {
57         return container_of(intel_attached_encoder(connector),
58                             struct intel_hdmi, base);
59 }
60
61 void intel_dip_infoframe_csum(struct dip_infoframe *avi_if)
62 {
63         uint8_t *data = (uint8_t *)avi_if;
64         uint8_t sum = 0;
65         unsigned i;
66
67         avi_if->checksum = 0;
68         avi_if->ecc = 0;
69
70         for (i = 0; i < sizeof(*avi_if); i++)
71                 sum += data[i];
72
73         avi_if->checksum = 0x100 - sum;
74 }
75
76 static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
77 {
78         struct dip_infoframe avi_if = {
79                 .type = DIP_TYPE_AVI,
80                 .ver = DIP_VERSION_AVI,
81                 .len = DIP_LEN_AVI,
82         };
83         uint32_t *data = (uint32_t *)&avi_if;
84         struct drm_device *dev = encoder->dev;
85         struct drm_i915_private *dev_priv = dev->dev_private;
86         struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
87         u32 port;
88         unsigned i;
89
90         if (!intel_hdmi->has_hdmi_sink)
91                 return;
92
93         /* XXX first guess at handling video port, is this corrent? */
94         if (intel_hdmi->sdvox_reg == SDVOB)
95                 port = VIDEO_DIP_PORT_B;
96         else if (intel_hdmi->sdvox_reg == SDVOC)
97                 port = VIDEO_DIP_PORT_C;
98         else
99                 return;
100
101         I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port |
102                    VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC);
103
104         intel_dip_infoframe_csum(&avi_if);
105         for (i = 0; i < sizeof(avi_if); i += 4) {
106                 I915_WRITE(VIDEO_DIP_DATA, *data);
107                 data++;
108         }
109
110         I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | port |
111                    VIDEO_DIP_SELECT_AVI | VIDEO_DIP_FREQ_VSYNC |
112                    VIDEO_DIP_ENABLE_AVI);
113 }
114
115 static void intel_hdmi_mode_set(struct drm_encoder *encoder,
116                                 struct drm_display_mode *mode,
117                                 struct drm_display_mode *adjusted_mode)
118 {
119         struct drm_device *dev = encoder->dev;
120         struct drm_i915_private *dev_priv = dev->dev_private;
121         struct drm_crtc *crtc = encoder->crtc;
122         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
123         struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
124         u32 sdvox;
125
126         sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
127         sdvox |= intel_hdmi->color_range;
128         if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
129                 sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
130         if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
131                 sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
132
133         /* Required on CPT */
134         if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
135                 sdvox |= HDMI_MODE_SELECT;
136
137         if (intel_hdmi->has_audio) {
138                 sdvox |= SDVO_AUDIO_ENABLE;
139                 sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
140         }
141
142         if (intel_crtc->pipe == 1) {
143                 if (HAS_PCH_CPT(dev))
144                         sdvox |= PORT_TRANS_B_SEL_CPT;
145                 else
146                         sdvox |= SDVO_PIPE_B_SELECT;
147         }
148
149         I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
150         POSTING_READ(intel_hdmi->sdvox_reg);
151
152         intel_hdmi_set_avi_infoframe(encoder);
153 }
154
155 static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
156 {
157         struct drm_device *dev = encoder->dev;
158         struct drm_i915_private *dev_priv = dev->dev_private;
159         struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
160         u32 temp;
161
162         temp = I915_READ(intel_hdmi->sdvox_reg);
163
164         /* HW workaround, need to toggle enable bit off and on for 12bpc, but
165          * we do this anyway which shows more stable in testing.
166          */
167         if (HAS_PCH_SPLIT(dev)) {
168                 I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
169                 POSTING_READ(intel_hdmi->sdvox_reg);
170         }
171
172         if (mode != DRM_MODE_DPMS_ON) {
173                 temp &= ~SDVO_ENABLE;
174         } else {
175                 temp |= SDVO_ENABLE;
176         }
177
178         I915_WRITE(intel_hdmi->sdvox_reg, temp);
179         POSTING_READ(intel_hdmi->sdvox_reg);
180
181         /* HW workaround, need to write this twice for issue that may result
182          * in first write getting masked.
183          */
184         if (HAS_PCH_SPLIT(dev)) {
185                 I915_WRITE(intel_hdmi->sdvox_reg, temp);
186                 POSTING_READ(intel_hdmi->sdvox_reg);
187         }
188 }
189
190 static int intel_hdmi_mode_valid(struct drm_connector *connector,
191                                  struct drm_display_mode *mode)
192 {
193         if (mode->clock > 165000)
194                 return MODE_CLOCK_HIGH;
195         if (mode->clock < 20000)
196                 return MODE_CLOCK_LOW;
197
198         if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
199                 return MODE_NO_DBLESCAN;
200
201         return MODE_OK;
202 }
203
204 static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
205                                   struct drm_display_mode *mode,
206                                   struct drm_display_mode *adjusted_mode)
207 {
208         return true;
209 }
210
211 static enum drm_connector_status
212 intel_hdmi_detect(struct drm_connector *connector, bool force)
213 {
214         struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
215         struct drm_i915_private *dev_priv = connector->dev->dev_private;
216         struct edid *edid;
217         enum drm_connector_status status = connector_status_disconnected;
218
219         intel_hdmi->has_hdmi_sink = false;
220         intel_hdmi->has_audio = false;
221         edid = drm_get_edid(connector,
222                             &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
223
224         if (edid) {
225                 if (edid->input & DRM_EDID_INPUT_DIGITAL) {
226                         status = connector_status_connected;
227                         intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
228                         intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
229                 }
230                 connector->display_info.raw_edid = NULL;
231                 kfree(edid);
232         }
233
234         if (status == connector_status_connected) {
235                 if (intel_hdmi->force_audio)
236                         intel_hdmi->has_audio = intel_hdmi->force_audio > 0;
237         }
238
239         return status;
240 }
241
242 static int intel_hdmi_get_modes(struct drm_connector *connector)
243 {
244         struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
245         struct drm_i915_private *dev_priv = connector->dev->dev_private;
246
247         /* We should parse the EDID data and find out if it's an HDMI sink so
248          * we can send audio to it.
249          */
250
251         return intel_ddc_get_modes(connector,
252                                    &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
253 }
254
255 static bool
256 intel_hdmi_detect_audio(struct drm_connector *connector)
257 {
258         struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
259         struct drm_i915_private *dev_priv = connector->dev->dev_private;
260         struct edid *edid;
261         bool has_audio = false;
262
263         edid = drm_get_edid(connector,
264                             &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
265         if (edid) {
266                 if (edid->input & DRM_EDID_INPUT_DIGITAL)
267                         has_audio = drm_detect_monitor_audio(edid);
268
269                 connector->display_info.raw_edid = NULL;
270                 kfree(edid);
271         }
272
273         return has_audio;
274 }
275
276 static int
277 intel_hdmi_set_property(struct drm_connector *connector,
278                       struct drm_property *property,
279                       uint64_t val)
280 {
281         struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
282         struct drm_i915_private *dev_priv = connector->dev->dev_private;
283         int ret;
284
285         ret = drm_connector_property_set_value(connector, property, val);
286         if (ret)
287                 return ret;
288
289         if (property == dev_priv->force_audio_property) {
290                 int i = val;
291                 bool has_audio;
292
293                 if (i == intel_hdmi->force_audio)
294                         return 0;
295
296                 intel_hdmi->force_audio = i;
297
298                 if (i == 0)
299                         has_audio = intel_hdmi_detect_audio(connector);
300                 else
301                         has_audio = i > 0;
302
303                 if (has_audio == intel_hdmi->has_audio)
304                         return 0;
305
306                 intel_hdmi->has_audio = has_audio;
307                 goto done;
308         }
309
310         if (property == dev_priv->broadcast_rgb_property) {
311                 if (val == !!intel_hdmi->color_range)
312                         return 0;
313
314                 intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0;
315                 goto done;
316         }
317
318         return -EINVAL;
319
320 done:
321         if (intel_hdmi->base.base.crtc) {
322                 struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
323                 drm_crtc_helper_set_mode(crtc, &crtc->mode,
324                                          crtc->x, crtc->y,
325                                          crtc->fb);
326         }
327
328         return 0;
329 }
330
331 static void intel_hdmi_destroy(struct drm_connector *connector)
332 {
333         drm_sysfs_connector_remove(connector);
334         drm_connector_cleanup(connector);
335         kfree(connector);
336 }
337
338 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
339         .dpms = intel_hdmi_dpms,
340         .mode_fixup = intel_hdmi_mode_fixup,
341         .prepare = intel_encoder_prepare,
342         .mode_set = intel_hdmi_mode_set,
343         .commit = intel_encoder_commit,
344 };
345
346 static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
347         .dpms = drm_helper_connector_dpms,
348         .detect = intel_hdmi_detect,
349         .fill_modes = drm_helper_probe_single_connector_modes,
350         .set_property = intel_hdmi_set_property,
351         .destroy = intel_hdmi_destroy,
352 };
353
354 static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
355         .get_modes = intel_hdmi_get_modes,
356         .mode_valid = intel_hdmi_mode_valid,
357         .best_encoder = intel_best_encoder,
358 };
359
360 static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
361         .destroy = intel_encoder_destroy,
362 };
363
364 static void
365 intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
366 {
367         intel_attach_force_audio_property(connector);
368         intel_attach_broadcast_rgb_property(connector);
369 }
370
371 void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
372 {
373         struct drm_i915_private *dev_priv = dev->dev_private;
374         struct drm_connector *connector;
375         struct intel_encoder *intel_encoder;
376         struct intel_connector *intel_connector;
377         struct intel_hdmi *intel_hdmi;
378
379         intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
380         if (!intel_hdmi)
381                 return;
382
383         intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
384         if (!intel_connector) {
385                 kfree(intel_hdmi);
386                 return;
387         }
388
389         intel_encoder = &intel_hdmi->base;
390         drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
391                          DRM_MODE_ENCODER_TMDS);
392
393         connector = &intel_connector->base;
394         drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
395                            DRM_MODE_CONNECTOR_HDMIA);
396         drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
397
398         intel_encoder->type = INTEL_OUTPUT_HDMI;
399
400         connector->polled = DRM_CONNECTOR_POLL_HPD;
401         connector->interlace_allowed = 0;
402         connector->doublescan_allowed = 0;
403         intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
404
405         /* Set up the DDC bus. */
406         if (sdvox_reg == SDVOB) {
407                 intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
408                 intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
409                 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
410         } else if (sdvox_reg == SDVOC) {
411                 intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
412                 intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
413                 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
414         } else if (sdvox_reg == HDMIB) {
415                 intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
416                 intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
417                 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
418         } else if (sdvox_reg == HDMIC) {
419                 intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
420                 intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
421                 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
422         } else if (sdvox_reg == HDMID) {
423                 intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
424                 intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
425                 dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
426         }
427
428         intel_hdmi->sdvox_reg = sdvox_reg;
429
430         drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
431
432         intel_hdmi_add_properties(intel_hdmi, connector);
433
434         intel_connector_attach_encoder(intel_connector, intel_encoder);
435         drm_sysfs_connector_add(connector);
436
437         /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
438          * 0xd.  Failure to do so will result in spurious interrupts being
439          * generated on the port when a cable is not attached.
440          */
441         if (IS_G4X(dev) && !IS_GM45(dev)) {
442                 u32 temp = I915_READ(PEG_BAND_GAP_DATA);
443                 I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
444         }
445 }