Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4e2d043 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Daniel Vetter
Browse files

drm/i915: Make the force_thru workaround atomic, v2.



Set connectors_changed to force a modeset if the panel fitter's force
enabled on eDP.

Changes since v1:
- Use connectors_changed instead of active_changed because it's a
  routing update.

Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 06059d50
Loading
Loading
Loading
Loading
+24 −58
Original line number Diff line number Diff line
@@ -3645,74 +3645,40 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
	return 0;
}

static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev, bool enable)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *crtc =
		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
	struct intel_crtc_state *pipe_config;
	struct drm_atomic_state *state;
	int ret = 0;

	drm_modeset_lock_all(dev);
	pipe_config = to_intel_crtc_state(crtc->base.state);

	/*
	 * If we use the eDP transcoder we need to make sure that we don't
	 * bypass the pfit, since otherwise the pipe CRC source won't work. Only
	 * relevant on hsw with pipe A when using the always-on power well
	 * routing.
	 */
	if (pipe_config->cpu_transcoder == TRANSCODER_EDP &&
	    !pipe_config->pch_pfit.enabled) {
		bool active = pipe_config->base.active;

		if (active) {
			intel_crtc_control(&crtc->base, false);
			pipe_config = to_intel_crtc_state(crtc->base.state);
		}

		pipe_config->pch_pfit.force_thru = true;

		intel_display_power_get(dev_priv,
					POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));

		if (active)
			intel_crtc_control(&crtc->base, true);
	}
	drm_modeset_unlock_all(dev);
	state = drm_atomic_state_alloc(dev);
	if (!state) {
		ret = -ENOMEM;
		goto out;
	}

static void hsw_undo_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *crtc =
		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
	struct intel_crtc_state *pipe_config;

	drm_modeset_lock_all(dev);
	/*
	 * If we use the eDP transcoder we need to make sure that we don't
	 * bypass the pfit, since otherwise the pipe CRC source won't work. Only
	 * relevant on hsw with pipe A when using the always-on power well
	 * routing.
	 */
	pipe_config = to_intel_crtc_state(crtc->base.state);
	if (pipe_config->pch_pfit.force_thru) {
		bool active = pipe_config->base.active;

		if (active) {
			intel_crtc_control(&crtc->base, false);
			pipe_config = to_intel_crtc_state(crtc->base.state);
	state->acquire_ctx = drm_modeset_legacy_acquire_ctx(&crtc->base);
	pipe_config = intel_atomic_get_crtc_state(state, crtc);
	if (IS_ERR(pipe_config)) {
		ret = PTR_ERR(pipe_config);
		goto out;
	}

		pipe_config->pch_pfit.force_thru = false;

		intel_display_power_put(dev_priv,
					POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
	pipe_config->pch_pfit.force_thru = enable;
	if (pipe_config->cpu_transcoder == TRANSCODER_EDP &&
	    pipe_config->pch_pfit.enabled != enable)
		pipe_config->base.connectors_changed = true;

		if (active)
			intel_crtc_control(&crtc->base, true);
	}
	ret = drm_atomic_commit(state);
out:
	drm_modeset_unlock_all(dev);
	WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret);
	if (ret)
		drm_atomic_state_free(state);
}

static int ivb_pipe_crc_ctl_reg(struct drm_device *dev,
@@ -3732,7 +3698,7 @@ static int ivb_pipe_crc_ctl_reg(struct drm_device *dev,
		break;
	case INTEL_PIPE_CRC_SOURCE_PF:
		if (IS_HASWELL(dev) && pipe == PIPE_A)
			hsw_trans_edp_pipe_A_crc_wa(dev);
			hsw_trans_edp_pipe_A_crc_wa(dev, true);

		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
		break;
@@ -3844,7 +3810,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
		else if (IS_VALLEYVIEW(dev))
			vlv_undo_pipe_scramble_reset(dev, pipe);
		else if (IS_HASWELL(dev) && pipe == PIPE_A)
			hsw_undo_trans_edp_pipe_A_crc_wa(dev);
			hsw_trans_edp_pipe_A_crc_wa(dev, false);

		hsw_enable_ips(crtc);
	}
+3 −0
Original line number Diff line number Diff line
@@ -12159,6 +12159,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
	struct intel_dpll_hw_state dpll_hw_state;
	enum intel_dpll_id shared_dpll;
	uint32_t ddi_pll_sel;
	bool force_thru;

	/* FIXME: before the switch to atomic started, a new pipe_config was
	 * kzalloc'd. Code that depends on any field being zero should be
@@ -12170,6 +12171,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
	shared_dpll = crtc_state->shared_dpll;
	dpll_hw_state = crtc_state->dpll_hw_state;
	ddi_pll_sel = crtc_state->ddi_pll_sel;
	force_thru = crtc_state->pch_pfit.force_thru;

	memset(crtc_state, 0, sizeof *crtc_state);

@@ -12178,6 +12180,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
	crtc_state->shared_dpll = shared_dpll;
	crtc_state->dpll_hw_state = dpll_hw_state;
	crtc_state->ddi_pll_sel = ddi_pll_sel;
	crtc_state->pch_pfit.force_thru = force_thru;
}

static int