diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2d918dc046ef..6c3b2ecd59d5 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -43,6 +43,8 @@ struct intel_hdmi { | |||
43 | int ddc_bus; | 43 | int ddc_bus; |
44 | bool has_hdmi_sink; | 44 | bool has_hdmi_sink; |
45 | bool has_audio; | 45 | bool has_audio; |
46 | int force_audio; | ||
47 | struct drm_property *force_audio_property; | ||
46 | }; | 48 | }; |
47 | 49 | ||
48 | static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) | 50 | static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) |
@@ -170,6 +172,11 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) | |||
170 | kfree(edid); | 172 | kfree(edid); |
171 | } | 173 | } |
172 | 174 | ||
175 | if (status == connector_status_connected) { | ||
176 | if (intel_hdmi->force_audio) | ||
177 | intel_hdmi->has_audio = intel_hdmi->force_audio > 0; | ||
178 | } | ||
179 | |||
173 | return status; | 180 | return status; |
174 | } | 181 | } |
175 | 182 | ||
@@ -186,6 +193,46 @@ static int intel_hdmi_get_modes(struct drm_connector *connector) | |||
186 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); | 193 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); |
187 | } | 194 | } |
188 | 195 | ||
196 | static int | ||
197 | intel_hdmi_set_property(struct drm_connector *connector, | ||
198 | struct drm_property *property, | ||
199 | uint64_t val) | ||
200 | { | ||
201 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); | ||
202 | int ret; | ||
203 | |||
204 | ret = drm_connector_property_set_value(connector, property, val); | ||
205 | if (ret) | ||
206 | return ret; | ||
207 | |||
208 | if (property == intel_hdmi->force_audio_property) { | ||
209 | if (val == intel_hdmi->force_audio) | ||
210 | return 0; | ||
211 | |||
212 | intel_hdmi->force_audio = val; | ||
213 | |||
214 | if (val > 0 && intel_hdmi->has_audio) | ||
215 | return 0; | ||
216 | if (val < 0 && !intel_hdmi->has_audio) | ||
217 | return 0; | ||
218 | |||
219 | intel_hdmi->has_audio = val > 0; | ||
220 | goto done; | ||
221 | } | ||
222 | |||
223 | return -EINVAL; | ||
224 | |||
225 | done: | ||
226 | if (intel_hdmi->base.base.crtc) { | ||
227 | struct drm_crtc *crtc = intel_hdmi->base.base.crtc; | ||
228 | drm_crtc_helper_set_mode(crtc, &crtc->mode, | ||
229 | crtc->x, crtc->y, | ||
230 | crtc->fb); | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
189 | static void intel_hdmi_destroy(struct drm_connector *connector) | 236 | static void intel_hdmi_destroy(struct drm_connector *connector) |
190 | { | 237 | { |
191 | drm_sysfs_connector_remove(connector); | 238 | drm_sysfs_connector_remove(connector); |
@@ -205,6 +252,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | |||
205 | .dpms = drm_helper_connector_dpms, | 252 | .dpms = drm_helper_connector_dpms, |
206 | .detect = intel_hdmi_detect, | 253 | .detect = intel_hdmi_detect, |
207 | .fill_modes = drm_helper_probe_single_connector_modes, | 254 | .fill_modes = drm_helper_probe_single_connector_modes, |
255 | .set_property = intel_hdmi_set_property, | ||
208 | .destroy = intel_hdmi_destroy, | 256 | .destroy = intel_hdmi_destroy, |
209 | }; | 257 | }; |
210 | 258 | ||
@@ -218,6 +266,20 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | |||
218 | .destroy = intel_encoder_destroy, | 266 | .destroy = intel_encoder_destroy, |
219 | }; | 267 | }; |
220 | 268 | ||
269 | static void | ||
270 | intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) | ||
271 | { | ||
272 | struct drm_device *dev = connector->dev; | ||
273 | |||
274 | intel_hdmi->force_audio_property = | ||
275 | drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2); | ||
276 | if (intel_hdmi->force_audio_property) { | ||
277 | intel_hdmi->force_audio_property->values[0] = -1; | ||
278 | intel_hdmi->force_audio_property->values[1] = 1; | ||
279 | drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0); | ||
280 | } | ||
281 | } | ||
282 | |||
221 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | 283 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) |
222 | { | 284 | { |
223 | struct drm_i915_private *dev_priv = dev->dev_private; | 285 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -279,6 +341,8 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | |||
279 | 341 | ||
280 | drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); | 342 | drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); |
281 | 343 | ||
344 | intel_hdmi_add_properties(intel_hdmi, connector); | ||
345 | |||
282 | intel_connector_attach_encoder(intel_connector, intel_encoder); | 346 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
283 | drm_sysfs_connector_add(connector); | 347 | drm_sysfs_connector_add(connector); |
284 | 348 | ||