@@ -753,9 +753,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */
if (set->crtc->fb != set->fb) {
- /* If we have no fb then treat it as a full mode set */
- if (set->crtc->fb == NULL) {
- DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
+ /* If the CRTC is off then treat it as a full mode set */
+ if (!set->crtc->enabled) {
mode_changed = true;
} else if (set->fb == NULL) {
mode_changed = true;
@@ -3573,11 +3573,15 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe;
struct drm_display_mode *mode;
+ int pipeconf = I915_READ((pipe == 0) ? PIPEACONF : PIPEBCONF);
int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+ if (!(pipeconf & PIPEACONF_ENABLE))
+ return NULL;
+
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
if (!mode)
return NULL;
@@ -4310,6 +4314,29 @@ static void intel_init_display(struct drm_device *dev)
}
}
+/**
+ * intel_get_current_modes - get current mode timings for each CRTC
+ * @dev: DRM device
+ *
+ * Setting each CRTC's mode field with the current values can help us avoid
+ * flicker in the case where the BIOS already put us in a native mode.
+ */
+static void intel_get_current_modes(struct drm_device *dev)
+{
+ struct drm_crtc *crtc;
+ struct drm_display_mode *mode;
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ mode = intel_crtc_mode_get(dev, crtc);
+ if (!mode) {
+ crtc->enabled = false;
+ continue;
+ }
+ crtc->mode = *mode; /* copy the mode over */
+ kfree(mode);
+ }
+}
+
void intel_modeset_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4362,6 +4389,8 @@ void intel_modeset_init(struct drm_device *dev)
intel_init_clock_gating(dev);
+ intel_get_current_modes(dev);
+
INIT_WORK(&dev_priv->idle_work, intel_idle_update);
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
(unsigned long)dev);