diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 97 |
1 files changed, 51 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c33451aec1bd..48cade0cf7b1 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -27,6 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <linux/slab.h> | ||
30 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
31 | #include "drmP.h" | 32 | #include "drmP.h" |
32 | #include "drm.h" | 33 | #include "drm.h" |
@@ -50,8 +51,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
50 | struct drm_i915_private *dev_priv = dev->dev_private; | 51 | struct drm_i915_private *dev_priv = dev->dev_private; |
51 | struct drm_crtc *crtc = encoder->crtc; | 52 | struct drm_crtc *crtc = encoder->crtc; |
52 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 53 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
53 | struct intel_output *intel_output = enc_to_intel_output(encoder); | 54 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); |
54 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 55 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; |
55 | u32 sdvox; | 56 | u32 sdvox; |
56 | 57 | ||
57 | sdvox = SDVO_ENCODING_HDMI | | 58 | sdvox = SDVO_ENCODING_HDMI | |
@@ -73,8 +74,8 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
73 | { | 74 | { |
74 | struct drm_device *dev = encoder->dev; | 75 | struct drm_device *dev = encoder->dev; |
75 | struct drm_i915_private *dev_priv = dev->dev_private; | 76 | struct drm_i915_private *dev_priv = dev->dev_private; |
76 | struct intel_output *intel_output = enc_to_intel_output(encoder); | 77 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); |
77 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 78 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; |
78 | u32 temp; | 79 | u32 temp; |
79 | 80 | ||
80 | temp = I915_READ(hdmi_priv->sdvox_reg); | 81 | temp = I915_READ(hdmi_priv->sdvox_reg); |
@@ -82,7 +83,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
82 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but | 83 | /* HW workaround, need to toggle enable bit off and on for 12bpc, but |
83 | * we do this anyway which shows more stable in testing. | 84 | * we do this anyway which shows more stable in testing. |
84 | */ | 85 | */ |
85 | if (IS_IGDNG(dev)) { | 86 | if (HAS_PCH_SPLIT(dev)) { |
86 | I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); | 87 | I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); |
87 | POSTING_READ(hdmi_priv->sdvox_reg); | 88 | POSTING_READ(hdmi_priv->sdvox_reg); |
88 | } | 89 | } |
@@ -99,7 +100,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
99 | /* HW workaround, need to write this twice for issue that may result | 100 | /* HW workaround, need to write this twice for issue that may result |
100 | * in first write getting masked. | 101 | * in first write getting masked. |
101 | */ | 102 | */ |
102 | if (IS_IGDNG(dev)) { | 103 | if (HAS_PCH_SPLIT(dev)) { |
103 | I915_WRITE(hdmi_priv->sdvox_reg, temp); | 104 | I915_WRITE(hdmi_priv->sdvox_reg, temp); |
104 | POSTING_READ(hdmi_priv->sdvox_reg); | 105 | POSTING_READ(hdmi_priv->sdvox_reg); |
105 | } | 106 | } |
@@ -109,8 +110,8 @@ static void intel_hdmi_save(struct drm_connector *connector) | |||
109 | { | 110 | { |
110 | struct drm_device *dev = connector->dev; | 111 | struct drm_device *dev = connector->dev; |
111 | struct drm_i915_private *dev_priv = dev->dev_private; | 112 | struct drm_i915_private *dev_priv = dev->dev_private; |
112 | struct intel_output *intel_output = to_intel_output(connector); | 113 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
113 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 114 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; |
114 | 115 | ||
115 | hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg); | 116 | hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg); |
116 | } | 117 | } |
@@ -119,8 +120,8 @@ static void intel_hdmi_restore(struct drm_connector *connector) | |||
119 | { | 120 | { |
120 | struct drm_device *dev = connector->dev; | 121 | struct drm_device *dev = connector->dev; |
121 | struct drm_i915_private *dev_priv = dev->dev_private; | 122 | struct drm_i915_private *dev_priv = dev->dev_private; |
122 | struct intel_output *intel_output = to_intel_output(connector); | 123 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
123 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 124 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; |
124 | 125 | ||
125 | I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX); | 126 | I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX); |
126 | POSTING_READ(hdmi_priv->sdvox_reg); | 127 | POSTING_READ(hdmi_priv->sdvox_reg); |
@@ -150,21 +151,21 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
150 | static enum drm_connector_status | 151 | static enum drm_connector_status |
151 | intel_hdmi_detect(struct drm_connector *connector) | 152 | intel_hdmi_detect(struct drm_connector *connector) |
152 | { | 153 | { |
153 | struct intel_output *intel_output = to_intel_output(connector); | 154 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
154 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 155 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; |
155 | struct edid *edid = NULL; | 156 | struct edid *edid = NULL; |
156 | enum drm_connector_status status = connector_status_disconnected; | 157 | enum drm_connector_status status = connector_status_disconnected; |
157 | 158 | ||
158 | hdmi_priv->has_hdmi_sink = false; | 159 | hdmi_priv->has_hdmi_sink = false; |
159 | edid = drm_get_edid(&intel_output->base, | 160 | edid = drm_get_edid(&intel_encoder->base, |
160 | intel_output->ddc_bus); | 161 | intel_encoder->ddc_bus); |
161 | 162 | ||
162 | if (edid) { | 163 | if (edid) { |
163 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { | 164 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
164 | status = connector_status_connected; | 165 | status = connector_status_connected; |
165 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | 166 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); |
166 | } | 167 | } |
167 | intel_output->base.display_info.raw_edid = NULL; | 168 | intel_encoder->base.display_info.raw_edid = NULL; |
168 | kfree(edid); | 169 | kfree(edid); |
169 | } | 170 | } |
170 | 171 | ||
@@ -173,24 +174,24 @@ intel_hdmi_detect(struct drm_connector *connector) | |||
173 | 174 | ||
174 | static int intel_hdmi_get_modes(struct drm_connector *connector) | 175 | static int intel_hdmi_get_modes(struct drm_connector *connector) |
175 | { | 176 | { |
176 | struct intel_output *intel_output = to_intel_output(connector); | 177 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
177 | 178 | ||
178 | /* We should parse the EDID data and find out if it's an HDMI sink so | 179 | /* We should parse the EDID data and find out if it's an HDMI sink so |
179 | * we can send audio to it. | 180 | * we can send audio to it. |
180 | */ | 181 | */ |
181 | 182 | ||
182 | return intel_ddc_get_modes(intel_output); | 183 | return intel_ddc_get_modes(intel_encoder); |
183 | } | 184 | } |
184 | 185 | ||
185 | static void intel_hdmi_destroy(struct drm_connector *connector) | 186 | static void intel_hdmi_destroy(struct drm_connector *connector) |
186 | { | 187 | { |
187 | struct intel_output *intel_output = to_intel_output(connector); | 188 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
188 | 189 | ||
189 | if (intel_output->i2c_bus) | 190 | if (intel_encoder->i2c_bus) |
190 | intel_i2c_destroy(intel_output->i2c_bus); | 191 | intel_i2c_destroy(intel_encoder->i2c_bus); |
191 | drm_sysfs_connector_remove(connector); | 192 | drm_sysfs_connector_remove(connector); |
192 | drm_connector_cleanup(connector); | 193 | drm_connector_cleanup(connector); |
193 | kfree(intel_output); | 194 | kfree(intel_encoder); |
194 | } | 195 | } |
195 | 196 | ||
196 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { | 197 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { |
@@ -225,63 +226,67 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | |||
225 | .destroy = intel_hdmi_enc_destroy, | 226 | .destroy = intel_hdmi_enc_destroy, |
226 | }; | 227 | }; |
227 | 228 | ||
228 | |||
229 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | 229 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) |
230 | { | 230 | { |
231 | struct drm_i915_private *dev_priv = dev->dev_private; | 231 | struct drm_i915_private *dev_priv = dev->dev_private; |
232 | struct drm_connector *connector; | 232 | struct drm_connector *connector; |
233 | struct intel_output *intel_output; | 233 | struct intel_encoder *intel_encoder; |
234 | struct intel_hdmi_priv *hdmi_priv; | 234 | struct intel_hdmi_priv *hdmi_priv; |
235 | 235 | ||
236 | intel_output = kcalloc(sizeof(struct intel_output) + | 236 | intel_encoder = kcalloc(sizeof(struct intel_encoder) + |
237 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); | 237 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); |
238 | if (!intel_output) | 238 | if (!intel_encoder) |
239 | return; | 239 | return; |
240 | hdmi_priv = (struct intel_hdmi_priv *)(intel_output + 1); | 240 | hdmi_priv = (struct intel_hdmi_priv *)(intel_encoder + 1); |
241 | 241 | ||
242 | connector = &intel_output->base; | 242 | connector = &intel_encoder->base; |
243 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, | 243 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
244 | DRM_MODE_CONNECTOR_HDMIA); | 244 | DRM_MODE_CONNECTOR_HDMIA); |
245 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); | 245 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
246 | 246 | ||
247 | intel_output->type = INTEL_OUTPUT_HDMI; | 247 | intel_encoder->type = INTEL_OUTPUT_HDMI; |
248 | 248 | ||
249 | connector->interlace_allowed = 0; | 249 | connector->interlace_allowed = 0; |
250 | connector->doublescan_allowed = 0; | 250 | connector->doublescan_allowed = 0; |
251 | intel_output->crtc_mask = (1 << 0) | (1 << 1); | 251 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
252 | 252 | ||
253 | /* Set up the DDC bus. */ | 253 | /* Set up the DDC bus. */ |
254 | if (sdvox_reg == SDVOB) { | 254 | if (sdvox_reg == SDVOB) { |
255 | intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); | 255 | intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); |
256 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); | 256 | intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); |
257 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; | ||
257 | } else if (sdvox_reg == SDVOC) { | 258 | } else if (sdvox_reg == SDVOC) { |
258 | intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); | 259 | intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); |
259 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); | 260 | intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); |
261 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; | ||
260 | } else if (sdvox_reg == HDMIB) { | 262 | } else if (sdvox_reg == HDMIB) { |
261 | intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); | 263 | intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); |
262 | intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, | 264 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, |
263 | "HDMIB"); | 265 | "HDMIB"); |
266 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; | ||
264 | } else if (sdvox_reg == HDMIC) { | 267 | } else if (sdvox_reg == HDMIC) { |
265 | intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); | 268 | intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); |
266 | intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, | 269 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, |
267 | "HDMIC"); | 270 | "HDMIC"); |
271 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; | ||
268 | } else if (sdvox_reg == HDMID) { | 272 | } else if (sdvox_reg == HDMID) { |
269 | intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); | 273 | intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); |
270 | intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, | 274 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, |
271 | "HDMID"); | 275 | "HDMID"); |
276 | dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; | ||
272 | } | 277 | } |
273 | if (!intel_output->ddc_bus) | 278 | if (!intel_encoder->ddc_bus) |
274 | goto err_connector; | 279 | goto err_connector; |
275 | 280 | ||
276 | hdmi_priv->sdvox_reg = sdvox_reg; | 281 | hdmi_priv->sdvox_reg = sdvox_reg; |
277 | intel_output->dev_priv = hdmi_priv; | 282 | intel_encoder->dev_priv = hdmi_priv; |
278 | 283 | ||
279 | drm_encoder_init(dev, &intel_output->enc, &intel_hdmi_enc_funcs, | 284 | drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs, |
280 | DRM_MODE_ENCODER_TMDS); | 285 | DRM_MODE_ENCODER_TMDS); |
281 | drm_encoder_helper_add(&intel_output->enc, &intel_hdmi_helper_funcs); | 286 | drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs); |
282 | 287 | ||
283 | drm_mode_connector_attach_encoder(&intel_output->base, | 288 | drm_mode_connector_attach_encoder(&intel_encoder->base, |
284 | &intel_output->enc); | 289 | &intel_encoder->enc); |
285 | drm_sysfs_connector_add(connector); | 290 | drm_sysfs_connector_add(connector); |
286 | 291 | ||
287 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | 292 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
@@ -297,7 +302,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
297 | 302 | ||
298 | err_connector: | 303 | err_connector: |
299 | drm_connector_cleanup(connector); | 304 | drm_connector_cleanup(connector); |
300 | kfree(intel_output); | 305 | kfree(intel_encoder); |
301 | 306 | ||
302 | return; | 307 | return; |
303 | } | 308 | } |