aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_crt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_crt.c')
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c51
1 files changed, 34 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 6a2c76e367a5..9c89df1af036 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -50,7 +50,7 @@ struct intel_crt {
* encoder's enable/disable callbacks */
struct intel_connector *connector;
bool force_hotplug_required;
- u32 adpa_reg;
+ i915_reg_t adpa_reg;
};
static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
@@ -480,12 +480,8 @@ intel_crt_load_detect(struct intel_crt *crt)
uint32_t vsample;
uint32_t vblank, vblank_start, vblank_end;
uint32_t dsl;
- uint32_t bclrpat_reg;
- uint32_t vtotal_reg;
- uint32_t vblank_reg;
- uint32_t vsync_reg;
- uint32_t pipeconf_reg;
- uint32_t pipe_dsl_reg;
+ i915_reg_t bclrpat_reg, vtotal_reg,
+ vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg;
uint8_t st00;
enum drm_connector_status status;
@@ -518,7 +514,7 @@ intel_crt_load_detect(struct intel_crt *crt)
/* Wait for next Vblank to substitue
* border color for Color info */
intel_wait_for_vblank(dev, pipe);
- st00 = I915_READ8(VGA_MSR_WRITE);
+ st00 = I915_READ8(_VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
connector_status_connected :
connector_status_disconnected;
@@ -563,7 +559,7 @@ intel_crt_load_detect(struct intel_crt *crt)
do {
count++;
/* Read the ST00 VGA status register */
- st00 = I915_READ8(VGA_MSR_WRITE);
+ st00 = I915_READ8(_VGA_MSR_WRITE);
if (st00 & (1 << 4))
detect++;
} while ((I915_READ(pipe_dsl_reg) == dsl));
@@ -781,11 +777,37 @@ 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;
+ i915_reg_t adpa_reg;
+ u32 adpa;
/* Skip machines without VGA that falsely report hotplug events */
if (dmi_check_system(intel_no_crt))
return;
+ if (HAS_PCH_SPLIT(dev))
+ adpa_reg = PCH_ADPA;
+ else if (IS_VALLEYVIEW(dev))
+ adpa_reg = VLV_ADPA;
+ else
+ adpa_reg = ADPA;
+
+ adpa = I915_READ(adpa_reg);
+ if ((adpa & ADPA_DAC_ENABLE) == 0) {
+ /*
+ * On some machines (some IVB at least) CRT can be
+ * fused off, but there's no known fuse bit to
+ * indicate that. On these machine the ADPA register
+ * works normally, except the DAC enable bit won't
+ * take. So the only way to tell is attempt to enable
+ * it and see what happens.
+ */
+ I915_WRITE(adpa_reg, adpa | ADPA_DAC_ENABLE |
+ ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+ if ((I915_READ(adpa_reg) & ADPA_DAC_ENABLE) == 0)
+ return;
+ I915_WRITE(adpa_reg, adpa);
+ }
+
crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
if (!crt)
return;
@@ -802,7 +824,7 @@ void intel_crt_init(struct drm_device *dev)
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs,
- DRM_MODE_ENCODER_DAC);
+ DRM_MODE_ENCODER_DAC, NULL);
intel_connector_attach_encoder(intel_connector, &crt->base);
@@ -819,15 +841,10 @@ void intel_crt_init(struct drm_device *dev)
connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
- if (HAS_PCH_SPLIT(dev))
- crt->adpa_reg = PCH_ADPA;
- else if (IS_VALLEYVIEW(dev))
- crt->adpa_reg = VLV_ADPA;
- else
- crt->adpa_reg = ADPA;
+ crt->adpa_reg = adpa_reg;
crt->base.compute_config = intel_crt_compute_config;
- if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) {
+ if (HAS_PCH_SPLIT(dev)) {
crt->base.disable = pch_disable_crt;
crt->base.post_disable = pch_post_disable_crt;
} else {