Merge branch 'fix/misc' into for-linus
[pandora-kernel.git] / drivers / gpu / drm / i915 / intel_crt.c
index 640f515..d6a1a6e 100644 (file)
@@ -37,11 +37,16 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 temp;
+       u32 temp, reg;
 
-       temp = I915_READ(ADPA);
+       if (IS_IGDNG(dev))
+               reg = PCH_ADPA;
+       else
+               reg = ADPA;
+
+       temp = I915_READ(reg);
        temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-       temp |= ADPA_DAC_ENABLE;
+       temp &= ~ADPA_DAC_ENABLE;
 
        switch(mode) {
        case DRM_MODE_DPMS_ON:
@@ -58,7 +63,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
                break;
        }
 
-       I915_WRITE(ADPA, temp);
+       I915_WRITE(reg, temp);
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -101,17 +106,23 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
        struct drm_i915_private *dev_priv = dev->dev_private;
        int dpll_md_reg;
        u32 adpa, dpll_md;
+       u32 adpa_reg;
 
        if (intel_crtc->pipe == 0)
                dpll_md_reg = DPLL_A_MD;
        else
                dpll_md_reg = DPLL_B_MD;
 
+       if (IS_IGDNG(dev))
+               adpa_reg = PCH_ADPA;
+       else
+               adpa_reg = ADPA;
+
        /*
         * Disable separate mode multiplier used when cloning SDVO to CRT
         * XXX this needs to be adjusted when we really are cloning
         */
-       if (IS_I965G(dev)) {
+       if (IS_I965G(dev) && !IS_IGDNG(dev)) {
                dpll_md = I915_READ(dpll_md_reg);
                I915_WRITE(dpll_md_reg,
                           dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
@@ -125,13 +136,53 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 
        if (intel_crtc->pipe == 0) {
                adpa |= ADPA_PIPE_A_SELECT;
-               I915_WRITE(BCLRPAT_A, 0);
+               if (!IS_IGDNG(dev))
+                       I915_WRITE(BCLRPAT_A, 0);
        } else {
                adpa |= ADPA_PIPE_B_SELECT;
-               I915_WRITE(BCLRPAT_B, 0);
+               if (!IS_IGDNG(dev))
+                       I915_WRITE(BCLRPAT_B, 0);
        }
 
-       I915_WRITE(ADPA, adpa);
+       I915_WRITE(adpa_reg, adpa);
+}
+
+static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 adpa, temp;
+       bool ret;
+
+       temp = adpa = I915_READ(PCH_ADPA);
+
+       adpa &= ~ADPA_CRT_HOTPLUG_MASK;
+
+       adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
+                       ADPA_CRT_HOTPLUG_WARMUP_10MS |
+                       ADPA_CRT_HOTPLUG_SAMPLE_4S |
+                       ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */
+                       ADPA_CRT_HOTPLUG_VOLREF_325MV |
+                       ADPA_CRT_HOTPLUG_ENABLE |
+                       ADPA_CRT_HOTPLUG_FORCE_TRIGGER);
+
+       DRM_DEBUG("pch crt adpa 0x%x", adpa);
+       I915_WRITE(PCH_ADPA, adpa);
+
+       /* This might not be needed as not specified in spec...*/
+       udelay(1000);
+
+       /* Check the status to see if both blue and green are on now */
+       adpa = I915_READ(PCH_ADPA);
+       if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) ==
+                       ADPA_CRT_HOTPLUG_MONITOR_COLOR)
+               ret = true;
+       else
+               ret = false;
+
+       /* restore origin register */
+       I915_WRITE(PCH_ADPA, temp);
+       return ret;
 }
 
 /**
@@ -148,6 +199,10 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 hotplug_en;
        int i, tries = 0;
+
+       if (IS_IGDNG(dev))
+               return intel_igdng_crt_detect_hotplug(connector);
+
        /*
         * On 4 series desktop, CRT detect sequence need to be done twice
         * to get a reliable result.
@@ -373,19 +428,40 @@ static void intel_crt_destroy(struct drm_connector *connector)
 
 static int intel_crt_get_modes(struct drm_connector *connector)
 {
+       int ret;
        struct intel_output *intel_output = to_intel_output(connector);
-       return intel_ddc_get_modes(intel_output);
+       struct i2c_adapter *ddcbus;
+       struct drm_device *dev = connector->dev;
+
+
+       ret = intel_ddc_get_modes(intel_output);
+       if (ret || !IS_G4X(dev))
+               goto end;
+
+       ddcbus = intel_output->ddc_bus;
+       /* Try to probe digital port for output in DVI-I -> VGA mode. */
+       intel_output->ddc_bus =
+               intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D");
+
+       if (!intel_output->ddc_bus) {
+               intel_output->ddc_bus = ddcbus;
+               dev_printk(KERN_ERR, &connector->dev->pdev->dev,
+                          "DDC bus registration failed for CRTDDC_D.\n");
+               goto end;
+       }
+       /* Try to get modes by GPIOD port */
+       ret = intel_ddc_get_modes(intel_output);
+       intel_i2c_destroy(ddcbus);
+
+end:
+       return ret;
+
 }
 
 static int intel_crt_set_property(struct drm_connector *connector,
                                  struct drm_property *property,
                                  uint64_t value)
 {
-       struct drm_device *dev = connector->dev;
-
-       if (property == dev->mode_config.dpms_property && connector->encoder)
-               intel_crt_dpms(connector->encoder, (uint32_t)(value & 0xf));
-
        return 0;
 }
 
@@ -402,6 +478,7 @@ static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = {
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
        .detect = intel_crt_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .destroy = intel_crt_destroy,
@@ -427,6 +504,7 @@ void intel_crt_init(struct drm_device *dev)
 {
        struct drm_connector *connector;
        struct intel_output *intel_output;
+       u32 i2c_reg;
 
        intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
        if (!intel_output)
@@ -443,7 +521,11 @@ void intel_crt_init(struct drm_device *dev)
                                          &intel_output->enc);
 
        /* Set up the DDC bus. */
-       intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
+       if (IS_IGDNG(dev))
+               i2c_reg = PCH_GPIOA;
+       else
+               i2c_reg = GPIOA;
+       intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
        if (!intel_output->ddc_bus) {
                dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
                           "failed.\n");