diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 71 |
1 files changed, 32 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 48cade0cf7b1..65727f0a79a3 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -39,7 +39,6 @@ | |||
39 | 39 | ||
40 | struct intel_hdmi_priv { | 40 | struct intel_hdmi_priv { |
41 | u32 sdvox_reg; | 41 | u32 sdvox_reg; |
42 | u32 save_SDVOX; | ||
43 | bool has_hdmi_sink; | 42 | bool has_hdmi_sink; |
44 | }; | 43 | }; |
45 | 44 | ||
@@ -63,8 +62,12 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
63 | if (hdmi_priv->has_hdmi_sink) | 62 | if (hdmi_priv->has_hdmi_sink) |
64 | sdvox |= SDVO_AUDIO_ENABLE; | 63 | sdvox |= SDVO_AUDIO_ENABLE; |
65 | 64 | ||
66 | if (intel_crtc->pipe == 1) | 65 | if (intel_crtc->pipe == 1) { |
67 | sdvox |= SDVO_PIPE_B_SELECT; | 66 | if (HAS_PCH_CPT(dev)) |
67 | sdvox |= PORT_TRANS_B_SEL_CPT; | ||
68 | else | ||
69 | sdvox |= SDVO_PIPE_B_SELECT; | ||
70 | } | ||
68 | 71 | ||
69 | I915_WRITE(hdmi_priv->sdvox_reg, sdvox); | 72 | I915_WRITE(hdmi_priv->sdvox_reg, sdvox); |
70 | POSTING_READ(hdmi_priv->sdvox_reg); | 73 | POSTING_READ(hdmi_priv->sdvox_reg); |
@@ -106,27 +109,6 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | |||
106 | } | 109 | } |
107 | } | 110 | } |
108 | 111 | ||
109 | static void intel_hdmi_save(struct drm_connector *connector) | ||
110 | { | ||
111 | struct drm_device *dev = connector->dev; | ||
112 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
113 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); | ||
114 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; | ||
115 | |||
116 | hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg); | ||
117 | } | ||
118 | |||
119 | static void intel_hdmi_restore(struct drm_connector *connector) | ||
120 | { | ||
121 | struct drm_device *dev = connector->dev; | ||
122 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
123 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); | ||
124 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; | ||
125 | |||
126 | I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX); | ||
127 | POSTING_READ(hdmi_priv->sdvox_reg); | ||
128 | } | ||
129 | |||
130 | static int intel_hdmi_mode_valid(struct drm_connector *connector, | 112 | static int intel_hdmi_mode_valid(struct drm_connector *connector, |
131 | struct drm_display_mode *mode) | 113 | struct drm_display_mode *mode) |
132 | { | 114 | { |
@@ -151,13 +133,14 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
151 | static enum drm_connector_status | 133 | static enum drm_connector_status |
152 | intel_hdmi_detect(struct drm_connector *connector) | 134 | intel_hdmi_detect(struct drm_connector *connector) |
153 | { | 135 | { |
154 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); | 136 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
137 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
155 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; | 138 | struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv; |
156 | struct edid *edid = NULL; | 139 | struct edid *edid = NULL; |
157 | enum drm_connector_status status = connector_status_disconnected; | 140 | enum drm_connector_status status = connector_status_disconnected; |
158 | 141 | ||
159 | hdmi_priv->has_hdmi_sink = false; | 142 | hdmi_priv->has_hdmi_sink = false; |
160 | edid = drm_get_edid(&intel_encoder->base, | 143 | edid = drm_get_edid(connector, |
161 | intel_encoder->ddc_bus); | 144 | intel_encoder->ddc_bus); |
162 | 145 | ||
163 | if (edid) { | 146 | if (edid) { |
@@ -165,7 +148,7 @@ intel_hdmi_detect(struct drm_connector *connector) | |||
165 | status = connector_status_connected; | 148 | status = connector_status_connected; |
166 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | 149 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); |
167 | } | 150 | } |
168 | intel_encoder->base.display_info.raw_edid = NULL; | 151 | connector->display_info.raw_edid = NULL; |
169 | kfree(edid); | 152 | kfree(edid); |
170 | } | 153 | } |
171 | 154 | ||
@@ -174,24 +157,21 @@ intel_hdmi_detect(struct drm_connector *connector) | |||
174 | 157 | ||
175 | static int intel_hdmi_get_modes(struct drm_connector *connector) | 158 | static int intel_hdmi_get_modes(struct drm_connector *connector) |
176 | { | 159 | { |
177 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); | 160 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
161 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
178 | 162 | ||
179 | /* We should parse the EDID data and find out if it's an HDMI sink so | 163 | /* We should parse the EDID data and find out if it's an HDMI sink so |
180 | * we can send audio to it. | 164 | * we can send audio to it. |
181 | */ | 165 | */ |
182 | 166 | ||
183 | return intel_ddc_get_modes(intel_encoder); | 167 | return intel_ddc_get_modes(connector, intel_encoder->ddc_bus); |
184 | } | 168 | } |
185 | 169 | ||
186 | static void intel_hdmi_destroy(struct drm_connector *connector) | 170 | static void intel_hdmi_destroy(struct drm_connector *connector) |
187 | { | 171 | { |
188 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); | ||
189 | |||
190 | if (intel_encoder->i2c_bus) | ||
191 | intel_i2c_destroy(intel_encoder->i2c_bus); | ||
192 | drm_sysfs_connector_remove(connector); | 172 | drm_sysfs_connector_remove(connector); |
193 | drm_connector_cleanup(connector); | 173 | drm_connector_cleanup(connector); |
194 | kfree(intel_encoder); | 174 | kfree(connector); |
195 | } | 175 | } |
196 | 176 | ||
197 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { | 177 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { |
@@ -204,8 +184,6 @@ static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { | |||
204 | 184 | ||
205 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | 185 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
206 | .dpms = drm_helper_connector_dpms, | 186 | .dpms = drm_helper_connector_dpms, |
207 | .save = intel_hdmi_save, | ||
208 | .restore = intel_hdmi_restore, | ||
209 | .detect = intel_hdmi_detect, | 187 | .detect = intel_hdmi_detect, |
210 | .fill_modes = drm_helper_probe_single_connector_modes, | 188 | .fill_modes = drm_helper_probe_single_connector_modes, |
211 | .destroy = intel_hdmi_destroy, | 189 | .destroy = intel_hdmi_destroy, |
@@ -214,12 +192,17 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | |||
214 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { | 192 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { |
215 | .get_modes = intel_hdmi_get_modes, | 193 | .get_modes = intel_hdmi_get_modes, |
216 | .mode_valid = intel_hdmi_mode_valid, | 194 | .mode_valid = intel_hdmi_mode_valid, |
217 | .best_encoder = intel_best_encoder, | 195 | .best_encoder = intel_attached_encoder, |
218 | }; | 196 | }; |
219 | 197 | ||
220 | static void intel_hdmi_enc_destroy(struct drm_encoder *encoder) | 198 | static void intel_hdmi_enc_destroy(struct drm_encoder *encoder) |
221 | { | 199 | { |
200 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
201 | |||
202 | if (intel_encoder->i2c_bus) | ||
203 | intel_i2c_destroy(intel_encoder->i2c_bus); | ||
222 | drm_encoder_cleanup(encoder); | 204 | drm_encoder_cleanup(encoder); |
205 | kfree(intel_encoder); | ||
223 | } | 206 | } |
224 | 207 | ||
225 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | 208 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { |
@@ -231,21 +214,30 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
231 | struct drm_i915_private *dev_priv = dev->dev_private; | 214 | struct drm_i915_private *dev_priv = dev->dev_private; |
232 | struct drm_connector *connector; | 215 | struct drm_connector *connector; |
233 | struct intel_encoder *intel_encoder; | 216 | struct intel_encoder *intel_encoder; |
217 | struct intel_connector *intel_connector; | ||
234 | struct intel_hdmi_priv *hdmi_priv; | 218 | struct intel_hdmi_priv *hdmi_priv; |
235 | 219 | ||
236 | intel_encoder = kcalloc(sizeof(struct intel_encoder) + | 220 | intel_encoder = kcalloc(sizeof(struct intel_encoder) + |
237 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); | 221 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); |
238 | if (!intel_encoder) | 222 | if (!intel_encoder) |
239 | return; | 223 | return; |
224 | |||
225 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | ||
226 | if (!intel_connector) { | ||
227 | kfree(intel_encoder); | ||
228 | return; | ||
229 | } | ||
230 | |||
240 | hdmi_priv = (struct intel_hdmi_priv *)(intel_encoder + 1); | 231 | hdmi_priv = (struct intel_hdmi_priv *)(intel_encoder + 1); |
241 | 232 | ||
242 | connector = &intel_encoder->base; | 233 | connector = &intel_connector->base; |
243 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, | 234 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
244 | DRM_MODE_CONNECTOR_HDMIA); | 235 | DRM_MODE_CONNECTOR_HDMIA); |
245 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); | 236 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
246 | 237 | ||
247 | intel_encoder->type = INTEL_OUTPUT_HDMI; | 238 | intel_encoder->type = INTEL_OUTPUT_HDMI; |
248 | 239 | ||
240 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
249 | connector->interlace_allowed = 0; | 241 | connector->interlace_allowed = 0; |
250 | connector->doublescan_allowed = 0; | 242 | connector->doublescan_allowed = 0; |
251 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | 243 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
@@ -285,7 +277,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
285 | DRM_MODE_ENCODER_TMDS); | 277 | DRM_MODE_ENCODER_TMDS); |
286 | drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs); | 278 | drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs); |
287 | 279 | ||
288 | drm_mode_connector_attach_encoder(&intel_encoder->base, | 280 | drm_mode_connector_attach_encoder(&intel_connector->base, |
289 | &intel_encoder->enc); | 281 | &intel_encoder->enc); |
290 | drm_sysfs_connector_add(connector); | 282 | drm_sysfs_connector_add(connector); |
291 | 283 | ||
@@ -303,6 +295,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
303 | err_connector: | 295 | err_connector: |
304 | drm_connector_cleanup(connector); | 296 | drm_connector_cleanup(connector); |
305 | kfree(intel_encoder); | 297 | kfree(intel_encoder); |
298 | kfree(intel_connector); | ||
306 | 299 | ||
307 | return; | 300 | return; |
308 | } | 301 | } |