diff options
author | Eric Anholt <eric@anholt.net> | 2009-01-02 16:33:00 -0500 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2009-01-06 20:49:47 -0500 |
commit | 7d57382e65994ab7d01741373bd1c420370aed9f (patch) | |
tree | b0c3c5f9657a360db60c45b4c4091b7c027a637f /drivers | |
parent | 3f8bc370ac679a5fe5c098f30d3cf8e80f62a9f8 (diff) |
drm/i915: Add support for integrated HDMI on G4X hardware.
This is ported directly from the userland 2D driver code. The HDMI audio bits
aren't hooked up yet.
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 280 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 8 |
7 files changed, 322 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index dd57a5bd4572..793cba39d832 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -13,6 +13,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | |||
13 | intel_crt.o \ | 13 | intel_crt.o \ |
14 | intel_lvds.o \ | 14 | intel_lvds.o \ |
15 | intel_bios.o \ | 15 | intel_bios.o \ |
16 | intel_hdmi.o \ | ||
16 | intel_sdvo.o \ | 17 | intel_sdvo.o \ |
17 | intel_modes.o \ | 18 | intel_modes.o \ |
18 | intel_i2c.o \ | 19 | intel_i2c.o \ |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4756e5cd6b5e..563de18063fd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -664,6 +664,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev); | |||
664 | writel(upper_32_bits(val), dev_priv->regs + \ | 664 | writel(upper_32_bits(val), dev_priv->regs + \ |
665 | (reg) + 4)) | 665 | (reg) + 4)) |
666 | #endif | 666 | #endif |
667 | #define POSTING_READ(reg) (void)I915_READ(reg) | ||
667 | 668 | ||
668 | #define I915_VERBOSE 0 | 669 | #define I915_VERBOSE 0 |
669 | 670 | ||
@@ -760,6 +761,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
760 | IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) | 761 | IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) |
761 | 762 | ||
762 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) | 763 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) |
764 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) | ||
763 | 765 | ||
764 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 766 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
765 | 767 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 47e6bafeb743..102431577dbb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -549,6 +549,8 @@ | |||
549 | /** GM965 GM45 render standby register */ | 549 | /** GM965 GM45 render standby register */ |
550 | #define MCHBAR_RENDER_STANDBY 0x111B8 | 550 | #define MCHBAR_RENDER_STANDBY 0x111B8 |
551 | 551 | ||
552 | #define PEG_BAND_GAP_DATA 0x14d68 | ||
553 | |||
552 | /* | 554 | /* |
553 | * Overlay regs | 555 | * Overlay regs |
554 | */ | 556 | */ |
@@ -612,6 +614,9 @@ | |||
612 | 614 | ||
613 | /* Hotplug control (945+ only) */ | 615 | /* Hotplug control (945+ only) */ |
614 | #define PORT_HOTPLUG_EN 0x61110 | 616 | #define PORT_HOTPLUG_EN 0x61110 |
617 | #define HDMIB_HOTPLUG_INT_EN (1 << 29) | ||
618 | #define HDMIC_HOTPLUG_INT_EN (1 << 28) | ||
619 | #define HDMID_HOTPLUG_INT_EN (1 << 27) | ||
615 | #define SDVOB_HOTPLUG_INT_EN (1 << 26) | 620 | #define SDVOB_HOTPLUG_INT_EN (1 << 26) |
616 | #define SDVOC_HOTPLUG_INT_EN (1 << 25) | 621 | #define SDVOC_HOTPLUG_INT_EN (1 << 25) |
617 | #define TV_HOTPLUG_INT_EN (1 << 18) | 622 | #define TV_HOTPLUG_INT_EN (1 << 18) |
@@ -619,6 +624,9 @@ | |||
619 | #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) | 624 | #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) |
620 | 625 | ||
621 | #define PORT_HOTPLUG_STAT 0x61114 | 626 | #define PORT_HOTPLUG_STAT 0x61114 |
627 | #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) | ||
628 | #define HDMIC_HOTPLUG_INT_STATUS (1 << 28) | ||
629 | #define HDMID_HOTPLUG_INT_STATUS (1 << 27) | ||
622 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) | 630 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) |
623 | #define TV_HOTPLUG_INT_STATUS (1 << 10) | 631 | #define TV_HOTPLUG_INT_STATUS (1 << 10) |
624 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) | 632 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) |
@@ -648,7 +656,16 @@ | |||
648 | #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) | 656 | #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) |
649 | #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) | 657 | #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) |
650 | #define SDVOC_GANG_MODE (1 << 16) | 658 | #define SDVOC_GANG_MODE (1 << 16) |
659 | #define SDVO_ENCODING_SDVO (0x0 << 10) | ||
660 | #define SDVO_ENCODING_HDMI (0x2 << 10) | ||
661 | /** Requird for HDMI operation */ | ||
662 | #define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) | ||
651 | #define SDVO_BORDER_ENABLE (1 << 7) | 663 | #define SDVO_BORDER_ENABLE (1 << 7) |
664 | #define SDVO_AUDIO_ENABLE (1 << 6) | ||
665 | /** New with 965, default is to be set */ | ||
666 | #define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) | ||
667 | /** New with 965, default is to be set */ | ||
668 | #define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) | ||
652 | #define SDVOB_PCIE_CONCURRENCY (1 << 3) | 669 | #define SDVOB_PCIE_CONCURRENCY (1 << 3) |
653 | #define SDVO_DETECTED (1 << 2) | 670 | #define SDVO_DETECTED (1 << 2) |
654 | /* Bits to be preserved when writing */ | 671 | /* Bits to be preserved when writing */ |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1204d26b50db..67d06fd29d8c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -751,6 +751,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
751 | is_lvds = true; | 751 | is_lvds = true; |
752 | break; | 752 | break; |
753 | case INTEL_OUTPUT_SDVO: | 753 | case INTEL_OUTPUT_SDVO: |
754 | case INTEL_OUTPUT_HDMI: | ||
754 | is_sdvo = true; | 755 | is_sdvo = true; |
755 | break; | 756 | break; |
756 | case INTEL_OUTPUT_DVO: | 757 | case INTEL_OUTPUT_DVO: |
@@ -1443,8 +1444,15 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
1443 | intel_lvds_init(dev); | 1444 | intel_lvds_init(dev); |
1444 | 1445 | ||
1445 | if (IS_I9XX(dev)) { | 1446 | if (IS_I9XX(dev)) { |
1446 | intel_sdvo_init(dev, SDVOB); | 1447 | int found; |
1447 | intel_sdvo_init(dev, SDVOC); | 1448 | |
1449 | found = intel_sdvo_init(dev, SDVOB); | ||
1450 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | ||
1451 | intel_hdmi_init(dev, SDVOB); | ||
1452 | |||
1453 | found = intel_sdvo_init(dev, SDVOC); | ||
1454 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | ||
1455 | intel_hdmi_init(dev, SDVOC); | ||
1448 | } else | 1456 | } else |
1449 | intel_dvo_init(dev); | 1457 | intel_dvo_init(dev); |
1450 | 1458 | ||
@@ -1458,6 +1466,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
1458 | 1466 | ||
1459 | /* valid crtcs */ | 1467 | /* valid crtcs */ |
1460 | switch(intel_output->type) { | 1468 | switch(intel_output->type) { |
1469 | case INTEL_OUTPUT_HDMI: | ||
1470 | crtc_mask = ((1 << 0)| | ||
1471 | (1 << 1)); | ||
1472 | clone_mask = ((1 << INTEL_OUTPUT_HDMI)); | ||
1473 | break; | ||
1461 | case INTEL_OUTPUT_DVO: | 1474 | case INTEL_OUTPUT_DVO: |
1462 | case INTEL_OUTPUT_SDVO: | 1475 | case INTEL_OUTPUT_SDVO: |
1463 | crtc_mask = ((1 << 0)| | 1476 | crtc_mask = ((1 << 0)| |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 94981ee7b8bd..8a4cc50c5b4e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define INTEL_OUTPUT_SDVO 3 | 53 | #define INTEL_OUTPUT_SDVO 3 |
54 | #define INTEL_OUTPUT_LVDS 4 | 54 | #define INTEL_OUTPUT_LVDS 4 |
55 | #define INTEL_OUTPUT_TVOUT 5 | 55 | #define INTEL_OUTPUT_TVOUT 5 |
56 | #define INTEL_OUTPUT_HDMI 6 | ||
56 | 57 | ||
57 | #define INTEL_DVO_CHIP_NONE 0 | 58 | #define INTEL_DVO_CHIP_NONE 0 |
58 | #define INTEL_DVO_CHIP_LVDS 1 | 59 | #define INTEL_DVO_CHIP_LVDS 1 |
@@ -109,7 +110,8 @@ int intel_ddc_get_modes(struct intel_output *intel_output); | |||
109 | extern bool intel_ddc_probe(struct intel_output *intel_output); | 110 | extern bool intel_ddc_probe(struct intel_output *intel_output); |
110 | 111 | ||
111 | extern void intel_crt_init(struct drm_device *dev); | 112 | extern void intel_crt_init(struct drm_device *dev); |
112 | extern void intel_sdvo_init(struct drm_device *dev, int output_device); | 113 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); |
114 | extern bool intel_sdvo_init(struct drm_device *dev, int output_device); | ||
113 | extern void intel_dvo_init(struct drm_device *dev); | 115 | extern void intel_dvo_init(struct drm_device *dev); |
114 | extern void intel_tv_init(struct drm_device *dev); | 116 | extern void intel_tv_init(struct drm_device *dev); |
115 | extern void intel_lvds_init(struct drm_device *dev); | 117 | extern void intel_lvds_init(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c new file mode 100644 index 000000000000..b06a4a3ff08d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -0,0 +1,280 @@ | |||
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/delay.h> | ||
31 | #include "drmP.h" | ||
32 | #include "drm.h" | ||
33 | #include "drm_crtc.h" | ||
34 | #include "intel_drv.h" | ||
35 | #include "i915_drm.h" | ||
36 | #include "i915_drv.h" | ||
37 | |||
38 | struct intel_hdmi_priv { | ||
39 | u32 sdvox_reg; | ||
40 | u32 save_SDVOX; | ||
41 | int has_hdmi_sink; | ||
42 | }; | ||
43 | |||
44 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, | ||
45 | struct drm_display_mode *mode, | ||
46 | struct drm_display_mode *adjusted_mode) | ||
47 | { | ||
48 | struct drm_device *dev = encoder->dev; | ||
49 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
50 | struct drm_crtc *crtc = encoder->crtc; | ||
51 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
52 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
53 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
54 | u32 sdvox; | ||
55 | |||
56 | sdvox = SDVO_ENCODING_HDMI | | ||
57 | SDVO_BORDER_ENABLE | | ||
58 | SDVO_VSYNC_ACTIVE_HIGH | | ||
59 | SDVO_HSYNC_ACTIVE_HIGH; | ||
60 | |||
61 | if (hdmi_priv->has_hdmi_sink) | ||
62 | sdvox |= SDVO_AUDIO_ENABLE; | ||
63 | |||
64 | if (intel_crtc->pipe == 1) | ||
65 | sdvox |= SDVO_PIPE_B_SELECT; | ||
66 | |||
67 | I915_WRITE(hdmi_priv->sdvox_reg, sdvox); | ||
68 | POSTING_READ(hdmi_priv->sdvox_reg); | ||
69 | } | ||
70 | |||
71 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | ||
72 | { | ||
73 | struct drm_device *dev = encoder->dev; | ||
74 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
75 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
76 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
77 | u32 temp; | ||
78 | |||
79 | if (mode != DRM_MODE_DPMS_ON) { | ||
80 | temp = I915_READ(hdmi_priv->sdvox_reg); | ||
81 | I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); | ||
82 | } else { | ||
83 | temp = I915_READ(hdmi_priv->sdvox_reg); | ||
84 | I915_WRITE(hdmi_priv->sdvox_reg, temp | SDVO_ENABLE); | ||
85 | } | ||
86 | POSTING_READ(hdmi_priv->sdvox_reg); | ||
87 | } | ||
88 | |||
89 | static void intel_hdmi_save(struct drm_connector *connector) | ||
90 | { | ||
91 | struct drm_device *dev = connector->dev; | ||
92 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
93 | struct intel_output *intel_output = to_intel_output(connector); | ||
94 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
95 | |||
96 | hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg); | ||
97 | } | ||
98 | |||
99 | static void intel_hdmi_restore(struct drm_connector *connector) | ||
100 | { | ||
101 | struct drm_device *dev = connector->dev; | ||
102 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
103 | struct intel_output *intel_output = to_intel_output(connector); | ||
104 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
105 | |||
106 | I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX); | ||
107 | POSTING_READ(hdmi_priv->sdvox_reg); | ||
108 | } | ||
109 | |||
110 | static int intel_hdmi_mode_valid(struct drm_connector *connector, | ||
111 | struct drm_display_mode *mode) | ||
112 | { | ||
113 | if (mode->clock > 165000) | ||
114 | return MODE_CLOCK_HIGH; | ||
115 | if (mode->clock < 20000) | ||
116 | return MODE_CLOCK_HIGH; | ||
117 | |||
118 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
119 | return MODE_NO_DBLESCAN; | ||
120 | |||
121 | return MODE_OK; | ||
122 | } | ||
123 | |||
124 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | ||
125 | struct drm_display_mode *mode, | ||
126 | struct drm_display_mode *adjusted_mode) | ||
127 | { | ||
128 | return true; | ||
129 | } | ||
130 | |||
131 | static enum drm_connector_status | ||
132 | intel_hdmi_detect(struct drm_connector *connector) | ||
133 | { | ||
134 | struct drm_device *dev = connector->dev; | ||
135 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
136 | struct intel_output *intel_output = to_intel_output(connector); | ||
137 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
138 | u32 temp, bit; | ||
139 | |||
140 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
141 | |||
142 | I915_WRITE(PORT_HOTPLUG_EN, | ||
143 | temp | | ||
144 | HDMIB_HOTPLUG_INT_EN | | ||
145 | HDMIC_HOTPLUG_INT_EN | | ||
146 | HDMID_HOTPLUG_INT_EN); | ||
147 | |||
148 | POSTING_READ(PORT_HOTPLUG_EN); | ||
149 | |||
150 | switch (hdmi_priv->sdvox_reg) { | ||
151 | case SDVOB: | ||
152 | bit = HDMIB_HOTPLUG_INT_STATUS; | ||
153 | break; | ||
154 | case SDVOC: | ||
155 | bit = HDMIC_HOTPLUG_INT_STATUS; | ||
156 | break; | ||
157 | default: | ||
158 | return connector_status_unknown; | ||
159 | } | ||
160 | |||
161 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) | ||
162 | return connector_status_connected; | ||
163 | else | ||
164 | return connector_status_disconnected; | ||
165 | } | ||
166 | |||
167 | static int intel_hdmi_get_modes(struct drm_connector *connector) | ||
168 | { | ||
169 | struct intel_output *intel_output = to_intel_output(connector); | ||
170 | |||
171 | /* We should parse the EDID data and find out if it's an HDMI sink so | ||
172 | * we can send audio to it. | ||
173 | */ | ||
174 | |||
175 | return intel_ddc_get_modes(intel_output); | ||
176 | } | ||
177 | |||
178 | static void intel_hdmi_destroy(struct drm_connector *connector) | ||
179 | { | ||
180 | struct intel_output *intel_output = to_intel_output(connector); | ||
181 | |||
182 | if (intel_output->i2c_bus) | ||
183 | intel_i2c_destroy(intel_output->i2c_bus); | ||
184 | drm_sysfs_connector_remove(connector); | ||
185 | drm_connector_cleanup(connector); | ||
186 | kfree(intel_output); | ||
187 | } | ||
188 | |||
189 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { | ||
190 | .dpms = intel_hdmi_dpms, | ||
191 | .mode_fixup = intel_hdmi_mode_fixup, | ||
192 | .prepare = intel_encoder_prepare, | ||
193 | .mode_set = intel_hdmi_mode_set, | ||
194 | .commit = intel_encoder_commit, | ||
195 | }; | ||
196 | |||
197 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | ||
198 | .save = intel_hdmi_save, | ||
199 | .restore = intel_hdmi_restore, | ||
200 | .detect = intel_hdmi_detect, | ||
201 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
202 | .destroy = intel_hdmi_destroy, | ||
203 | }; | ||
204 | |||
205 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { | ||
206 | .get_modes = intel_hdmi_get_modes, | ||
207 | .mode_valid = intel_hdmi_mode_valid, | ||
208 | .best_encoder = intel_best_encoder, | ||
209 | }; | ||
210 | |||
211 | static void intel_hdmi_enc_destroy(struct drm_encoder *encoder) | ||
212 | { | ||
213 | drm_encoder_cleanup(encoder); | ||
214 | } | ||
215 | |||
216 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | ||
217 | .destroy = intel_hdmi_enc_destroy, | ||
218 | }; | ||
219 | |||
220 | |||
221 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | ||
222 | { | ||
223 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
224 | struct drm_connector *connector; | ||
225 | struct intel_output *intel_output; | ||
226 | struct intel_hdmi_priv *hdmi_priv; | ||
227 | |||
228 | intel_output = kcalloc(sizeof(struct intel_output) + | ||
229 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); | ||
230 | if (!intel_output) | ||
231 | return; | ||
232 | hdmi_priv = (struct intel_hdmi_priv *)(intel_output + 1); | ||
233 | |||
234 | connector = &intel_output->base; | ||
235 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, | ||
236 | DRM_MODE_CONNECTOR_DVID); | ||
237 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); | ||
238 | |||
239 | intel_output->type = INTEL_OUTPUT_HDMI; | ||
240 | |||
241 | connector->interlace_allowed = 0; | ||
242 | connector->doublescan_allowed = 0; | ||
243 | |||
244 | /* Set up the DDC bus. */ | ||
245 | if (sdvox_reg == SDVOB) | ||
246 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); | ||
247 | else | ||
248 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); | ||
249 | |||
250 | if (!intel_output->ddc_bus) | ||
251 | goto err_connector; | ||
252 | |||
253 | hdmi_priv->sdvox_reg = sdvox_reg; | ||
254 | intel_output->dev_priv = hdmi_priv; | ||
255 | |||
256 | drm_encoder_init(dev, &intel_output->enc, &intel_hdmi_enc_funcs, | ||
257 | DRM_MODE_ENCODER_TMDS); | ||
258 | drm_encoder_helper_add(&intel_output->enc, &intel_hdmi_helper_funcs); | ||
259 | |||
260 | drm_mode_connector_attach_encoder(&intel_output->base, | ||
261 | &intel_output->enc); | ||
262 | drm_sysfs_connector_add(connector); | ||
263 | |||
264 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | ||
265 | * 0xd. Failure to do so will result in spurious interrupts being | ||
266 | * generated on the port when a cable is not attached. | ||
267 | */ | ||
268 | if (IS_G4X(dev) && !IS_GM45(dev)) { | ||
269 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | ||
270 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | ||
271 | } | ||
272 | |||
273 | return; | ||
274 | |||
275 | err_connector: | ||
276 | drm_connector_cleanup(connector); | ||
277 | kfree(intel_output); | ||
278 | |||
279 | return; | ||
280 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index fbbaa4f414a0..407215469102 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -978,7 +978,7 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { | |||
978 | }; | 978 | }; |
979 | 979 | ||
980 | 980 | ||
981 | void intel_sdvo_init(struct drm_device *dev, int output_device) | 981 | bool intel_sdvo_init(struct drm_device *dev, int output_device) |
982 | { | 982 | { |
983 | struct drm_connector *connector; | 983 | struct drm_connector *connector; |
984 | struct intel_output *intel_output; | 984 | struct intel_output *intel_output; |
@@ -991,7 +991,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) | |||
991 | 991 | ||
992 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 992 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
993 | if (!intel_output) { | 993 | if (!intel_output) { |
994 | return; | 994 | return false; |
995 | } | 995 | } |
996 | 996 | ||
997 | connector = &intel_output->base; | 997 | connector = &intel_output->base; |
@@ -1116,7 +1116,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1116 | 1116 | ||
1117 | intel_output->ddc_bus = i2cbus; | 1117 | intel_output->ddc_bus = i2cbus; |
1118 | 1118 | ||
1119 | return; | 1119 | return true; |
1120 | 1120 | ||
1121 | err_i2c: | 1121 | err_i2c: |
1122 | intel_i2c_destroy(intel_output->i2c_bus); | 1122 | intel_i2c_destroy(intel_output->i2c_bus); |
@@ -1124,5 +1124,5 @@ err_connector: | |||
1124 | drm_connector_cleanup(connector); | 1124 | drm_connector_cleanup(connector); |
1125 | kfree(intel_output); | 1125 | kfree(intel_output); |
1126 | 1126 | ||
1127 | return; | 1127 | return false; |
1128 | } | 1128 | } |