diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 61 |
1 files changed, 28 insertions, 33 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 926934a482ec..9fb9501f2d07 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -40,12 +40,19 @@ | |||
40 | struct intel_hdmi { | 40 | struct intel_hdmi { |
41 | struct intel_encoder base; | 41 | struct intel_encoder base; |
42 | u32 sdvox_reg; | 42 | u32 sdvox_reg; |
43 | int ddc_bus; | ||
43 | bool has_hdmi_sink; | 44 | bool has_hdmi_sink; |
44 | }; | 45 | }; |
45 | 46 | ||
46 | static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) | 47 | static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
47 | { | 48 | { |
48 | return container_of(enc_to_intel_encoder(encoder), struct intel_hdmi, base); | 49 | return container_of(encoder, struct intel_hdmi, base.base); |
50 | } | ||
51 | |||
52 | static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) | ||
53 | { | ||
54 | return container_of(intel_attached_encoder(connector), | ||
55 | struct intel_hdmi, base); | ||
49 | } | 56 | } |
50 | 57 | ||
51 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, | 58 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, |
@@ -141,13 +148,14 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
141 | static enum drm_connector_status | 148 | static enum drm_connector_status |
142 | intel_hdmi_detect(struct drm_connector *connector, bool force) | 149 | intel_hdmi_detect(struct drm_connector *connector, bool force) |
143 | { | 150 | { |
144 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 151 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
145 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 152 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
146 | struct edid *edid = NULL; | 153 | struct edid *edid; |
147 | enum drm_connector_status status = connector_status_disconnected; | 154 | enum drm_connector_status status = connector_status_disconnected; |
148 | 155 | ||
149 | intel_hdmi->has_hdmi_sink = false; | 156 | intel_hdmi->has_hdmi_sink = false; |
150 | edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus); | 157 | edid = drm_get_edid(connector, |
158 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); | ||
151 | 159 | ||
152 | if (edid) { | 160 | if (edid) { |
153 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { | 161 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
@@ -163,14 +171,15 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) | |||
163 | 171 | ||
164 | static int intel_hdmi_get_modes(struct drm_connector *connector) | 172 | static int intel_hdmi_get_modes(struct drm_connector *connector) |
165 | { | 173 | { |
166 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 174 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
167 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); | 175 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
168 | 176 | ||
169 | /* We should parse the EDID data and find out if it's an HDMI sink so | 177 | /* We should parse the EDID data and find out if it's an HDMI sink so |
170 | * we can send audio to it. | 178 | * we can send audio to it. |
171 | */ | 179 | */ |
172 | 180 | ||
173 | return intel_ddc_get_modes(connector, intel_hdmi->base.ddc_bus); | 181 | return intel_ddc_get_modes(connector, |
182 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); | ||
174 | } | 183 | } |
175 | 184 | ||
176 | static void intel_hdmi_destroy(struct drm_connector *connector) | 185 | static void intel_hdmi_destroy(struct drm_connector *connector) |
@@ -198,7 +207,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | |||
198 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { | 207 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { |
199 | .get_modes = intel_hdmi_get_modes, | 208 | .get_modes = intel_hdmi_get_modes, |
200 | .mode_valid = intel_hdmi_mode_valid, | 209 | .mode_valid = intel_hdmi_mode_valid, |
201 | .best_encoder = intel_attached_encoder, | 210 | .best_encoder = intel_best_encoder, |
202 | }; | 211 | }; |
203 | 212 | ||
204 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | 213 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { |
@@ -224,6 +233,9 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
224 | } | 233 | } |
225 | 234 | ||
226 | intel_encoder = &intel_hdmi->base; | 235 | intel_encoder = &intel_hdmi->base; |
236 | drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs, | ||
237 | DRM_MODE_ENCODER_TMDS); | ||
238 | |||
227 | connector = &intel_connector->base; | 239 | connector = &intel_connector->base; |
228 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, | 240 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
229 | DRM_MODE_CONNECTOR_HDMIA); | 241 | DRM_MODE_CONNECTOR_HDMIA); |
@@ -239,39 +251,31 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
239 | /* Set up the DDC bus. */ | 251 | /* Set up the DDC bus. */ |
240 | if (sdvox_reg == SDVOB) { | 252 | if (sdvox_reg == SDVOB) { |
241 | intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); | 253 | intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); |
242 | intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); | 254 | intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
243 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; | 255 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; |
244 | } else if (sdvox_reg == SDVOC) { | 256 | } else if (sdvox_reg == SDVOC) { |
245 | intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); | 257 | intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); |
246 | intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); | 258 | intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
247 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; | 259 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; |
248 | } else if (sdvox_reg == HDMIB) { | 260 | } else if (sdvox_reg == HDMIB) { |
249 | intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); | 261 | intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); |
250 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, | 262 | intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
251 | "HDMIB"); | ||
252 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; | 263 | dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; |
253 | } else if (sdvox_reg == HDMIC) { | 264 | } else if (sdvox_reg == HDMIC) { |
254 | intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); | 265 | intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); |
255 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, | 266 | intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
256 | "HDMIC"); | ||
257 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; | 267 | dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; |
258 | } else if (sdvox_reg == HDMID) { | 268 | } else if (sdvox_reg == HDMID) { |
259 | intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); | 269 | intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); |
260 | intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, | 270 | intel_hdmi->ddc_bus = GMBUS_PORT_DPD; |
261 | "HDMID"); | ||
262 | dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; | 271 | dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; |
263 | } | 272 | } |
264 | if (!intel_encoder->ddc_bus) | ||
265 | goto err_connector; | ||
266 | 273 | ||
267 | intel_hdmi->sdvox_reg = sdvox_reg; | 274 | intel_hdmi->sdvox_reg = sdvox_reg; |
268 | 275 | ||
269 | drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs, | 276 | drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); |
270 | DRM_MODE_ENCODER_TMDS); | ||
271 | drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs); | ||
272 | 277 | ||
273 | drm_mode_connector_attach_encoder(&intel_connector->base, | 278 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
274 | &intel_encoder->enc); | ||
275 | drm_sysfs_connector_add(connector); | 279 | drm_sysfs_connector_add(connector); |
276 | 280 | ||
277 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | 281 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
@@ -282,13 +286,4 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
282 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | 286 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); |
283 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | 287 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); |
284 | } | 288 | } |
285 | |||
286 | return; | ||
287 | |||
288 | err_connector: | ||
289 | drm_connector_cleanup(connector); | ||
290 | kfree(intel_hdmi); | ||
291 | kfree(intel_connector); | ||
292 | |||
293 | return; | ||
294 | } | 289 | } |