]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/i915/intel_lvds.c
drm/i915: Remove the redundant check for a fixed_panel_mode
[~andy/linux] / drivers / gpu / drm / i915 / intel_lvds.c
index b66806a37d37f53ac0a18ae1b536a5db0322c9e3..6ef9388c54d3c1a5c7f88a1c334ec6556eaf5769 100644 (file)
@@ -139,75 +139,6 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
        /* XXX: We never power down the LVDS pairs. */
 }
 
-static void intel_lvds_save(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
-       u32 pwm_ctl_reg;
-
-       if (HAS_PCH_SPLIT(dev)) {
-               pp_on_reg = PCH_PP_ON_DELAYS;
-               pp_off_reg = PCH_PP_OFF_DELAYS;
-               pp_ctl_reg = PCH_PP_CONTROL;
-               pp_div_reg = PCH_PP_DIVISOR;
-               pwm_ctl_reg = BLC_PWM_CPU_CTL;
-       } else {
-               pp_on_reg = PP_ON_DELAYS;
-               pp_off_reg = PP_OFF_DELAYS;
-               pp_ctl_reg = PP_CONTROL;
-               pp_div_reg = PP_DIVISOR;
-               pwm_ctl_reg = BLC_PWM_CTL;
-       }
-
-       dev_priv->savePP_ON = I915_READ(pp_on_reg);
-       dev_priv->savePP_OFF = I915_READ(pp_off_reg);
-       dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg);
-       dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg);
-       dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg);
-       dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
-                                      BACKLIGHT_DUTY_CYCLE_MASK);
-
-       /*
-        * If the light is off at server startup, just make it full brightness
-        */
-       if (dev_priv->backlight_duty_cycle == 0)
-               dev_priv->backlight_duty_cycle =
-                       intel_lvds_get_max_backlight(dev);
-}
-
-static void intel_lvds_restore(struct drm_connector *connector)
-{
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
-       u32 pwm_ctl_reg;
-
-       if (HAS_PCH_SPLIT(dev)) {
-               pp_on_reg = PCH_PP_ON_DELAYS;
-               pp_off_reg = PCH_PP_OFF_DELAYS;
-               pp_ctl_reg = PCH_PP_CONTROL;
-               pp_div_reg = PCH_PP_DIVISOR;
-               pwm_ctl_reg = BLC_PWM_CPU_CTL;
-       } else {
-               pp_on_reg = PP_ON_DELAYS;
-               pp_off_reg = PP_OFF_DELAYS;
-               pp_ctl_reg = PP_CONTROL;
-               pp_div_reg = PP_DIVISOR;
-               pwm_ctl_reg = BLC_PWM_CTL;
-       }
-
-       I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL);
-       I915_WRITE(pp_on_reg, dev_priv->savePP_ON);
-       I915_WRITE(pp_off_reg, dev_priv->savePP_OFF);
-       I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR);
-       I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL);
-       if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
-               intel_lvds_set_power(dev, true);
-       else
-               intel_lvds_set_power(dev, false);
-}
-
 static int intel_lvds_mode_valid(struct drm_connector *connector,
                                 struct drm_display_mode *mode)
 {
@@ -269,27 +200,25 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
        if (dev_priv->panel_fixed_mode == NULL)
                return true;
        /*
-        * If we have timings from the BIOS for the panel, put them in
+        * We have timings from the BIOS for the panel, put them in
         * to the adjusted mode.  The CRTC will be set up for this mode,
         * with the panel scaling set up to source from the H/VDisplay
         * of the original mode.
         */
-       if (dev_priv->panel_fixed_mode != NULL) {
-               adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
-               adjusted_mode->hsync_start =
-                       dev_priv->panel_fixed_mode->hsync_start;
-               adjusted_mode->hsync_end =
-                       dev_priv->panel_fixed_mode->hsync_end;
-               adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
-               adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
-               adjusted_mode->vsync_start =
-                       dev_priv->panel_fixed_mode->vsync_start;
-               adjusted_mode->vsync_end =
-                       dev_priv->panel_fixed_mode->vsync_end;
-               adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
-               adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
-               drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-       }
+       adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
+       adjusted_mode->hsync_start =
+               dev_priv->panel_fixed_mode->hsync_start;
+       adjusted_mode->hsync_end =
+               dev_priv->panel_fixed_mode->hsync_end;
+       adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
+       adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
+       adjusted_mode->vsync_start =
+               dev_priv->panel_fixed_mode->vsync_start;
+       adjusted_mode->vsync_end =
+               dev_priv->panel_fixed_mode->vsync_end;
+       adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
+       adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
+       drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
 
        /* Make sure pre-965s set dither correctly */
        if (!IS_I965G(dev)) {
@@ -635,12 +564,13 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connect
 static int intel_lvds_get_modes(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
-       struct intel_encoder *intel_encoder = to_intel_encoder(connector);
+       struct drm_encoder *encoder = intel_attached_encoder(connector);
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
        struct drm_i915_private *dev_priv = dev->dev_private;
        int ret = 0;
 
        if (dev_priv->lvds_edid_good) {
-               ret = intel_ddc_get_modes(intel_encoder);
+               ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
 
                if (ret)
                        return ret;
@@ -667,6 +597,26 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
        return 0;
 }
 
+static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
+{
+       DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident);
+       return 1;
+}
+
+/* The GPU hangs up on these systems if modeset is performed on LID open */
+static const struct dmi_system_id intel_no_modeset_on_lid[] = {
+       {
+               .callback = intel_no_modeset_on_lid_dmi_callback,
+               .ident = "Toshiba Tecra A11",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
+               },
+       },
+
+       { }     /* terminating entry */
+};
+
 /*
  * Lid events. Note the use of 'modeset_on_lid':
  *  - we set it on lid close, and reset it on open
@@ -690,6 +640,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
         */
        if (connector)
                connector->status = connector->funcs->detect(connector);
+       /* Don't force modeset on machines where it causes a GPU lockup */
+       if (dmi_check_system(intel_no_modeset_on_lid))
+               return NOTIFY_OK;
        if (!acpi_lid_open()) {
                dev_priv->modeset_on_lid = 1;
                return NOTIFY_OK;
@@ -717,11 +670,8 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
 static void intel_lvds_destroy(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
-       struct intel_encoder *intel_encoder = to_intel_encoder(connector);
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (intel_encoder->ddc_bus)
-               intel_i2c_destroy(intel_encoder->ddc_bus);
        if (dev_priv->lid_notifier.notifier_call)
                acpi_lid_notifier_unregister(&dev_priv->lid_notifier);
        drm_sysfs_connector_remove(connector);
@@ -734,13 +684,14 @@ static int intel_lvds_set_property(struct drm_connector *connector,
                                   uint64_t value)
 {
        struct drm_device *dev = connector->dev;
-       struct intel_encoder *intel_encoder =
-                       to_intel_encoder(connector);
 
        if (property == dev->mode_config.scaling_mode_property &&
                                connector->encoder) {
                struct drm_crtc *crtc = connector->encoder->crtc;
+               struct drm_encoder *encoder = connector->encoder;
+               struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
                struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
+
                if (value == DRM_MODE_SCALE_NONE) {
                        DRM_DEBUG_KMS("no scaling not supported\n");
                        return 0;
@@ -774,13 +725,11 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
        .get_modes = intel_lvds_get_modes,
        .mode_valid = intel_lvds_mode_valid,
-       .best_encoder = intel_best_encoder,
+       .best_encoder = intel_attached_encoder,
 };
 
 static const struct drm_connector_funcs intel_lvds_connector_funcs = {
        .dpms = drm_helper_connector_dpms,
-       .save = intel_lvds_save,
-       .restore = intel_lvds_restore,
        .detect = intel_lvds_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = intel_lvds_set_property,
@@ -790,7 +739,12 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
 
 static void intel_lvds_enc_destroy(struct drm_encoder *encoder)
 {
+       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+
+       if (intel_encoder->ddc_bus)
+               intel_i2c_destroy(intel_encoder->ddc_bus);
        drm_encoder_cleanup(encoder);
+       kfree(intel_encoder);
 }
 
 static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
@@ -979,6 +933,7 @@ void intel_lvds_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
+       struct intel_connector *intel_connector;
        struct drm_connector *connector;
        struct drm_encoder *encoder;
        struct drm_display_mode *scan; /* *modes, *bios_mode; */
@@ -1012,19 +967,27 @@ void intel_lvds_init(struct drm_device *dev)
                return;
        }
 
-       connector = &intel_encoder->base;
+       intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+       if (!intel_connector) {
+               kfree(intel_encoder);
+               return;
+       }
+
+       connector = &intel_connector->base;
        encoder = &intel_encoder->enc;
-       drm_connector_init(dev, &intel_encoder->base, &intel_lvds_connector_funcs,
+       drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
                           DRM_MODE_CONNECTOR_LVDS);
 
        drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs,
                         DRM_MODE_ENCODER_LVDS);
 
-       drm_mode_connector_attach_encoder(&intel_encoder->base, &intel_encoder->enc);
+       drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
        intel_encoder->type = INTEL_OUTPUT_LVDS;
 
        intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
        intel_encoder->crtc_mask = (1 << 1);
+       if (IS_I965G(dev))
+               intel_encoder->crtc_mask |= (1 << 0);
        drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
        drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
@@ -1039,10 +1002,10 @@ void intel_lvds_init(struct drm_device *dev)
         * the initial panel fitting mode will be FULL_SCREEN.
         */
 
-       drm_connector_attach_property(&intel_encoder->base,
+       drm_connector_attach_property(&intel_connector->base,
                                      dev->mode_config.scaling_mode_property,
-                                     DRM_MODE_SCALE_FULLSCREEN);
-       lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
+                                     DRM_MODE_SCALE_ASPECT);
+       lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT;
        /*
         * LVDS discovery:
         * 1) check for EDID on DDC
@@ -1067,7 +1030,7 @@ void intel_lvds_init(struct drm_device *dev)
         */
        dev_priv->lvds_edid_good = true;
 
-       if (!intel_ddc_get_modes(intel_encoder))
+       if (!intel_ddc_get_modes(connector, intel_encoder->ddc_bus))
                dev_priv->lvds_edid_good = false;
 
        list_for_each_entry(scan, &connector->probed_modes, head) {
@@ -1151,4 +1114,5 @@ failed:
        drm_connector_cleanup(connector);
        drm_encoder_cleanup(encoder);
        kfree(intel_encoder);
+       kfree(intel_connector);
 }