aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_hdmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c61
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 @@
40struct intel_hdmi { 40struct 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
46static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) 47static 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
52static 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
51static void intel_hdmi_mode_set(struct drm_encoder *encoder, 58static void intel_hdmi_mode_set(struct drm_encoder *encoder,
@@ -141,13 +148,14 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
141static enum drm_connector_status 148static enum drm_connector_status
142intel_hdmi_detect(struct drm_connector *connector, bool force) 149intel_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
164static int intel_hdmi_get_modes(struct drm_connector *connector) 172static 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
176static void intel_hdmi_destroy(struct drm_connector *connector) 185static void intel_hdmi_destroy(struct drm_connector *connector)
@@ -198,7 +207,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
198static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { 207static 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
204static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { 213static 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
288err_connector:
289 drm_connector_cleanup(connector);
290 kfree(intel_hdmi);
291 kfree(intel_connector);
292
293 return;
294} 289}