|
@@ -84,13 +84,17 @@ static void intel_enable_crt(struct intel_encoder *encoder)
|
|
|
I915_WRITE(crt->adpa_reg, temp);
|
|
|
}
|
|
|
|
|
|
-static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
|
|
|
+/* Note: The caller is required to filter out dpms modes not supported by the
|
|
|
+ * platform. */
|
|
|
+static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
|
|
|
{
|
|
|
- struct drm_device *dev = encoder->dev;
|
|
|
+ struct drm_device *dev = encoder->base.dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ struct intel_crt *crt = intel_encoder_to_crt(encoder);
|
|
|
u32 temp;
|
|
|
|
|
|
- temp = I915_READ(PCH_ADPA);
|
|
|
+ temp = I915_READ(crt->adpa_reg);
|
|
|
+ temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
|
|
|
temp &= ~ADPA_DAC_ENABLE;
|
|
|
|
|
|
switch (mode) {
|
|
@@ -98,44 +102,59 @@ static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
|
|
|
temp |= ADPA_DAC_ENABLE;
|
|
|
break;
|
|
|
case DRM_MODE_DPMS_STANDBY:
|
|
|
+ temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
|
|
|
+ break;
|
|
|
case DRM_MODE_DPMS_SUSPEND:
|
|
|
+ temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
|
|
|
+ break;
|
|
|
case DRM_MODE_DPMS_OFF:
|
|
|
- /* Just leave port enable cleared */
|
|
|
+ temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- I915_WRITE(PCH_ADPA, temp);
|
|
|
+ I915_WRITE(crt->adpa_reg, temp);
|
|
|
}
|
|
|
|
|
|
-static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
|
|
|
+static void intel_crt_dpms(struct drm_connector *connector, int mode)
|
|
|
{
|
|
|
- struct drm_device *dev = encoder->dev;
|
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- u32 temp;
|
|
|
-
|
|
|
- temp = I915_READ(ADPA);
|
|
|
- temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
|
|
|
- temp &= ~ADPA_DAC_ENABLE;
|
|
|
+ struct drm_device *dev = connector->dev;
|
|
|
+ struct intel_encoder *encoder = intel_attached_encoder(connector);
|
|
|
+ struct drm_crtc *crtc;
|
|
|
+ int old_dpms;
|
|
|
|
|
|
- if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
|
|
|
+ /* PCH platforms and VLV only support on/off. */
|
|
|
+ if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
|
|
|
mode = DRM_MODE_DPMS_OFF;
|
|
|
|
|
|
- switch (mode) {
|
|
|
- case DRM_MODE_DPMS_ON:
|
|
|
- temp |= ADPA_DAC_ENABLE;
|
|
|
- break;
|
|
|
- case DRM_MODE_DPMS_STANDBY:
|
|
|
- temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
|
|
|
- break;
|
|
|
- case DRM_MODE_DPMS_SUSPEND:
|
|
|
- temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
|
|
|
- break;
|
|
|
- case DRM_MODE_DPMS_OFF:
|
|
|
- temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
|
|
|
- break;
|
|
|
+ if (mode == connector->dpms)
|
|
|
+ return;
|
|
|
+
|
|
|
+ old_dpms = connector->dpms;
|
|
|
+ connector->dpms = mode;
|
|
|
+
|
|
|
+ /* Only need to change hw state when actually enabled */
|
|
|
+ crtc = encoder->base.crtc;
|
|
|
+ if (!crtc) {
|
|
|
+ encoder->connectors_active = false;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- I915_WRITE(ADPA, temp);
|
|
|
+ /* We need the pipe to run for anything but OFF. */
|
|
|
+ if (mode == DRM_MODE_DPMS_OFF)
|
|
|
+ encoder->connectors_active = false;
|
|
|
+ else
|
|
|
+ encoder->connectors_active = true;
|
|
|
+
|
|
|
+ if (mode < old_dpms) {
|
|
|
+ /* From off to on, enable the pipe first. */
|
|
|
+ intel_crtc_update_dpms(crtc);
|
|
|
+
|
|
|
+ intel_crt_set_dpms(encoder, mode);
|
|
|
+ } else {
|
|
|
+ intel_crt_set_dpms(encoder, mode);
|
|
|
+
|
|
|
+ intel_crtc_update_dpms(crtc);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int intel_crt_mode_valid(struct drm_connector *connector,
|
|
@@ -596,27 +615,17 @@ static void intel_crt_reset(struct drm_connector *connector)
|
|
|
* Routines for controlling stuff on the analog port
|
|
|
*/
|
|
|
|
|
|
-static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
|
|
|
- .mode_fixup = intel_crt_mode_fixup,
|
|
|
- .prepare = intel_encoder_noop,
|
|
|
- .commit = intel_encoder_noop,
|
|
|
- .mode_set = intel_crt_mode_set,
|
|
|
- .dpms = pch_crt_dpms,
|
|
|
- .disable = intel_encoder_disable,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
|
|
|
+static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
|
|
|
.mode_fixup = intel_crt_mode_fixup,
|
|
|
.prepare = intel_encoder_noop,
|
|
|
.commit = intel_encoder_noop,
|
|
|
.mode_set = intel_crt_mode_set,
|
|
|
- .dpms = gmch_crt_dpms,
|
|
|
.disable = intel_encoder_disable,
|
|
|
};
|
|
|
|
|
|
static const struct drm_connector_funcs intel_crt_connector_funcs = {
|
|
|
.reset = intel_crt_reset,
|
|
|
- .dpms = drm_helper_connector_dpms,
|
|
|
+ .dpms = intel_crt_dpms,
|
|
|
.detect = intel_crt_detect,
|
|
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
|
|
.destroy = intel_crt_destroy,
|
|
@@ -657,7 +666,6 @@ void intel_crt_init(struct drm_device *dev)
|
|
|
struct intel_crt *crt;
|
|
|
struct intel_connector *intel_connector;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
- const struct drm_encoder_helper_funcs *encoder_helper_funcs;
|
|
|
|
|
|
/* Skip machines without VGA that falsely report hotplug events */
|
|
|
if (dmi_check_system(intel_no_crt))
|
|
@@ -695,11 +703,6 @@ void intel_crt_init(struct drm_device *dev)
|
|
|
connector->interlace_allowed = 1;
|
|
|
connector->doublescan_allowed = 0;
|
|
|
|
|
|
- if (HAS_PCH_SPLIT(dev))
|
|
|
- encoder_helper_funcs = &pch_encoder_funcs;
|
|
|
- else
|
|
|
- encoder_helper_funcs = &gmch_encoder_funcs;
|
|
|
-
|
|
|
if (HAS_PCH_SPLIT(dev))
|
|
|
crt->adpa_reg = PCH_ADPA;
|
|
|
else if (IS_VALLEYVIEW(dev))
|
|
@@ -710,7 +713,7 @@ void intel_crt_init(struct drm_device *dev)
|
|
|
crt->base.disable = intel_disable_crt;
|
|
|
crt->base.enable = intel_enable_crt;
|
|
|
|
|
|
- drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
|
|
|
+ drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
|
|
|
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
|
|
|
|
|
|
drm_sysfs_connector_add(connector);
|