|
@@ -4913,22 +4913,19 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc,
|
|
|
uint32_t tmp;
|
|
|
|
|
|
tmp = I915_READ(PFIT_CONTROL);
|
|
|
+ if (!(tmp & PFIT_ENABLE))
|
|
|
+ return;
|
|
|
|
|
|
+ /* Check whether the pfit is attached to our pipe. */
|
|
|
if (INTEL_INFO(dev)->gen < 4) {
|
|
|
if (crtc->pipe != PIPE_B)
|
|
|
return;
|
|
|
-
|
|
|
- /* gen2/3 store dither state in pfit control, needs to match */
|
|
|
- pipe_config->gmch_pfit.control = tmp & PANEL_8TO6_DITHER_ENABLE;
|
|
|
} else {
|
|
|
if ((tmp & PFIT_PIPE_MASK) != (crtc->pipe << PFIT_PIPE_SHIFT))
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (!(tmp & PFIT_ENABLE))
|
|
|
- return;
|
|
|
-
|
|
|
- pipe_config->gmch_pfit.control = I915_READ(PFIT_CONTROL);
|
|
|
+ pipe_config->gmch_pfit.control = tmp;
|
|
|
pipe_config->gmch_pfit.pgm_ratios = I915_READ(PFIT_PGM_RATIOS);
|
|
|
if (INTEL_INFO(dev)->gen < 5)
|
|
|
pipe_config->gmch_pfit.lvds_border_bits =
|
|
@@ -8317,6 +8314,8 @@ check_shared_dpll_state(struct drm_device *dev)
|
|
|
pll->active, pll->refcount);
|
|
|
WARN(pll->active && !pll->on,
|
|
|
"pll in active use but not on in sw tracking\n");
|
|
|
+ WARN(pll->on && !pll->active,
|
|
|
+ "pll in on but not on in use in sw tracking\n");
|
|
|
WARN(pll->on != active,
|
|
|
"pll on state mismatch (expected %i, found %i)\n",
|
|
|
pll->on, active);
|
|
@@ -8541,15 +8540,20 @@ static void intel_set_config_restore_state(struct drm_device *dev,
|
|
|
}
|
|
|
|
|
|
static bool
|
|
|
-is_crtc_connector_off(struct drm_crtc *crtc, struct drm_connector *connectors,
|
|
|
- int num_connectors)
|
|
|
+is_crtc_connector_off(struct drm_mode_set *set)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
- for (i = 0; i < num_connectors; i++)
|
|
|
- if (connectors[i].encoder &&
|
|
|
- connectors[i].encoder->crtc == crtc &&
|
|
|
- connectors[i].dpms != DRM_MODE_DPMS_ON)
|
|
|
+ if (set->num_connectors == 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (WARN_ON(set->connectors == NULL))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ for (i = 0; i < set->num_connectors; i++)
|
|
|
+ if (set->connectors[i]->encoder &&
|
|
|
+ set->connectors[i]->encoder->crtc == set->crtc &&
|
|
|
+ set->connectors[i]->dpms != DRM_MODE_DPMS_ON)
|
|
|
return true;
|
|
|
|
|
|
return false;
|
|
@@ -8562,10 +8566,8 @@ intel_set_config_compute_mode_changes(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->connectors != NULL &&
|
|
|
- is_crtc_connector_off(set->crtc, *set->connectors,
|
|
|
- set->num_connectors)) {
|
|
|
- config->mode_changed = true;
|
|
|
+ if (is_crtc_connector_off(set)) {
|
|
|
+ config->mode_changed = true;
|
|
|
} else if (set->crtc->fb != set->fb) {
|
|
|
/* If we have no fb then treat it as a full mode set */
|
|
|
if (set->crtc->fb == NULL) {
|
|
@@ -9398,6 +9400,17 @@ static void quirk_invert_brightness(struct drm_device *dev)
|
|
|
DRM_INFO("applying inverted panel brightness quirk\n");
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Some machines (Dell XPS13) suffer broken backlight controls if
|
|
|
+ * BLM_PCH_PWM_ENABLE is set.
|
|
|
+ */
|
|
|
+static void quirk_no_pcm_pwm_enable(struct drm_device *dev)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+ dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE;
|
|
|
+ DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n");
|
|
|
+}
|
|
|
+
|
|
|
struct intel_quirk {
|
|
|
int device;
|
|
|
int subsystem_vendor;
|
|
@@ -9467,6 +9480,11 @@ static struct intel_quirk intel_quirks[] = {
|
|
|
|
|
|
/* Acer Aspire 4736Z */
|
|
|
{ 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
|
|
|
+
|
|
|
+ /* Dell XPS13 HD Sandy Bridge */
|
|
|
+ { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
|
|
|
+ /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */
|
|
|
+ { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable },
|
|
|
};
|
|
|
|
|
|
static void intel_init_quirks(struct drm_device *dev)
|
|
@@ -9817,8 +9835,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
|
|
|
}
|
|
|
pll->refcount = pll->active;
|
|
|
|
|
|
- DRM_DEBUG_KMS("%s hw state readout: refcount %i\n",
|
|
|
- pll->name, pll->refcount);
|
|
|
+ DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n",
|
|
|
+ pll->name, pll->refcount, pll->on);
|
|
|
}
|
|
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
|
@@ -9869,6 +9887,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|
|
struct drm_plane *plane;
|
|
|
struct intel_crtc *crtc;
|
|
|
struct intel_encoder *encoder;
|
|
|
+ int i;
|
|
|
|
|
|
intel_modeset_readout_hw_state(dev);
|
|
|
|
|
@@ -9884,6 +9903,18 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
|
|
|
intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]");
|
|
|
}
|
|
|
|
|
|
+ for (i = 0; i < dev_priv->num_shared_dpll; i++) {
|
|
|
+ struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
|
|
|
+
|
|
|
+ if (!pll->on || pll->active)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);
|
|
|
+
|
|
|
+ pll->disable(dev_priv, pll);
|
|
|
+ pll->on = false;
|
|
|
+ }
|
|
|
+
|
|
|
if (force_restore) {
|
|
|
/*
|
|
|
* We need to use raw interfaces for restoring state to avoid
|