All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/18] Generic DRRS implementation across the encoders
@ 2015-06-26 13:51 Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation Ramalingam C
                   ` (18 more replies)
  0 siblings, 19 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

Display Refresh Rate Switching (DRRS) is a power conservation feature
which enables swtching between low and high refresh rates,
dynamically, based on the usage scenario to save power.

This feature is applicable for internal panels.

Indication that the panel supports DRRS is given by the panel EDID, which
would list multiple refresh rates for one resolution along with VBT fields
like drrs_min_vrefresh.

DRRS is of 2 types - static and seamless.
Static needs full modeset. Which can be used in docking and undocking
scenarios.
Seamless DRRS involves changing RR without any visual effect to the user
and can be used during normal system usage. This is done by programming
certain registers.

Support for static/seamless DRRS may be indicated in the VBT based on
inputs from the panel spec.

We have implemented two DRRS use case scenrios :
1. Idleness DRRS,	2. Media playback DRRS (Content's FPS based)

Idleness DRRS:-
	The implementation is based on frontbuffer tracking implementation.
When there is a disturbance on the screen triggered by user activity or a
periodic system activity, DRRS is disabled (RR is changed to high RR).
When there is no movement on screen, after a timeout, a switch
to low RR is made.
	For integration with frontbuffer tracking code,
intel_drrs_invalidate() and intel_drrs_flush() are called.

Media playback DRRS (Content's FPS based):
	Based on the content's Frames Per Second, minimum required vrefresh
is called in userspace. If the panel supports the minimum required vrefresh
and if the DRRS is supported on the platform, userspace will make a modeset
request with same mode and FB but with different vrefresh.
	Panel's vrefresh range will be exposed through connector's modelist and
connector property is created to expose the DRRS capability to the userspace.

	In DRRS state machine Media plyabck DRRS holds the highest priority.
Idleness DRRS is disabled as soon as Media playback DRRS is requested.
Idleness DRRS is reenabled when the userspace indicates the exit of Media
playback DRRS by requesting for highest vrefresh supported.

NOTE:
1. DRM documentation will be made once the RFC is closed along with IGT.
2. Currently in RFC, platform support is developed only for VLV.
   it will be extended to other platform once the design is approved.
3. Basic design of DSI DRRS and Content based DRRS is functionally tested on
   Android(VLV & CHT).

Ramalingam C (18):
  drm/i915: Removing the eDP specific DRRS implementation
  drm/i915: Generic DRRS state Machine
  drm/i915: Addition of the drrs_min_vrefresh in VBT
  drm/i915: Implementation of Generic DSI DRRS
  drm/i915: Adjusting the pclk for dual link and burst mode
  drm/i915: VLV dsi drrs support
  drm/i915: Generic eDP DRRS implementation
  drm/i915: VLV eDP DRRS methods
  drm/i915: Cloned mode check
  drm/i915: Initializing DRRS for all connectors
  drm/i915: Updating the crtc modes in DRRS transitions
  drm/i915: Redesigning dp_set_m_n to receive divider values
  drm/i915: MEDIA_RR support in general DRRS state machine
  drm/i915: MEDIA_RR support in eDP DRRS module
  drm/i915: MEDIA_RR support in DSI DRRS module
  drm/i915: Filtering media playback DRRS requests
  drm/i915: Addition of downclock mode to connector modelist
  drm/i915: Connector property for DRRS capability

 drivers/gpu/drm/i915/Makefile            |    3 +
 drivers/gpu/drm/i915/i915_debugfs.c      |  110 -----
 drivers/gpu/drm/i915/i915_drv.h          |   91 +++-
 drivers/gpu/drm/i915/i915_reg.h          |    4 +
 drivers/gpu/drm/i915/intel_bios.c        |    3 +
 drivers/gpu/drm/i915/intel_bios.h        |    9 +-
 drivers/gpu/drm/i915/intel_ddi.c         |    2 -
 drivers/gpu/drm/i915/intel_display.c     |   57 ++-
 drivers/gpu/drm/i915/intel_dp.c          |  397 +---------------
 drivers/gpu/drm/i915/intel_drrs.c        |  728 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drrs.h        |   38 ++
 drivers/gpu/drm/i915/intel_drv.h         |   45 +-
 drivers/gpu/drm/i915/intel_dsi.c         |   29 +-
 drivers/gpu/drm/i915/intel_dsi.h         |    3 +
 drivers/gpu/drm/i915/intel_dsi_drrs.c    |  415 +++++++++++++++++
 drivers/gpu/drm/i915/intel_dsi_drrs.h    |   66 +++
 drivers/gpu/drm/i915/intel_dsi_pll.c     |  303 +++++++++++--
 drivers/gpu/drm/i915/intel_edp_drrs.c    |  196 ++++++++
 drivers/gpu/drm/i915/intel_edp_drrs.h    |   29 ++
 drivers/gpu/drm/i915/intel_frontbuffer.c |    4 +-
 drivers/gpu/drm/i915/intel_modes.c       |   28 ++
 21 files changed, 1959 insertions(+), 601 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_drrs.c
 create mode 100644 drivers/gpu/drm/i915/intel_drrs.h
 create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.c
 create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.h
 create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.c
 create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.h

-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 16:50   ` Daniel Vetter
  2015-06-26 13:51 ` [RFC PATCH 02/18] drm/i915: Generic DRRS state Machine Ramalingam C
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

EDP specific DRRS implementation is removed to implement a
generic DRRS stack extentable accross the supportable encoders.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c      |  110 ---------
 drivers/gpu/drm/i915/i915_drv.h          |   22 --
 drivers/gpu/drm/i915/intel_ddi.c         |    2 -
 drivers/gpu/drm/i915/intel_dp.c          |  392 ------------------------------
 drivers/gpu/drm/i915/intel_drv.h         |    5 -
 drivers/gpu/drm/i915/intel_frontbuffer.c |    2 -
 6 files changed, 533 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index c49fe2a..7dbf170 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2962,115 +2962,6 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
 	return 0;
 }
 
-static void drrs_status_per_crtc(struct seq_file *m,
-		struct drm_device *dev, struct intel_crtc *intel_crtc)
-{
-	struct intel_encoder *intel_encoder;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_drrs *drrs = &dev_priv->drrs;
-	int vrefresh = 0;
-
-	for_each_encoder_on_crtc(dev, &intel_crtc->base, intel_encoder) {
-		/* Encoder connected on this CRTC */
-		switch (intel_encoder->type) {
-		case INTEL_OUTPUT_EDP:
-			seq_puts(m, "eDP:\n");
-			break;
-		case INTEL_OUTPUT_DSI:
-			seq_puts(m, "DSI:\n");
-			break;
-		case INTEL_OUTPUT_HDMI:
-			seq_puts(m, "HDMI:\n");
-			break;
-		case INTEL_OUTPUT_DISPLAYPORT:
-			seq_puts(m, "DP:\n");
-			break;
-		default:
-			seq_printf(m, "Other encoder (id=%d).\n",
-						intel_encoder->type);
-			return;
-		}
-	}
-
-	if (dev_priv->vbt.drrs_type == STATIC_DRRS_SUPPORT)
-		seq_puts(m, "\tVBT: DRRS_type: Static");
-	else if (dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT)
-		seq_puts(m, "\tVBT: DRRS_type: Seamless");
-	else if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED)
-		seq_puts(m, "\tVBT: DRRS_type: None");
-	else
-		seq_puts(m, "\tVBT: DRRS_type: FIXME: Unrecognized Value");
-
-	seq_puts(m, "\n\n");
-
-	if (to_intel_crtc_state(intel_crtc->base.state)->has_drrs) {
-		struct intel_panel *panel;
-
-		mutex_lock(&drrs->mutex);
-		/* DRRS Supported */
-		seq_puts(m, "\tDRRS Supported: Yes\n");
-
-		/* disable_drrs() will make drrs->dp NULL */
-		if (!drrs->dp) {
-			seq_puts(m, "Idleness DRRS: Disabled");
-			mutex_unlock(&drrs->mutex);
-			return;
-		}
-
-		panel = &drrs->dp->attached_connector->panel;
-		seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X",
-					drrs->busy_frontbuffer_bits);
-
-		seq_puts(m, "\n\t\t");
-		if (drrs->refresh_rate_type == DRRS_HIGH_RR) {
-			seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n");
-			vrefresh = panel->fixed_mode->vrefresh;
-		} else if (drrs->refresh_rate_type == DRRS_LOW_RR) {
-			seq_puts(m, "DRRS_State: DRRS_LOW_RR\n");
-			vrefresh = panel->downclock_mode->vrefresh;
-		} else {
-			seq_printf(m, "DRRS_State: Unknown(%d)\n",
-						drrs->refresh_rate_type);
-			mutex_unlock(&drrs->mutex);
-			return;
-		}
-		seq_printf(m, "\t\tVrefresh: %d", vrefresh);
-
-		seq_puts(m, "\n\t\t");
-		mutex_unlock(&drrs->mutex);
-	} else {
-		/* DRRS not supported. Print the VBT parameter*/
-		seq_puts(m, "\tDRRS Supported : No");
-	}
-	seq_puts(m, "\n");
-}
-
-static int i915_drrs_status(struct seq_file *m, void *unused)
-{
-	struct drm_info_node *node = m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct intel_crtc *intel_crtc;
-	int active_crtc_cnt = 0;
-
-	for_each_intel_crtc(dev, intel_crtc) {
-		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
-
-		if (intel_crtc->base.state->active) {
-			active_crtc_cnt++;
-			seq_printf(m, "\nCRTC %d:  ", active_crtc_cnt);
-
-			drrs_status_per_crtc(m, dev, intel_crtc);
-		}
-
-		drm_modeset_unlock(&intel_crtc->base.mutex);
-	}
-
-	if (!active_crtc_cnt)
-		seq_puts(m, "No active crtc found\n");
-
-	return 0;
-}
-
 struct pipe_crc_info {
 	const char *name;
 	struct drm_device *dev;
@@ -5048,7 +4939,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_wa_registers", i915_wa_registers, 0},
 	{"i915_ddb_info", i915_ddb_info, 0},
 	{"i915_sseu_status", i915_sseu_status, 0},
-	{"i915_drrs_status", i915_drrs_status, 0},
 	{"i915_rps_boost_info", i915_rps_boost_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 491ef0c..922dd68 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -930,33 +930,12 @@ struct i915_fbc {
 	} no_fbc_reason;
 };
 
-/**
- * HIGH_RR is the highest eDP panel refresh rate read from EDID
- * LOW_RR is the lowest eDP panel refresh rate found from EDID
- * parsing for same resolution.
- */
-enum drrs_refresh_rate_type {
-	DRRS_HIGH_RR,
-	DRRS_LOW_RR,
-	DRRS_MAX_RR, /* RR count */
-};
-
 enum drrs_support_type {
 	DRRS_NOT_SUPPORTED = 0,
 	STATIC_DRRS_SUPPORT = 1,
 	SEAMLESS_DRRS_SUPPORT = 2
 };
 
-struct intel_dp;
-struct i915_drrs {
-	struct mutex mutex;
-	struct delayed_work work;
-	struct intel_dp *dp;
-	unsigned busy_frontbuffer_bits;
-	enum drrs_refresh_rate_type refresh_rate_type;
-	enum drrs_support_type type;
-};
-
 struct i915_psr {
 	struct mutex lock;
 	bool sink_support;
@@ -1718,7 +1697,6 @@ struct drm_i915_private {
 
 	struct i915_hotplug hotplug;
 	struct i915_fbc fbc;
-	struct i915_drrs drrs;
 	struct intel_opregion opregion;
 	struct intel_vbt_data vbt;
 
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 31b29e8..75afbd7 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2012,7 +2012,6 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
 
 		intel_edp_backlight_on(intel_dp);
 		intel_psr_enable(intel_dp);
-		intel_edp_drrs_enable(intel_dp);
 	}
 
 	if (intel_crtc->config->has_audio) {
@@ -2038,7 +2037,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
 	if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-		intel_edp_drrs_disable(intel_dp);
 		intel_psr_disable(intel_dp);
 		intel_edp_backlight_off(intel_dp);
 	}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f52eef1..738e98e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1483,15 +1483,6 @@ found:
 			       pipe_config->port_clock,
 			       &pipe_config->dp_m_n);
 
-	if (intel_connector->panel.downclock_mode != NULL &&
-		dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) {
-			pipe_config->has_drrs = true;
-			intel_link_compute_m_n(bpp, lane_count,
-				intel_connector->panel.downclock_mode->clock,
-				pipe_config->port_clock,
-				&pipe_config->dp_m2_n2);
-	}
-
 	if (IS_SKYLAKE(dev) && is_edp(intel_dp))
 		skl_edp_set_pll_config(pipe_config, common_rates[clock]);
 	else if (IS_BROXTON(dev))
@@ -5254,387 +5245,6 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 		      I915_READ(pp_div_reg));
 }
 
-/**
- * intel_dp_set_drrs_state - program registers for RR switch to take effect
- * @dev: DRM device
- * @refresh_rate: RR to be programmed
- *
- * This function gets called when refresh rate (RR) has to be changed from
- * one frequency to another. Switches can be between high and low RR
- * supported by the panel or to any other RR based on media playback (in
- * this case, RR value needs to be passed from user space).
- *
- * The caller of this function needs to take a lock on dev_priv->drrs.
- */
-static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_encoder *encoder;
-	struct intel_digital_port *dig_port = NULL;
-	struct intel_dp *intel_dp = dev_priv->drrs.dp;
-	struct intel_crtc_state *config = NULL;
-	struct intel_crtc *intel_crtc = NULL;
-	u32 reg, val;
-	enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
-
-	if (refresh_rate <= 0) {
-		DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n");
-		return;
-	}
-
-	if (intel_dp == NULL) {
-		DRM_DEBUG_KMS("DRRS not supported.\n");
-		return;
-	}
-
-	/*
-	 * FIXME: This needs proper synchronization with psr state for some
-	 * platforms that cannot have PSR and DRRS enabled at the same time.
-	 */
-
-	dig_port = dp_to_dig_port(intel_dp);
-	encoder = &dig_port->base;
-	intel_crtc = to_intel_crtc(encoder->base.crtc);
-
-	if (!intel_crtc) {
-		DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
-		return;
-	}
-
-	config = intel_crtc->config;
-
-	if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
-		DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
-		return;
-	}
-
-	if (intel_dp->attached_connector->panel.downclock_mode->vrefresh ==
-			refresh_rate)
-		index = DRRS_LOW_RR;
-
-	if (index == dev_priv->drrs.refresh_rate_type) {
-		DRM_DEBUG_KMS(
-			"DRRS requested for previously set RR...ignoring\n");
-		return;
-	}
-
-	if (!intel_crtc->active) {
-		DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n");
-		return;
-	}
-
-	if (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev)) {
-		switch (index) {
-		case DRRS_HIGH_RR:
-			intel_dp_set_m_n(intel_crtc, M1_N1);
-			break;
-		case DRRS_LOW_RR:
-			intel_dp_set_m_n(intel_crtc, M2_N2);
-			break;
-		case DRRS_MAX_RR:
-		default:
-			DRM_ERROR("Unsupported refreshrate type\n");
-		}
-	} else if (INTEL_INFO(dev)->gen > 6) {
-		reg = PIPECONF(intel_crtc->config->cpu_transcoder);
-		val = I915_READ(reg);
-
-		if (index > DRRS_HIGH_RR) {
-			if (IS_VALLEYVIEW(dev))
-				val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
-			else
-				val |= PIPECONF_EDP_RR_MODE_SWITCH;
-		} else {
-			if (IS_VALLEYVIEW(dev))
-				val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
-			else
-				val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
-		}
-		I915_WRITE(reg, val);
-	}
-
-	dev_priv->drrs.refresh_rate_type = index;
-
-	DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
-}
-
-/**
- * intel_edp_drrs_enable - init drrs struct if supported
- * @intel_dp: DP struct
- *
- * Initializes frontbuffer_bits and drrs.dp
- */
-void intel_edp_drrs_enable(struct intel_dp *intel_dp)
-{
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_crtc *crtc = dig_port->base.base.crtc;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	if (!intel_crtc->config->has_drrs) {
-		DRM_DEBUG_KMS("Panel doesn't support DRRS\n");
-		return;
-	}
-
-	mutex_lock(&dev_priv->drrs.mutex);
-	if (WARN_ON(dev_priv->drrs.dp)) {
-		DRM_ERROR("DRRS already enabled\n");
-		goto unlock;
-	}
-
-	dev_priv->drrs.busy_frontbuffer_bits = 0;
-
-	dev_priv->drrs.dp = intel_dp;
-
-unlock:
-	mutex_unlock(&dev_priv->drrs.mutex);
-}
-
-/**
- * intel_edp_drrs_disable - Disable DRRS
- * @intel_dp: DP struct
- *
- */
-void intel_edp_drrs_disable(struct intel_dp *intel_dp)
-{
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_crtc *crtc = dig_port->base.base.crtc;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	if (!intel_crtc->config->has_drrs)
-		return;
-
-	mutex_lock(&dev_priv->drrs.mutex);
-	if (!dev_priv->drrs.dp) {
-		mutex_unlock(&dev_priv->drrs.mutex);
-		return;
-	}
-
-	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
-		intel_dp_set_drrs_state(dev_priv->dev,
-			intel_dp->attached_connector->panel.
-			fixed_mode->vrefresh);
-
-	dev_priv->drrs.dp = NULL;
-	mutex_unlock(&dev_priv->drrs.mutex);
-
-	cancel_delayed_work_sync(&dev_priv->drrs.work);
-}
-
-static void intel_edp_drrs_downclock_work(struct work_struct *work)
-{
-	struct drm_i915_private *dev_priv =
-		container_of(work, typeof(*dev_priv), drrs.work.work);
-	struct intel_dp *intel_dp;
-
-	mutex_lock(&dev_priv->drrs.mutex);
-
-	intel_dp = dev_priv->drrs.dp;
-
-	if (!intel_dp)
-		goto unlock;
-
-	/*
-	 * The delayed work can race with an invalidate hence we need to
-	 * recheck.
-	 */
-
-	if (dev_priv->drrs.busy_frontbuffer_bits)
-		goto unlock;
-
-	if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR)
-		intel_dp_set_drrs_state(dev_priv->dev,
-			intel_dp->attached_connector->panel.
-			downclock_mode->vrefresh);
-
-unlock:
-	mutex_unlock(&dev_priv->drrs.mutex);
-}
-
-/**
- * intel_edp_drrs_invalidate - Disable Idleness DRRS
- * @dev: DRM device
- * @frontbuffer_bits: frontbuffer plane tracking bits
- *
- * This function gets called everytime rendering on the given planes start.
- * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
- *
- * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
- */
-void intel_edp_drrs_invalidate(struct drm_device *dev,
-		unsigned frontbuffer_bits)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	enum pipe pipe;
-
-	if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
-		return;
-
-	cancel_delayed_work(&dev_priv->drrs.work);
-
-	mutex_lock(&dev_priv->drrs.mutex);
-	if (!dev_priv->drrs.dp) {
-		mutex_unlock(&dev_priv->drrs.mutex);
-		return;
-	}
-
-	crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
-	pipe = to_intel_crtc(crtc)->pipe;
-
-	/* invalidate means busy screen hence upclock */
-	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
-		intel_dp_set_drrs_state(dev_priv->dev,
-				dev_priv->drrs.dp->attached_connector->panel.
-				fixed_mode->vrefresh);
-	}
-
-	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
-
-	dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
-	mutex_unlock(&dev_priv->drrs.mutex);
-}
-
-/**
- * intel_edp_drrs_flush - Restart Idleness DRRS
- * @dev: DRM device
- * @frontbuffer_bits: frontbuffer plane tracking bits
- *
- * This function gets called every time rendering on the given planes has
- * completed or flip on a crtc is completed. So DRRS should be upclocked
- * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
- * if no other planes are dirty.
- *
- * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
- */
-void intel_edp_drrs_flush(struct drm_device *dev,
-		unsigned frontbuffer_bits)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	enum pipe pipe;
-
-	if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
-		return;
-
-	cancel_delayed_work(&dev_priv->drrs.work);
-
-	mutex_lock(&dev_priv->drrs.mutex);
-	if (!dev_priv->drrs.dp) {
-		mutex_unlock(&dev_priv->drrs.mutex);
-		return;
-	}
-
-	crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
-	pipe = to_intel_crtc(crtc)->pipe;
-	dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
-
-	/* flush means busy screen hence upclock */
-	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
-		intel_dp_set_drrs_state(dev_priv->dev,
-				dev_priv->drrs.dp->attached_connector->panel.
-				fixed_mode->vrefresh);
-
-	/*
-	 * flush also means no more activity hence schedule downclock, if all
-	 * other fbs are quiescent too
-	 */
-	if (!dev_priv->drrs.busy_frontbuffer_bits)
-		schedule_delayed_work(&dev_priv->drrs.work,
-				msecs_to_jiffies(1000));
-	mutex_unlock(&dev_priv->drrs.mutex);
-}
-
-/**
- * DOC: Display Refresh Rate Switching (DRRS)
- *
- * Display Refresh Rate Switching (DRRS) is a power conservation feature
- * which enables swtching between low and high refresh rates,
- * dynamically, based on the usage scenario. This feature is applicable
- * for internal panels.
- *
- * Indication that the panel supports DRRS is given by the panel EDID, which
- * would list multiple refresh rates for one resolution.
- *
- * DRRS is of 2 types - static and seamless.
- * Static DRRS involves changing refresh rate (RR) by doing a full modeset
- * (may appear as a blink on screen) and is used in dock-undock scenario.
- * Seamless DRRS involves changing RR without any visual effect to the user
- * and can be used during normal system usage. This is done by programming
- * certain registers.
- *
- * Support for static/seamless DRRS may be indicated in the VBT based on
- * inputs from the panel spec.
- *
- * DRRS saves power by switching to low RR based on usage scenarios.
- *
- * eDP DRRS:-
- *        The implementation is based on frontbuffer tracking implementation.
- * When there is a disturbance on the screen triggered by user activity or a
- * periodic system activity, DRRS is disabled (RR is changed to high RR).
- * When there is no movement on screen, after a timeout of 1 second, a switch
- * to low RR is made.
- *        For integration with frontbuffer tracking code,
- * intel_edp_drrs_invalidate() and intel_edp_drrs_flush() are called.
- *
- * DRRS can be further extended to support other internal panels and also
- * the scenario of video playback wherein RR is set based on the rate
- * requested by userspace.
- */
-
-/**
- * intel_dp_drrs_init - Init basic DRRS work and mutex.
- * @intel_connector: eDP connector
- * @fixed_mode: preferred mode of panel
- *
- * This function is  called only once at driver load to initialize basic
- * DRRS stuff.
- *
- * Returns:
- * Downclock mode if panel supports it, else return NULL.
- * DRRS support is determined by the presence of downclock mode (apart
- * from VBT setting).
- */
-static struct drm_display_mode *
-intel_dp_drrs_init(struct intel_connector *intel_connector,
-		struct drm_display_mode *fixed_mode)
-{
-	struct drm_connector *connector = &intel_connector->base;
-	struct drm_device *dev = connector->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_display_mode *downclock_mode = NULL;
-
-	INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
-	mutex_init(&dev_priv->drrs.mutex);
-
-	if (INTEL_INFO(dev)->gen <= 6) {
-		DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
-		return NULL;
-	}
-
-	if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
-		DRM_DEBUG_KMS("VBT doesn't support DRRS\n");
-		return NULL;
-	}
-
-	downclock_mode = intel_find_panel_downclock
-					(dev, fixed_mode, connector);
-
-	if (!downclock_mode) {
-		DRM_DEBUG_KMS("Downclock mode is not found. DRRS not supported\n");
-		return NULL;
-	}
-
-	dev_priv->drrs.type = dev_priv->vbt.drrs_type;
-
-	dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
-	DRM_DEBUG_KMS("seamless DRRS supported for eDP panel.\n");
-	return downclock_mode;
-}
-
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 				     struct intel_connector *intel_connector)
 {
@@ -5696,8 +5306,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	list_for_each_entry(scan, &connector->probed_modes, head) {
 		if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
 			fixed_mode = drm_mode_duplicate(dev, scan);
-			downclock_mode = intel_dp_drrs_init(
-						intel_connector, fixed_mode);
 			break;
 		}
 	}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bcafefc..e2f534a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1198,11 +1198,6 @@ void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
 void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
 uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
 void intel_plane_destroy(struct drm_plane *plane);
-void intel_edp_drrs_enable(struct intel_dp *intel_dp);
-void intel_edp_drrs_disable(struct intel_dp *intel_dp);
-void intel_edp_drrs_invalidate(struct drm_device *dev,
-		unsigned frontbuffer_bits);
-void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
 
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c
index 57095f5..249d0b3 100644
--- a/drivers/gpu/drm/i915/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
@@ -154,7 +154,6 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
 	intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
 
 	intel_psr_invalidate(dev, obj->frontbuffer_bits);
-	intel_edp_drrs_invalidate(dev, obj->frontbuffer_bits);
 	intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin);
 }
 
@@ -181,7 +180,6 @@ void intel_frontbuffer_flush(struct drm_device *dev,
 
 	intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
 
-	intel_edp_drrs_flush(dev, frontbuffer_bits);
 	intel_psr_flush(dev, frontbuffer_bits);
 	intel_fbc_flush(dev_priv, frontbuffer_bits);
 }
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 02/18] drm/i915: Generic DRRS state Machine
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 03/18] drm/i915: Addition of the drrs_min_vrefresh in VBT Ramalingam C
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

DRRS is a power saving feature, which will refresh the display
at the lowest supported refresh rate, based on the rate of change
of display content to be rendered.

This patch implements the Generic state machine for the Idleness DRRS.
Idleness DRRS is nothing but, when the content of the Display is not
changed for a certain duration, refresh rate will be set to the
minimum vrefresh supported by the panel.

This will be extended for media playback DRRS. i.e based on the
display content's Frames Per Second, required lowest vrefresh to
support the FPS will be used to render the data. This involves
the Userspace and Kernel handshaking.

DRRS Support for the encoders like DSI and eDP can be implemented
as a separate module and get registered with this generic DRRS stack.
Hence extending to new encoder and platform is made easy.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/Makefile            |    1 +
 drivers/gpu/drm/i915/i915_drv.h          |   77 ++++-
 drivers/gpu/drm/i915/intel_drrs.c        |  460 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drrs.h        |   34 +++
 drivers/gpu/drm/i915/intel_drv.h         |    5 +
 drivers/gpu/drm/i915/intel_frontbuffer.c |    2 +
 6 files changed, 578 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/intel_drrs.c
 create mode 100644 drivers/gpu/drm/i915/intel_drrs.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index b7ddf48..5fd100b 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -54,6 +54,7 @@ i915-y += intel_audio.o \
 	  intel_modes.o \
 	  intel_overlay.o \
 	  intel_psr.o \
+	  intel_drrs.o \
 	  intel_sideband.o \
 	  intel_sprite.o
 i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 922dd68..00982bb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -930,10 +930,82 @@ struct i915_fbc {
 	} no_fbc_reason;
 };
 
+/**
+ * DRRS Support Type:
+ * DRRS_NOT_SUPPORTED		: DRRS not supported
+ * STATIC_DRRS_SUPPORT		: Need a complete modeset for DRRS
+ * SEAMLESS_DRRS_SUPPORT	: Seamless vrefresh switch is supported on HW
+ * SEAMLESS_DRRS_SUPPORT_SW	: Seamless vrefresh switch is supported on SW
+ */
 enum drrs_support_type {
 	DRRS_NOT_SUPPORTED = 0,
 	STATIC_DRRS_SUPPORT = 1,
-	SEAMLESS_DRRS_SUPPORT = 2
+	SEAMLESS_DRRS_SUPPORT = 2,
+	SEAMLESS_DRRS_SUPPORT_SW = 3,
+};
+
+/**
+ * Different DRRS States:
+ * DRRS_HIGH_RR	: Refreshrate of Fixed mode. [Maximum Vrefresh]
+ * DRRS_LOW_RR	: Refreshrate of Downclock mode. [Minimum vrefresh]
+ */
+enum drrs_refresh_rate_type {
+	DRRS_HIGH_RR,
+	DRRS_LOW_RR,
+	DRRS_MAX_RR,
+};
+
+struct drrs_info {
+	enum drrs_support_type type;
+	enum drrs_refresh_rate_type current_rr_type;
+	enum drrs_refresh_rate_type target_rr_type;
+};
+
+struct i915_drrs;
+
+/**
+ * intel_idleness_drrs_work:
+ * work		: Deferred work to declare the Idleness, if not disturbed.
+ * crtc		: Target drm_crtc
+ * interval	: Time to defer the deferred work
+ */
+struct intel_idleness_drrs_work {
+	struct delayed_work work;
+	struct i915_drrs *drrs;
+
+	/* Idleness interval in mSec*/
+	int interval;
+};
+
+/* Encoder related function pointers */
+struct drrs_encoder_ops {
+	int (*init)(struct i915_drrs *, struct drm_display_mode *);
+	void (*exit)(struct i915_drrs *);
+	void (*set_drrs_state)(struct i915_drrs *);
+	bool (*is_drrs_hr_state_pending)(struct i915_drrs *);
+};
+
+struct i915_drrs {
+	/* Whether another pipe is enabled in parallel */
+	bool is_clone;
+
+	/* Whether DRRS is supported on this Panel */
+	bool has_drrs;
+
+	/* Holds the DRRS state machine states */
+	struct drrs_info drrs_state;
+
+	/* Pointer to the relevant connector */
+	struct intel_connector *connector;
+
+	/* Front buffer tracking bits */
+	unsigned busy_frontbuffer_bits;
+
+	struct intel_idleness_drrs_work *idleness_drrs_work;
+
+	/* Functions to hold encoder specific DRRS functions */
+	struct drrs_encoder_ops *encoder_ops;
+	struct mutex drrs_mutex;
 };
 
 struct i915_psr {
@@ -1697,6 +1769,7 @@ struct drm_i915_private {
 
 	struct i915_hotplug hotplug;
 	struct i915_fbc fbc;
+	struct i915_drrs *drrs[I915_MAX_PIPES];
 	struct intel_opregion opregion;
 	struct intel_vbt_data vbt;
 
@@ -2394,6 +2467,8 @@ struct drm_i915_cmd_table {
 #define IS_HSW_ULX(dev)		(INTEL_DEVID(dev) == 0x0A0E || \
 				 INTEL_DEVID(dev) == 0x0A1E)
 #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
+#define IS_PLATFORM_HAS_DRRS(dev)	(INTEL_INFO(dev)->gen >= 7 || \
+					 INTEL_INFO(dev)->gen <= 9)
 
 #define SKL_REVID_A0		(0x0)
 #define SKL_REVID_B0		(0x1)
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
new file mode 100644
index 0000000..eb67909
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#include <drm/i915_drm.h>
+#include <linux/delay.h>
+
+#include "i915_drv.h"
+#include "intel_drv.h"
+#include "intel_drrs.h"
+
+int get_drrs_struct_index_for_pipe(struct drm_i915_private *dev_priv, int pipe)
+{
+	struct intel_crtc *crtc;
+	struct i915_drrs *drrs;
+	int i;
+
+	for (i = 0; i < I915_MAX_PIPES; i++) {
+		drrs = dev_priv->drrs[i];
+		if (drrs) {
+			crtc = to_intel_crtc(
+					drrs->connector->encoder->base.crtc);
+			if (crtc && crtc->pipe == pipe)
+				return i;
+		}
+	}
+	return -ENXIO;
+}
+
+int get_drrs_struct_index_for_crtc(struct drm_i915_private *dev_priv,
+						struct intel_crtc *intel_crtc)
+{
+	int i;
+
+	for (i = 0; i < I915_MAX_PIPES; i++) {
+		if (dev_priv->drrs[i] &&
+			(dev_priv->drrs[i]->connector->encoder->base.crtc ==
+							&intel_crtc->base))
+			return i;
+	}
+
+	/* No drrs struct exist for this crtc */
+	return -ENXIO;
+
+}
+
+int get_drrs_struct_index_for_connector(struct drm_i915_private *dev_priv,
+					struct intel_connector *intel_connector)
+{
+	int i;
+
+	for (i = 0; i < I915_MAX_PIPES; i++) {
+		if (dev_priv->drrs[i] &&
+			(dev_priv->drrs[i]->connector == intel_connector))
+			return i;
+	}
+
+	/* No drrs struct exist for this connector */
+	return -ENXIO;
+}
+
+int get_free_drrs_struct_index(struct drm_i915_private *dev_priv)
+{
+	int i;
+
+	for (i = 0; i < I915_MAX_PIPES; i++) {
+		if (!dev_priv->drrs[i])
+			return i;
+	}
+
+	/* All drrs index are busy */
+	return -EBUSY;
+}
+
+void intel_set_drrs_state(struct i915_drrs *drrs)
+{
+	struct drrs_info *drrs_state;
+	struct drm_display_mode *target_mode;
+	struct intel_crtc *intel_crtc;
+	struct intel_panel *panel;
+	int refresh_rate;
+
+	if (!drrs || !drrs->has_drrs) {
+		DRM_ERROR("DRRS is not supported on this pipe\n");
+		return;
+	}
+
+	panel = &drrs->connector->panel;
+	drrs_state = &drrs->drrs_state;
+
+	intel_crtc = to_intel_crtc(drrs->connector->encoder->base.crtc);
+
+	if (!intel_crtc) {
+		DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
+		return;
+	}
+
+	if (!intel_crtc->active) {
+		DRM_INFO("Encoder has been disabled. CRTC not Active\n");
+		return;
+	}
+
+	target_mode = panel->target_mode;
+	if (target_mode == NULL) {
+		DRM_ERROR("target_mode cannot be NULL\n");
+		return;
+	}
+	refresh_rate = target_mode->vrefresh;
+
+	if (refresh_rate <= 0) {
+		DRM_ERROR("Refresh rate should be positive non-zero.<%d>\n",
+								refresh_rate);
+		return;
+	}
+
+	if (drrs_state->target_rr_type >= DRRS_MAX_RR) {
+		DRM_ERROR("Unknown refresh_rate_type\n");
+		return;
+	}
+
+	if (drrs_state->target_rr_type == drrs_state->current_rr_type) {
+		DRM_INFO("Requested for previously set RR. Ignoring\n");
+		return;
+	}
+
+	drrs->encoder_ops->set_drrs_state(drrs);
+	if (drrs_state->type != SEAMLESS_DRRS_SUPPORT_SW) {
+
+		/*
+		 * If it is non-DSI encoders.
+		 * As only DSI has SEAMLESS_DRRS_SUPPORT_SW.
+		 */
+		drrs_state->current_rr_type = drrs_state->target_rr_type;
+		DRM_INFO("Refresh Rate set to : %dHz\n", refresh_rate);
+	}
+}
+
+static void intel_idleness_drrs_work_fn(struct work_struct *__work)
+{
+	struct intel_idleness_drrs_work *work =
+		container_of(to_delayed_work(__work),
+				struct intel_idleness_drrs_work, work);
+	struct intel_panel *panel;
+	struct i915_drrs *drrs = work->drrs;
+
+	panel = &drrs->connector->panel;
+
+	/* TODO: If DRRS is not supported on clone mode act here */
+	mutex_lock(&drrs->drrs_mutex);
+	if (panel->target_mode != NULL)
+		DRM_ERROR("FIXME: We shouldn't be here\n");
+
+	panel->target_mode = panel->downclock_mode;
+	drrs->drrs_state.target_rr_type = DRRS_LOW_RR;
+
+	intel_set_drrs_state(drrs);
+
+	panel->target_mode = NULL;
+	mutex_unlock(&drrs->drrs_mutex);
+}
+
+static void intel_cancel_idleness_drrs_work(struct i915_drrs *drrs, bool sync)
+{
+	if (!drrs || !drrs->has_drrs || !drrs->idleness_drrs_work)
+		return;
+	if (sync) {
+		mutex_unlock(&drrs->drrs_mutex);
+		cancel_delayed_work_sync(&drrs->idleness_drrs_work->work);
+		mutex_lock(&drrs->drrs_mutex);
+	} else {
+		cancel_delayed_work(&drrs->idleness_drrs_work->work);
+	}
+	drrs->connector->panel.target_mode = NULL;
+}
+
+static void intel_enable_idleness_drrs(struct i915_drrs *drrs)
+{
+	bool force_enable_drrs = false;
+
+	mutex_lock(&drrs->drrs_mutex);
+
+	/* Capturing the deferred request for disable_drrs */
+	if (drrs->drrs_state.type == SEAMLESS_DRRS_SUPPORT_SW &&
+				drrs->encoder_ops->is_drrs_hr_state_pending) {
+		if (drrs->encoder_ops->is_drrs_hr_state_pending(drrs))
+				force_enable_drrs = true;
+	}
+
+	if (drrs->drrs_state.current_rr_type != DRRS_LOW_RR ||
+							force_enable_drrs) {
+		drrs->idleness_drrs_work->drrs = drrs;
+
+		/*
+		 * Delay the actual enabling to let pageflipping cease and the
+		 * display to settle before starting DRRS
+		 */
+		schedule_delayed_work(&drrs->idleness_drrs_work->work,
+			msecs_to_jiffies(drrs->idleness_drrs_work->interval));
+	}
+	mutex_unlock(&drrs->drrs_mutex);
+}
+
+/* Needs to be called with drrs_mutex acquired */
+void intel_disable_idleness_drrs(struct i915_drrs *drrs)
+{
+	struct intel_panel *panel;
+
+	mutex_lock(&drrs->drrs_mutex);
+	panel = &drrs->connector->panel;
+
+	/* as part of disable DRRS, reset refresh rate to HIGH_RR */
+	if (drrs->drrs_state.current_rr_type == DRRS_LOW_RR) {
+		if (panel->target_mode != NULL)
+			DRM_ERROR("FIXME: We shouldn't be here\n");
+
+		panel->target_mode = panel->fixed_mode;
+		drrs->drrs_state.target_rr_type = DRRS_HIGH_RR;
+		intel_set_drrs_state(drrs);
+		panel->target_mode = NULL;
+	}
+	mutex_unlock(&drrs->drrs_mutex);
+}
+
+/**
+ * intel_drrs_invalidate - Disable Idleness DRRS
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called everytime rendering on the given planes start.
+ * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
+ *
+ * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
+ */
+void intel_drrs_invalidate(struct drm_device *dev,
+		unsigned frontbuffer_bits)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_drrs *drrs;
+	struct intel_crtc *crtc;
+	int pipe;
+	int index;
+
+
+	for (pipe = 0; pipe < 4; pipe++) {
+		if (frontbuffer_bits & (0xf << (16 * pipe))) {
+			index = get_drrs_struct_index_for_pipe(dev_priv, pipe);
+			if (index < 0)
+				return;
+
+			drrs = dev_priv->drrs[index];
+			if (!drrs || !drrs->has_drrs)
+				return;
+
+			intel_cancel_idleness_drrs_work(drrs, false);
+
+			crtc = to_intel_crtc(
+					drrs->connector->encoder->base.crtc);
+			if (!crtc)
+				return;
+
+			intel_disable_idleness_drrs(drrs);
+
+			frontbuffer_bits &=
+					INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe);
+
+			mutex_lock(&drrs->drrs_mutex);
+			drrs->busy_frontbuffer_bits |= frontbuffer_bits;
+			mutex_unlock(&drrs->drrs_mutex);
+		}
+	}
+}
+
+/**
+ * intel_drrs_flush - Restart Idleness DRRS
+ * @dev: DRM device
+ * @frontbuffer_bits: frontbuffer plane tracking bits
+ *
+ * This function gets called every time rendering on the given planes has
+ * completed or flip on a crtc is completed. So DRRS should be upclocked
+ * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
+ * if no other planes are dirty.
+ *
+ * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
+ */
+void intel_drrs_flush(struct drm_device *dev,
+		unsigned frontbuffer_bits)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_drrs *drrs;
+	int pipe;
+	int index;
+
+	for (pipe = 0; pipe < 4; pipe++) {
+		if (frontbuffer_bits & (0xf << (16 * pipe))) {
+			index = get_drrs_struct_index_for_pipe(dev_priv, pipe);
+			if (index < 0)
+				return;
+
+			drrs = dev_priv->drrs[index];
+			if (!drrs || !drrs->has_drrs)
+				return;
+
+			intel_cancel_idleness_drrs_work(drrs, false);
+
+			mutex_lock(&drrs->drrs_mutex);
+			drrs->busy_frontbuffer_bits &= ~frontbuffer_bits;
+			mutex_unlock(&drrs->drrs_mutex);
+
+			intel_disable_idleness_drrs(drrs);
+
+			if (!drrs->busy_frontbuffer_bits)
+				intel_enable_idleness_drrs(drrs);
+		}
+	}
+}
+
+/* Idleness detection logic is initialized */
+int intel_drrs_idleness_detection_init(struct i915_drrs *drrs)
+{
+	struct intel_idleness_drrs_work *work;
+
+	work = kzalloc(sizeof(struct intel_idleness_drrs_work), GFP_KERNEL);
+	if (!work) {
+		DRM_ERROR("Failed to allocate DRRS work structure\n");
+		return -ENOMEM;
+	}
+
+	drrs->is_clone = false;
+	work->interval = DRRS_IDLENESS_INTERVAL_MS;
+	work->drrs = drrs;
+	INIT_DELAYED_WORK(&work->work, intel_idleness_drrs_work_fn);
+
+	drrs->idleness_drrs_work = work;
+	return 0;
+}
+
+/*
+ * intel_drrs_init : General entry for DRRS Unit. Called for each PIPE.
+ */
+int intel_drrs_init(struct drm_device *dev,
+				struct intel_connector *intel_connector,
+					struct drm_display_mode *fixed_mode)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_drrs *drrs;
+	int ret = 0, index;
+
+	if (!IS_PLATFORM_HAS_DRRS(dev)) {
+		DRM_ERROR("DRRS is not enabled on this platform\n");
+		return -EPERM;
+	}
+
+	if (get_drrs_struct_index_for_connector(dev_priv, intel_connector)
+									>= 0) {
+		DRM_ERROR("DRRS is already initialized for this connector\n");
+		return -EINVAL;
+	}
+
+	index = get_free_drrs_struct_index(dev_priv);
+	if (index < 0) {
+		DRM_ERROR("DRRS is initialized for all pipes\n");
+		return -EBUSY;
+	}
+
+	/* FIXME: Linkedlist can be used */
+	dev_priv->drrs[index] = kzalloc(sizeof(*drrs), GFP_KERNEL);
+	if (!dev_priv->drrs[index]) {
+		DRM_ERROR("DRRS memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	drrs = dev_priv->drrs[index];
+	drrs->connector = intel_connector;
+
+	if (!drrs->encoder_ops) {
+		DRM_ERROR("Encoder ops not initialized\n");
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	/* First check if DRRS is enabled from VBT struct */
+	if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
+		DRM_INFO("Panel doesn't support SEAMLESS DRRS\n");
+		ret = -EPERM;
+		goto err_out;
+	}
+
+	if (!drrs->encoder_ops->init || !drrs->encoder_ops->exit ||
+					!drrs->encoder_ops->set_drrs_state) {
+		DRM_ERROR("Essential func ptrs are NULL\n");
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	ret = drrs->encoder_ops->init(drrs, fixed_mode);
+	if (ret < 0) {
+		DRM_ERROR("Encoder DRRS init failed\n");
+		goto err_out;
+	}
+
+	ret = intel_drrs_idleness_detection_init(drrs);
+	if (ret < 0) {
+		drrs->encoder_ops->exit(drrs);
+		goto err_out;
+	}
+
+	/* SEAMLESS DRRS is supported and downclock mode also exist */
+	drrs->has_drrs = true;
+	to_intel_crtc(intel_encoder->base.crtc)->config->has_drrs = true;
+	mutex_init(&drrs->drrs_mutex);
+	drrs->drrs_state.current_rr_type = DRRS_HIGH_RR;
+	DRM_INFO("SEAMLESS DRRS supported on this panel.\n");
+
+	return 0;
+
+err_out:
+	drrs->drrs_state.type = DRRS_NOT_SUPPORTED;
+	kfree(dev_priv->drrs[index]);
+	dev_priv->drrs[index] = NULL;
+	return ret;
+}
+
+void intel_drrs_exit(struct drm_device *dev,
+				struct intel_connector *intel_connector)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_drrs *drrs;
+	int index;
+
+	index = get_drrs_struct_index_for_connector(dev_priv, intel_connector);
+	if (index < 0)
+		return;
+
+	drrs = dev_priv->drrs[index];
+	intel_cancel_idleness_drrs_work(drrs, true);
+
+	if (drrs->encoder_ops->exit)
+		drrs->encoder_ops->exit(drrs);
+
+	drrs->has_drrs = false;
+	to_intel_crtc(intel_connector->encoder->base.crtc)->config->has_drrs =
+									false;
+	mutex_destroy(&drrs->drrs_mutex);
+	kfree(drrs->idleness_drrs_work);
+
+	kfree(drrs);
+	dev_priv->drrs[index] = NULL;
+}
diff --git a/drivers/gpu/drm/i915/intel_drrs.h b/drivers/gpu/drm/i915/intel_drrs.h
new file mode 100644
index 0000000..a07f023
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_drrs.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef INTEL_DRRS_H__
+#define INTEL_DRRS_H__
+
+#define DRRS_IDLENESS_INTERVAL_MS	1000
+
+struct intel_encoder;
+
+int get_drrs_struct_index_for_crtc(struct drm_i915_private *dev_priv,
+						struct intel_crtc *intel_crtc);
+int get_drrs_struct_index_for_connector(struct drm_i915_private *dev_priv,
+				struct intel_connector *intel_connector);
+int get_free_drrs_struct_index(struct drm_i915_private *dev_priv);
+
+int intel_drrs_init(struct drm_device *dev,
+			struct intel_connector *intel_connector,
+				struct drm_display_mode *fixed_mode);
+
+#endif /* INTEL_DRRS_H__ */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e2f534a..726c31d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -37,6 +37,8 @@
 #include <drm/drm_rect.h>
 #include <drm/drm_atomic.h>
 
+#include "intel_drrs.h"
+
 /**
  * _wait_for - magic (register) wait macro
  *
@@ -171,6 +173,7 @@ struct intel_encoder {
 struct intel_panel {
 	struct drm_display_mode *fixed_mode;
 	struct drm_display_mode *downclock_mode;
+	struct drm_display_mode *target_mode;
 	int fitting_mode;
 
 	/* backlight */
@@ -1198,6 +1201,8 @@ void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
 void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
 uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
 void intel_plane_destroy(struct drm_plane *plane);
+void intel_drrs_invalidate(struct drm_device *dev, unsigned frontbuffer_bits);
+void intel_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
 
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c
index 249d0b3..62d18eb 100644
--- a/drivers/gpu/drm/i915/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
@@ -153,6 +153,7 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
 
 	intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
 
+	intel_drrs_invalidate(dev, obj->frontbuffer_bits);
 	intel_psr_invalidate(dev, obj->frontbuffer_bits);
 	intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin);
 }
@@ -180,6 +181,7 @@ void intel_frontbuffer_flush(struct drm_device *dev,
 
 	intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
 
+	intel_drrs_flush(dev, frontbuffer_bits);
 	intel_psr_flush(dev, frontbuffer_bits);
 	intel_fbc_flush(dev_priv, frontbuffer_bits);
 }
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 03/18] drm/i915: Addition of the drrs_min_vrefresh in VBT
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 02/18] drm/i915: Generic DRRS state Machine Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 04/18] drm/i915: Implementation of Generic DSI DRRS Ramalingam C
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

VBT structure's block 42 is updated as per the current VBT v188
specification and additonal member drrs_min_vrefresh is added.

Corresponding logic for parsing drrs_min_vrefresh is added.
drrs_min_vrefresh is nothing but lowest vrefresh supported by the panel.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h   |    1 +
 drivers/gpu/drm/i915/intel_bios.c |    3 +++
 drivers/gpu/drm/i915/intel_bios.h |    9 +++++++--
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 00982bb..677293d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1479,6 +1479,7 @@ struct intel_vbt_data {
 	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
 
 	enum drrs_support_type drrs_type;
+	unsigned int drrs_min_vrefresh;
 
 	/* eDP */
 	int edp_rate;
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 198fc3c..5d6117a 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -251,6 +251,9 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 	if (!lvds_lfp_data)
 		return;
 
+	dev_priv->vbt.drrs_min_vrefresh = (unsigned int)
+			lvds_lfp_data->seamless_drrs_min_vrefresh[panel_type];
+
 	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
 	if (!lvds_lfp_data_ptrs)
 		return;
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index af0b476..b0cd827 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -338,8 +338,6 @@ struct lvds_fp_timing {
 	u32 pp_off_reg_val;
 	u32 pp_cycle_reg;
 	u32 pp_cycle_reg_val;
-	u32 pfit_reg;
-	u32 pfit_reg_val;
 	u16 terminator;
 } __packed;
 
@@ -385,8 +383,15 @@ struct bdb_lvds_lfp_data_entry {
 	struct lvds_pnp_id pnp_id;
 } __packed;
 
+struct lfp_panel_name {
+	u8 name[13];
+} __packed;
+
 struct bdb_lvds_lfp_data {
 	struct bdb_lvds_lfp_data_entry data[16];
+	struct lfp_panel_name name[16];
+	u16 scaling_enabling_bits;
+	u8 seamless_drrs_min_vrefresh[16];
 } __packed;
 
 #define BDB_BACKLIGHT_TYPE_NONE	0
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 04/18] drm/i915: Implementation of Generic DSI DRRS
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (2 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 03/18] drm/i915: Addition of the drrs_min_vrefresh in VBT Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 05/18] drm/i915: Adjusting the pclk for dual link and burst mode Ramalingam C
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

This patch Implements the generic DSI DRRS functions and registers
them with Generic DRRS state machine.

Platform specific DSI DRRS functions will be implemented and
registered with this generic DSI DRRS implementation. Hence
extending the DSI DRRS to new platform is made simple.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/Makefile         |    1 +
 drivers/gpu/drm/i915/intel_drrs.c     |   10 ++
 drivers/gpu/drm/i915/intel_dsi.h      |    3 +
 drivers/gpu/drm/i915/intel_dsi_drrs.c |  320 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dsi_drrs.h |   61 +++++++
 drivers/gpu/drm/i915/intel_dsi_pll.c  |    5 -
 6 files changed, 395 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.c
 create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 5fd100b..4f77fb2 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -55,6 +55,7 @@ i915-y += intel_audio.o \
 	  intel_overlay.o \
 	  intel_psr.o \
 	  intel_drrs.o \
+	  intel_dsi_drrs.o \
 	  intel_sideband.o \
 	  intel_sprite.o
 i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index eb67909..2a776d2 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -19,6 +19,7 @@
 
 #include "i915_drv.h"
 #include "intel_drv.h"
+#include "intel_dsi.h"
 #include "intel_drrs.h"
 
 int get_drrs_struct_index_for_pipe(struct drm_i915_private *dev_priv, int pipe)
@@ -354,6 +355,7 @@ int intel_drrs_init(struct drm_device *dev,
 					struct drm_display_mode *fixed_mode)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder = intel_connector->encoder;
 	struct i915_drrs *drrs;
 	int ret = 0, index;
 
@@ -384,6 +386,14 @@ int intel_drrs_init(struct drm_device *dev,
 	drrs = dev_priv->drrs[index];
 	drrs->connector = intel_connector;
 
+	if (intel_encoder->type == INTEL_OUTPUT_DSI) {
+		drrs->encoder_ops = get_intel_dsi_drrs_ops();
+	} else {
+		DRM_ERROR("DRRS: Unsupported Encoder\n");
+		ret = -EINVAL;
+		goto err_out;
+	}
+
 	if (!drrs->encoder_ops) {
 		DRM_ERROR("Encoder ops not initialized\n");
 		ret = -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index 2784ac4..129f68e 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -28,6 +28,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_mipi_dsi.h>
 #include "intel_drv.h"
+#include "intel_dsi_drrs.h"
 
 /* Dual Link support */
 #define DSI_DUAL_LINK_NONE		0
@@ -47,6 +48,8 @@ struct intel_dsi {
 	/* bit mask of ports being driven */
 	u16 ports;
 
+	struct dsi_drrs dsi_drrs;
+
 	/* if true, use HS mode, otherwise LP */
 	bool hs;
 
diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
new file mode 100644
index 0000000..6ab0e9e
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#include <drm/i915_drm.h>
+#include <linux/delay.h>
+
+#include "intel_drv.h"
+#include "intel_dsi.h"
+
+/* Work function for DSI deferred work */
+static void intel_mipi_drrs_work_fn(struct work_struct *__work)
+{
+	struct intel_mipi_drrs_work *work =
+				container_of(to_delayed_work(__work),
+					struct intel_mipi_drrs_work, work);
+	struct i915_drrs *drrs = work->drrs;
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct dsi_mnp *dsi_mnp;
+	struct drm_display_mode *prev_mode = NULL;
+	bool fallback_attempt = false;
+	int ret, retry_cnt = 3;
+
+init:
+	dsi_mnp = &dsi_drrs->mnp[work->target_rr_type];
+	DRM_DEBUG("Refresh rate Type: %d-->%d\n",
+					drrs->drrs_state.current_rr_type,
+						work->target_rr_type);
+	DRM_DEBUG("Target RR: %d\n", work->target_mode->vrefresh);
+
+retry:
+	if (!intel_crtc || !intel_crtc->active)
+		goto out;
+
+	ret = dsi_drrs->ops->configure_dsi_pll(intel_encoder, dsi_mnp);
+	if (ret == 0) {
+
+		/* PLL Programming is successful */
+		mutex_lock(&drrs->drrs_mutex);
+		drrs->drrs_state.current_rr_type = work->target_rr_type;
+		mutex_unlock(&drrs->drrs_mutex);
+		DRM_INFO("Refresh Rate set to : %dHz\n",
+						work->target_mode->vrefresh);
+
+		/* TODO: Update crtc mode and drain ladency with watermark */
+
+	} else if (ret == -ETIMEDOUT && retry_cnt) {
+
+		/* Timed out. But still attempts are allowed */
+		retry_cnt--;
+		DRM_DEBUG("Retry left ... <%d>\n", retry_cnt);
+		goto retry;
+	} else if (ret == -EACCES && !fallback_attempt) {
+
+		/*
+		 * PLL Didn't lock for the programmed value
+		 * fall back to prev mode
+		 */
+		DRM_ERROR("Falling back to the previous DRRS state. %d->%d\n",
+					work->target_rr_type,
+					drrs->drrs_state.current_rr_type);
+
+		mutex_lock(&drrs->drrs_mutex);
+		drrs->drrs_state.target_rr_type =
+					drrs->drrs_state.current_rr_type;
+		mutex_unlock(&drrs->drrs_mutex);
+
+		work->target_rr_type = drrs->drrs_state.target_rr_type;
+		drm_mode_destroy(intel_encoder->base.dev, work->target_mode);
+
+		if (work->target_rr_type == DRRS_HIGH_RR)
+			prev_mode = drrs->connector->panel.fixed_mode;
+		else if (work->target_rr_type == DRRS_LOW_RR)
+			prev_mode = drrs->connector->panel.downclock_mode;
+
+		work->target_mode = drm_mode_duplicate(intel_encoder->base.dev,
+								prev_mode);
+		fallback_attempt = true;
+		goto init;
+	} else {
+
+		/*
+		 * All attempts are failed or Fall back
+		 * mode all didn't go through.
+		 */
+		if (fallback_attempt)
+			DRM_ERROR("DRRS State Fallback attempt failed\n");
+		if (ret == -ETIMEDOUT)
+			DRM_ERROR("TIMEDOUT in all retry attempt\n");
+	}
+
+out:
+	drm_mode_destroy(intel_encoder->base.dev, work->target_mode);
+	work->work_completed = true;
+}
+
+/* Whether DRRS_HR_STATE is pending in the dsi deferred work */
+bool intel_dsi_is_drrs_hr_state_pending(struct i915_drrs *drrs)
+{
+	struct intel_dsi *intel_dsi =
+			enc_to_intel_dsi(&drrs->connector->encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+
+	if (work_busy(&work->work.work) && work->target_rr_type == DRRS_HIGH_RR)
+		return true;
+	return false;
+}
+
+void intel_dsi_set_drrs_state(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct drm_display_mode *target_mode =
+				drrs->connector->panel.target_mode;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+	unsigned int ret;
+
+	ret = work_busy(&work->work.work);
+	if (ret) {
+		if (work->target_mode)
+			if (work->target_mode->vrefresh ==
+						target_mode->vrefresh) {
+				DRM_INFO("Repeated request for %dHz\n",
+							target_mode->vrefresh);
+				return;
+			}
+		DRM_DEBUG("Cancelling an queued/executing work\n");
+		atomic_set(&work->abort_wait_loop, 1);
+		cancel_delayed_work_sync(&work->work);
+		atomic_set(&work->abort_wait_loop, 0);
+		if ((ret & WORK_BUSY_PENDING) && !work->work_completed)
+			drm_mode_destroy(intel_encoder->base.dev,
+							work->target_mode);
+	}
+
+	work->work_completed = false;
+	work->drrs = drrs;
+	work->target_rr_type = drrs->drrs_state.target_rr_type;
+	work->target_mode = drm_mode_duplicate(intel_encoder->base.dev,
+								target_mode);
+	schedule_delayed_work(&work->work, 0);
+}
+
+/* DSI deferred function init*/
+int intel_dsi_drrs_deferred_work_init(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work;
+
+	work = kzalloc(sizeof(struct intel_mipi_drrs_work), GFP_KERNEL);
+	if (!work) {
+		DRM_ERROR("Failed to allocate mipi DRRS work structure\n");
+		return -ENOMEM;
+	}
+
+	atomic_set(&work->abort_wait_loop, 0);
+	INIT_DELAYED_WORK(&work->work, intel_mipi_drrs_work_fn);
+	work->target_mode = NULL;
+	work->work_completed = true;
+
+	dsi_drrs->mipi_drrs_work = work;
+	return 0;
+}
+
+/* Based on the VBT's min supported vrefresh, downclock mode will be created */
+struct drm_display_mode *
+intel_dsi_calc_panel_downclock(struct i915_drrs *drrs,
+			struct drm_display_mode *fixed_mode)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct drm_display_mode *downclock_mode = NULL;
+
+	if (dsi_drrs->min_vrefresh == 0 ||
+			dsi_drrs->min_vrefresh >= fixed_mode->vrefresh) {
+		DRM_ERROR("Invalid min Vrefresh. %d\n", dsi_drrs->min_vrefresh);
+		return NULL;
+	}
+
+	/* Allocate */
+	downclock_mode =
+			drm_mode_duplicate(intel_encoder->base.dev, fixed_mode);
+	if (!downclock_mode) {
+		DRM_ERROR("Downclock mode allocation failed. No memory\n");
+		return NULL;
+	}
+
+	downclock_mode->vrefresh = dsi_drrs->min_vrefresh;
+	DRM_DEBUG("drrs_min_vrefresh = %u\n", downclock_mode->vrefresh);
+	downclock_mode->clock = downclock_mode->vrefresh *
+		downclock_mode->vtotal * downclock_mode->htotal / 1000;
+
+	return downclock_mode;
+}
+
+/* Main init Enrty for DSI DRRS module */
+int intel_dsi_drrs_init(struct i915_drrs *drrs,
+					struct drm_display_mode *fixed_mode)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct drm_i915_private *dev_priv =
+					intel_encoder->base.dev->dev_private;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_panel *panel = &drrs->connector->panel;
+	struct drm_display_mode *downclock_mode;
+	int ret = 0;
+
+	dsi_drrs->min_vrefresh = dev_priv->vbt.drrs_min_vrefresh;
+
+	if (fixed_mode->vrefresh == 0)
+		fixed_mode->vrefresh = drm_mode_vrefresh(fixed_mode);
+
+	/* Modes Initialization */
+	downclock_mode = intel_dsi_calc_panel_downclock(drrs, fixed_mode);
+	if (!downclock_mode) {
+		DRM_ERROR("Downclock mode not Found\n");
+		ret = -ENOMEM;
+		goto out_err_1;
+	}
+
+	DRM_DEBUG("downclock_mode :\n");
+	drm_mode_debug_printmodeline(downclock_mode);
+
+	panel->target_mode = NULL;
+
+	if (!dsi_drrs->ops || !dsi_drrs->ops->mnp_calculate_for_mode ||
+					!dsi_drrs->ops->configure_dsi_pll) {
+		DRM_ERROR("DSI platform ops not initialized\n");
+		ret = -EINVAL;
+		goto out_err_2;
+	}
+
+	/* Calculate mnp for fixed and downclock modes */
+	ret = dsi_drrs->ops->mnp_calculate_for_mode(
+			intel_encoder, &dsi_drrs->mnp[DRRS_HIGH_RR],
+			fixed_mode);
+	if (ret < 0)
+		goto out_err_2;
+
+	ret = dsi_drrs->ops->mnp_calculate_for_mode(
+			intel_encoder, &dsi_drrs->mnp[DRRS_LOW_RR],
+			downclock_mode);
+	if (ret < 0)
+		goto out_err_2;
+
+	ret = intel_dsi_drrs_deferred_work_init(drrs);
+	if (ret < 0)
+		goto out_err_2;
+
+	/* In DSI SEAMLESS DRRS is a SW driven feature */
+	drrs->drrs_state.type = SEAMLESS_DRRS_SUPPORT_SW;
+	intel_panel_init(panel, fixed_mode, downclock_mode);
+
+	return ret;
+
+out_err_2:
+	drm_mode_destroy(intel_encoder->base.dev, downclock_mode);
+out_err_1:
+	return ret;
+}
+
+void intel_dsi_drrs_exit(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+	unsigned int ret;
+
+	ret = work_busy(&work->work.work);
+	if (ret) {
+		DRM_DEBUG("Cancelling an queued/executing work\n");
+		atomic_set(&work->abort_wait_loop, 1);
+		cancel_delayed_work_sync(&work->work);
+		atomic_set(&work->abort_wait_loop, 0);
+		if ((ret & WORK_BUSY_PENDING) && !work->work_completed)
+			drm_mode_destroy(intel_encoder->base.dev,
+							work->target_mode);
+	}
+
+	drm_mode_destroy(intel_encoder->base.dev,
+				drrs->connector->panel.downclock_mode);
+	drrs->connector->panel.downclock_mode = NULL;
+
+	kfree(dsi_drrs->mipi_drrs_work);
+	drrs->drrs_state.type = DRRS_NOT_SUPPORTED;
+}
+
+struct drrs_encoder_ops drrs_dsi_ops = {
+	.init = intel_dsi_drrs_init,
+	.exit = intel_dsi_drrs_exit,
+	.set_drrs_state = intel_dsi_set_drrs_state,
+	.is_drrs_hr_state_pending = intel_dsi_is_drrs_hr_state_pending,
+};
+
+/* Call back Function for Intel_drrs module to get the dsi func ptr */
+inline struct drrs_encoder_ops *get_intel_dsi_drrs_ops(void)
+{
+	return &drrs_dsi_ops;
+}
diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.h b/drivers/gpu/drm/i915/intel_dsi_drrs.h
new file mode 100644
index 0000000..27736a0
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef INTEL_DSI_DRRS_H
+#define INTEL_DSI_DRRS_H
+
+struct dsi_mnp {
+	u32 dsi_pll_ctrl;
+	u32 dsi_pll_div;
+};
+
+struct drrs_dsi_platform_ops {
+	int (*configure_dsi_pll)(struct intel_encoder *encoder,
+						struct dsi_mnp *dsi_mnp);
+	int (*mnp_calculate_for_mode)(struct intel_encoder *encoder,
+				struct dsi_mnp *dsi_mnp,
+				struct drm_display_mode *mode);
+};
+
+/**
+ * MIPI PLL register dont have a option to perform a seamless
+ * PLL divider change. To simulate that operation in SW we are using
+ * this deferred work
+ */
+struct intel_mipi_drrs_work {
+	struct delayed_work work;
+	struct i915_drrs *drrs;
+
+	/* Target Refresh rate type and the target mode */
+	enum drrs_refresh_rate_type target_rr_type;
+	struct drm_display_mode *target_mode;
+
+	/* Atomic variable to terminate any executing deferred work */
+	atomic_t abort_wait_loop;
+
+	/* To indicate the scheduled work completion */
+	bool work_completed;
+};
+
+struct dsi_drrs {
+	struct intel_mipi_drrs_work *mipi_drrs_work;
+	struct dsi_mnp mnp[DRRS_MAX_RR];
+	int min_vrefresh;
+	struct drrs_dsi_platform_ops *ops;
+};
+
+extern inline struct drrs_encoder_ops *get_intel_dsi_drrs_ops(void);
+#endif /* INTEL_DSI_DRRS_H */
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index d20cf37..c58eb02 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -38,11 +38,6 @@
 #define DSI_HFP_PACKET_EXTRA_SIZE	6
 #define DSI_EOTP_PACKET_SIZE		4
 
-struct dsi_mnp {
-	u32 dsi_pll_ctrl;
-	u32 dsi_pll_div;
-};
-
 static const u32 lfsr_converts[] = {
 	426, 469, 234, 373, 442, 221, 110, 311, 411,		/* 62 - 70 */
 	461, 486, 243, 377, 188, 350, 175, 343, 427, 213,	/* 71 - 80 */
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 05/18] drm/i915: Adjusting the pclk for dual link and burst mode
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (3 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 04/18] drm/i915: Implementation of Generic DSI DRRS Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 06/18] drm/i915: VLV dsi drrs support Ramalingam C
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

dsi_clk is calculated for the clock of passed drm_display_mode
and pclk is adjusted considering dual link and the burst mode.

This change is required to make the drrs to co-exist with dual link
and Burst mode.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_dsi_pll.c |   77 ++++++++++++++++++++++++++++++----
 1 file changed, 68 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index c58eb02..ce5949f 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -128,13 +128,11 @@ static u32 dsi_rr_formula(const struct drm_display_mode *mode,
 
 #else
 
-/* Get DSI clock from pixel clock */
-static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
+static u32 intel_get_bits_per_pixel(struct intel_dsi *intel_dsi)
 {
-	u32 dsi_clk_khz;
 	u32 bpp;
 
-	switch (pixel_format) {
+	switch (intel_dsi->pixel_format) {
 	default:
 	case VID_MODE_FORMAT_RGB888:
 	case VID_MODE_FORMAT_RGB666_LOOSE:
@@ -147,10 +145,70 @@ static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
 		bpp = 16;
 		break;
 	}
+	return bpp;
+}
+
+void adjust_pclk_for_dual_link(struct intel_dsi *intel_dsi,
+				struct drm_display_mode *mode, u32 *pclk)
+{
+	/* In dual link mode each port needs half of pixel clock */
+	*pclk = *pclk / 2;
+
+	/*
+	 * If pixel_overlap needed by panel, we need to	increase the pixel
+	 * clock for extra pixels.
+	 */
+	if (intel_dsi->dual_link & DSI_DUAL_LINK_FRONT_BACK)
+		*pclk += DIV_ROUND_UP(mode->vtotal * intel_dsi->pixel_overlap *
+							mode->vrefresh, 1000);
+}
+
+void adjust_pclk_for_burst_mode(u32 *pclk, u16 burst_mode_ratio)
+{
+	*pclk = DIV_ROUND_UP(*pclk * burst_mode_ratio, 100);
+}
+
+
+/* To recalculate the pclk considering dual link and Burst mode */
+static u32 intel_drrs_calc_pclk(struct intel_dsi *intel_dsi,
+					struct drm_display_mode *mode)
+{
+	u32 pclk;
+	int pkt_pixel_size;		/* in bits */
 
-	/* DSI data rate = pixel clock * bits per pixel / lane count
-	   pixel clock is converted from KHz to Hz */
-	dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, lane_count);
+	pclk = mode->clock;
+
+	pkt_pixel_size = intel_get_bits_per_pixel(intel_dsi);
+
+	/* In dual link mode each port needs half of pixel clock */
+	if (intel_dsi->dual_link)
+		adjust_pclk_for_dual_link(intel_dsi, mode, &pclk);
+
+	/* Retaining the same Burst mode ratio for DRRS. Need to be tested */
+	if (intel_dsi->burst_mode_ratio > 100)
+		adjust_pclk_for_burst_mode(&pclk, intel_dsi->burst_mode_ratio);
+
+	DRM_DEBUG_KMS("mode->clock : %d, pclk : %d\n", mode->clock, pclk);
+	return pclk;
+}
+
+/* Get DSI clock from pixel clock */
+static u32 dsi_clk_from_pclk(struct intel_dsi *intel_dsi,
+					struct drm_display_mode *mode)
+{
+	u32 dsi_clk_khz;
+	u32 bpp;
+	u32 pclk;
+
+	bpp = intel_get_bits_per_pixel(intel_dsi);
+
+	pclk = intel_drrs_calc_pclk(intel_dsi, mode);
+
+	/*
+	 * DSI data rate = pixel clock * bits per pixel / lane count
+	 * pixel clock is converted from KHz to Hz
+	 */
+	dsi_clk_khz = DIV_ROUND_CLOSEST(pclk * bpp, intel_dsi->lane_count);
 
 	return dsi_clk_khz;
 }
@@ -205,12 +263,13 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	struct intel_connector *intel_connector = intel_dsi->attached_connector;
 	int ret;
 	struct dsi_mnp dsi_mnp;
 	u32 dsi_clk;
 
-	dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
-				    intel_dsi->lane_count);
+	dsi_clk = dsi_clk_from_pclk(intel_dsi,
+				    intel_connector->panel.fixed_mode);
 
 	ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
 	if (ret) {
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 06/18] drm/i915: VLV dsi drrs support
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (4 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 05/18] drm/i915: Adjusting the pclk for dual link and burst mode Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 07/18] drm/i915: Generic eDP DRRS implementation Ramalingam C
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

VLV related dsi drrs functions are implemented and registered
with generic dsi drrs.

This will provide the service to generic dsi drrs stack to calculate
the pll divider values and program the pll registers for DRRS
functionality.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h       |    4 +
 drivers/gpu/drm/i915/intel_dsi_drrs.c |   27 ++++
 drivers/gpu/drm/i915/intel_dsi_drrs.h |    5 +
 drivers/gpu/drm/i915/intel_dsi_pll.c  |  225 ++++++++++++++++++++++++++++++---
 4 files changed, 243 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 0b979ad..9f1332b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2964,6 +2964,10 @@ enum skl_disp_power_wells {
 #define  VLV_EDP_PSR_IN_TRANS		(1<<7)
 #define VLV_PSRSTAT(pipe) _PIPE(pipe, _PSRSTATA, _PSRSTATB)
 
+#define VERTICAL_ACTIVE_DISPLAY_MASK		(0xfff)
+#define VERTICAL_TOTAL_DISPLAY_OFFSET		16
+#define VERTICAL_TOTAL_DISPLAY_MASK		(0xfff<<16)
+
 /* HSW+ eDP PSR registers */
 #define EDP_PSR_BASE(dev)                       (IS_HASWELL(dev) ? 0x64800 : 0x6f800)
 #define EDP_PSR_CTL(dev)			(EDP_PSR_BASE(dev) + 0)
diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
index 6ab0e9e..eb0758a 100644
--- a/drivers/gpu/drm/i915/intel_dsi_drrs.c
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
@@ -20,6 +20,23 @@
 #include "intel_drv.h"
 #include "intel_dsi.h"
 
+/*
+ * VLV and CHV platform code
+ */
+struct drrs_dsi_platform_ops vlv_dsi_drrs_ops = {
+	.configure_dsi_pll		= vlv_drrs_configure_dsi_pll,
+	.mnp_calculate_for_mode		= vlv_dsi_mnp_calculate_for_mode,
+};
+
+inline struct drrs_dsi_platform_ops *get_vlv_dsi_drrs_ops(void)
+{
+	return &vlv_dsi_drrs_ops;
+}
+
+/*
+ * Generic DSI DRRS code
+ */
+
 /* Work function for DSI deferred work */
 static void intel_mipi_drrs_work_fn(struct work_struct *__work)
 {
@@ -243,6 +260,16 @@ int intel_dsi_drrs_init(struct i915_drrs *drrs,
 
 	panel->target_mode = NULL;
 
+	if (IS_VALLEYVIEW(intel_encoder->base.dev)) {
+
+		/* VLV and CHV */
+		dsi_drrs->ops = get_vlv_dsi_drrs_ops();
+	} else {
+		DRM_ERROR("DRRS: Unsupported platform\n");
+		ret = -EINVAL;
+		goto out_err_2;
+	}
+
 	if (!dsi_drrs->ops || !dsi_drrs->ops->mnp_calculate_for_mode ||
 					!dsi_drrs->ops->configure_dsi_pll) {
 		DRM_ERROR("DSI platform ops not initialized\n");
diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.h b/drivers/gpu/drm/i915/intel_dsi_drrs.h
index 27736a0..02f76f0 100644
--- a/drivers/gpu/drm/i915/intel_dsi_drrs.h
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.h
@@ -58,4 +58,9 @@ struct dsi_drrs {
 };
 
 extern inline struct drrs_encoder_ops *get_intel_dsi_drrs_ops(void);
+int vlv_dsi_mnp_calculate_for_mode(struct intel_encoder *encoder,
+				struct dsi_mnp *dsi_mnp,
+				struct drm_display_mode *mode);
+int vlv_drrs_configure_dsi_pll(struct intel_encoder *encoder,
+						struct dsi_mnp *dsi_mnp);
 #endif /* INTEL_DSI_DRRS_H */
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
index ce5949f..46346b3 100644
--- a/drivers/gpu/drm/i915/intel_dsi_pll.c
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -29,6 +29,7 @@
 #include "intel_drv.h"
 #include "i915_drv.h"
 #include "intel_dsi.h"
+#include "intel_drrs.h"
 
 #define DSI_HSS_PACKET_SIZE		4
 #define DSI_HSE_PACKET_SIZE		4
@@ -38,6 +39,8 @@
 #define DSI_HFP_PACKET_EXTRA_SIZE	6
 #define DSI_EOTP_PACKET_SIZE		4
 
+#define DSI_DRRS_PLL_CONFIG_TIMEOUT_MS	100
+
 static const u32 lfsr_converts[] = {
 	426, 469, 234, 373, 442, 221, 110, 311, 411,		/* 62 - 70 */
 	461, 486, 243, 377, 188, 350, 175, 343, 427, 213,	/* 71 - 80 */
@@ -256,39 +259,225 @@ static int dsi_calc_mnp(int target_dsi_clk, struct dsi_mnp *dsi_mnp)
 }
 
 /*
+ * vlv_dsi_pll_reg_configure:
+ *	Function to configure the CCK registers for PLL control and dividers
+ *
+ * pll		: Pll that is getting configure
+ * dsi_mnp	: Struct with divider values
+ * pll_enable	: Flag to indicate whether it is a fresh pll enable call or
+ *		  call on DRRS purpose
+ */
+static void vlv_dsi_pll_reg_configure(struct intel_encoder *encoder,
+				struct dsi_mnp *dsi_mnp, bool pll_enable)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+
+	if (!intel_crtc)
+		return;
+
+	if (pll_enable) {
+		vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
+
+		if (intel_dsi->ports & (1 << PORT_A))
+			dsi_mnp->dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;
+
+		if (intel_dsi->ports & (1 << PORT_C))
+			dsi_mnp->dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL;
+
+	} else {
+
+		/*
+		 * Updating the M1, N1, P1 div values alone on the
+		 * CCK registers. these new values are abstracted from
+		 * the dsi_mnp struction
+		 */
+		dsi_mnp->dsi_pll_ctrl =
+			(dsi_mnp->dsi_pll_ctrl & DSI_PLL_P1_POST_DIV_MASK) |
+			(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) &
+			~DSI_PLL_P1_POST_DIV_MASK);
+		dsi_mnp->dsi_pll_div = (dsi_mnp->dsi_pll_div &
+			(DSI_PLL_M1_DIV_MASK | DSI_PLL_N1_DIV_MASK)) |
+			(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER)
+			& ~(DSI_PLL_M1_DIV_MASK | DSI_PLL_N1_DIV_MASK));
+	}
+
+	DRM_DEBUG("dsi_pll: div %08x, ctrl %08x\n",
+				dsi_mnp->dsi_pll_div, dsi_mnp->dsi_pll_ctrl);
+
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp->dsi_pll_div);
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp->dsi_pll_ctrl);
+}
+
+/*
+ * vlv_drrs_configure_dsi_pll:
+ *	Function to configure the PLL dividers and bring the new values
+ * into effect by power cycling the VCO. This power cycle is supposed
+ * to be completed within the vblank period. This is software implementation
+ * and depends on the CCK register access. Needs to be tested thoroughly.
+ *
+ * encoder	: target encoder
+ * dsi_mnp	: struct with pll divider values
+ */
+int vlv_drrs_configure_dsi_pll(struct intel_encoder *encoder,
+						struct dsi_mnp *dsi_mnp)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+	enum pipe pipe;
+	u32 dsl_offset, dsl1, dsl2;
+	u32 vactive, vtotal, vblank, vblank_30_percent, vblank_70_percent;
+	unsigned long timeout;
+
+	if (!intel_crtc)
+		return -EPERM;
+
+	pipe = intel_crtc->pipe;
+	dsl_offset = PIPEDSL(pipe);
+
+	mutex_lock(&dev_priv->sb_lock);
+	vlv_dsi_pll_reg_configure(encoder, dsi_mnp, false);
+	mutex_unlock(&dev_priv->sb_lock);
+
+	DRM_DEBUG("dsi_mnp:: ctrl: 0x%X, div: 0x%X\n", dsi_mnp->dsi_pll_ctrl,
+							dsi_mnp->dsi_pll_div);
+
+	dsi_mnp->dsi_pll_ctrl &= (~DSI_PLL_VCO_EN);
+
+	vtotal = I915_READ(VTOTAL(pipe));
+	vactive = (vtotal & VERTICAL_ACTIVE_DISPLAY_MASK);
+	vtotal = (vtotal & VERTICAL_TOTAL_DISPLAY_MASK) >>
+					VERTICAL_TOTAL_DISPLAY_OFFSET;
+	vblank = vtotal - vactive;
+	vblank_30_percent = vactive + DIV_ROUND_UP((vblank * 3), 10);
+	vblank_70_percent = vactive + DIV_ROUND_UP((vblank * 7), 10);
+
+	timeout = jiffies + msecs_to_jiffies(DSI_DRRS_PLL_CONFIG_TIMEOUT_MS);
+
+tap_vblank_start:
+	do {
+		if (atomic_read(&work->abort_wait_loop) == 1) {
+			DRM_DEBUG_KMS("Aborting the pll update\n");
+			return -EPERM;
+		}
+
+		if (time_after(jiffies, timeout)) {
+			DRM_DEBUG("Timeout at waiting for Vblank\n");
+			return -ETIMEDOUT;
+		}
+
+		dsl1 = (I915_READ(dsl_offset) & DSL_LINEMASK_GEN3);
+
+	} while (dsl1 <= vactive || dsl1 > vblank_30_percent);
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	dsl2 = I915_READ(dsl_offset) & DSL_LINEMASK_GEN3;
+
+	/*
+	 * Did we cross Vblank due to delay in mutex acquirement?
+	 * Keeping two scanlines in vblank as buffer for ops.
+	 */
+	if (dsl2 < vactive || dsl2 > vblank_70_percent) {
+		mutex_unlock(&dev_priv->sb_lock);
+		goto tap_vblank_start;
+	}
+
+	/* Toggle the VCO_EN to bring in the new dividers values */
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp->dsi_pll_ctrl);
+	dsi_mnp->dsi_pll_ctrl |= DSI_PLL_VCO_EN;
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp->dsi_pll_ctrl);
+
+	dsl2 = I915_READ(dsl_offset) & DSL_LINEMASK_GEN3;
+
+	mutex_unlock(&dev_priv->sb_lock);
+
+	if (wait_for(I915_READ(PIPECONF(pipe)) &
+					PIPECONF_DSI_PLL_LOCKED, 20)) {
+		DRM_ERROR("DSI PLL lock failed\n");
+		return -1;
+	}
+
+	DRM_DEBUG("PLL Changed between DSL: %u, %u\n", dsl1, dsl2);
+	DRM_DEBUG("DSI PLL locked\n");
+	return 0;
+}
+
+/*
+ * vlv_dsi_mnp_calculate_for_mode:
+ *	calculates the dsi_mnp values for a given mode
+ *
+ * encoder	: Target encoder
+ * dsi_mnp	: output struct to store divider values
+ * mode		: Input mode for which mnp is calculated
+ */
+int vlv_dsi_mnp_calculate_for_mode(struct intel_encoder *encoder,
+				struct dsi_mnp *dsi_mnp,
+				struct drm_display_mode *mode)
+{
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	u32 dsi_clk, ret;
+
+	dsi_clk = dsi_clk_from_pclk(intel_dsi, mode);
+
+	DRM_DEBUG("Mode->clk: %u, dsi_clk: %u\n", mode->clock, dsi_clk);
+
+	ret = dsi_calc_mnp(dsi_clk, dsi_mnp);
+	if (ret)
+		DRM_DEBUG("dsi_calc_mnp failed\n");
+	else
+		DRM_DEBUG("dsi_mnp: ctrl : 0x%X, div : 0x%X\n",
+						dsi_mnp->dsi_pll_ctrl,
+							dsi_mnp->dsi_pll_div);
+	return ret;
+}
+
+/*
  * XXX: The muxing and gating is hard coded for now. Need to add support for
  * sharing PLLs with two DSI outputs.
  */
 static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct i915_drrs *drrs;
 	struct intel_connector *intel_connector = intel_dsi->attached_connector;
-	int ret;
-	struct dsi_mnp dsi_mnp;
-	u32 dsi_clk;
-
-	dsi_clk = dsi_clk_from_pclk(intel_dsi,
-				    intel_connector->panel.fixed_mode);
+	int ret, index;
 
-	ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
-	if (ret) {
-		DRM_DEBUG_KMS("dsi_calc_mnp failed\n");
+	ret = vlv_dsi_mnp_calculate_for_mode(encoder,
+					&dsi_drrs->mnp[DRRS_HIGH_RR],
+					intel_connector->panel.fixed_mode);
+	if (ret < 0) {
+		DRM_ERROR("dsi_mnp calculations failed\n");
 		return;
 	}
 
-	if (intel_dsi->ports & (1 << PORT_A))
-		dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;
+	index = get_drrs_struct_index_for_crtc(dev_priv, intel_crtc);
+	if (index < 0)
+		return;
 
-	if (intel_dsi->ports & (1 << PORT_C))
-		dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL;
+	drrs = dev_priv->drrs[index];
+	if (!drrs || !drrs->has_drrs)
+		return;
 
-	DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n",
-		      dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl);
+	if (drrs && drrs->has_drrs &&
+				intel_connector->panel.downclock_mode) {
+		ret = vlv_dsi_mnp_calculate_for_mode(encoder,
+					&dsi_drrs->mnp[DRRS_LOW_RR],
+					intel_connector->panel.downclock_mode);
+		if (ret < 0) {
+			DRM_ERROR("dsi_mnp calculations failed\n");
+			return;
+		}
+	}
 
-	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
-	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div);
-	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl);
+	vlv_dsi_pll_reg_configure(encoder, &dsi_drrs->mnp[DRRS_HIGH_RR], true);
 }
 
 void vlv_enable_dsi_pll(struct intel_encoder *encoder)
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 07/18] drm/i915: Generic eDP DRRS implementation
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (5 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 06/18] drm/i915: VLV dsi drrs support Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 08/18] drm/i915: VLV eDP DRRS methods Ramalingam C
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

This patch Implements the generic eDP DRRS functions and registers
them with Generic DRRS state machine.

Platform specific eDP DRRS functions will be implemented and
registered with this generic eDP DRRS implementation. Hence
extending the eDP DRRS to new platform is made simple.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/Makefile         |    1 +
 drivers/gpu/drm/i915/intel_dp.c       |    6 +++
 drivers/gpu/drm/i915/intel_drrs.c     |    2 +
 drivers/gpu/drm/i915/intel_drv.h      |    3 ++
 drivers/gpu/drm/i915/intel_edp_drrs.c |   95 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_edp_drrs.h |   29 ++++++++++
 6 files changed, 136 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.c
 create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 4f77fb2..9a3c43f 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -56,6 +56,7 @@ i915-y += intel_audio.o \
 	  intel_psr.o \
 	  intel_drrs.o \
 	  intel_dsi_drrs.o \
+	  intel_edp_drrs.o \
 	  intel_sideband.o \
 	  intel_sprite.o
 i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 738e98e..9ded4d1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1483,6 +1483,12 @@ found:
 			       pipe_config->port_clock,
 			       &pipe_config->dp_m_n);
 
+	if (intel_connector->panel.downclock_mode)
+		intel_link_compute_m_n(bpp, lane_count,
+			       intel_connector->panel.downclock_mode->clock,
+			       pipe_config->port_clock,
+			       &pipe_config->dp_m2_n2);
+
 	if (IS_SKYLAKE(dev) && is_edp(intel_dp))
 		skl_edp_set_pll_config(pipe_config, common_rates[clock]);
 	else if (IS_BROXTON(dev))
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index 2a776d2..e5d8bcd 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -388,6 +388,8 @@ int intel_drrs_init(struct drm_device *dev,
 
 	if (intel_encoder->type == INTEL_OUTPUT_DSI) {
 		drrs->encoder_ops = get_intel_dsi_drrs_ops();
+	} else if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+		drrs->encoder_ops = get_intel_edp_drrs_ops();
 	} else {
 		DRM_ERROR("DRRS: Unsupported Encoder\n");
 		ret = -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 726c31d..d5354f3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -38,6 +38,7 @@
 #include <drm/drm_atomic.h>
 
 #include "intel_drrs.h"
+#include "intel_edp_drrs.h"
 
 /**
  * _wait_for - magic (register) wait macro
@@ -758,6 +759,8 @@ struct intel_dp {
 	unsigned long compliance_test_type;
 	unsigned long compliance_test_data;
 	bool compliance_test_active;
+
+	struct edp_drrs_platform_ops *drrs_ops;
 };
 
 struct intel_digital_port {
diff --git a/drivers/gpu/drm/i915/intel_edp_drrs.c b/drivers/gpu/drm/i915/intel_edp_drrs.c
new file mode 100644
index 0000000..606271b
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_edp_drrs.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Authors:
+ * Ramalingam C <ramalingam.c@intel.com>
+ * Durgadoss R <durgadoss.r@intel.com>
+ */
+
+#include <linux/delay.h>
+#include <drm/i915_drm.h>
+
+#include "i915_drv.h"
+
+void intel_edp_set_drrs_state(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+	intel_dp->drrs_ops->set_drrs_state(intel_encoder,
+					drrs->drrs_state.target_rr_type);
+}
+
+int intel_edp_drrs_init(struct i915_drrs *drrs,
+					struct drm_display_mode *fixed_mode)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	struct drm_display_mode *downclock_mode;
+	int ret = -EINVAL;
+
+	if (!intel_dp->drrs_ops ||
+			!intel_dp->drrs_ops->set_drrs_state) {
+		DRM_ERROR("Required platform ops are NULL\n");
+		return ret;
+	}
+
+	if (fixed_mode->vrefresh == 0)
+		fixed_mode->vrefresh = drm_mode_vrefresh(fixed_mode);
+
+	downclock_mode = intel_find_panel_downclock(intel_encoder->base.dev,
+					fixed_mode, &drrs->connector->base);
+	if (!downclock_mode) {
+		DRM_DEBUG("No Downclock mode is found\n");
+		return ret;
+	}
+
+	if (intel_dp->drrs_ops->init) {
+		ret = intel_dp->drrs_ops->init(intel_encoder);
+		if (ret < 0)
+			return ret;
+	}
+
+	DRM_DEBUG("eDP DRRS modes:\n");
+	drm_mode_debug_printmodeline(fixed_mode);
+	drm_mode_debug_printmodeline(downclock_mode);
+
+	/* We are good to go .. */
+	intel_panel_init(&drrs->connector->panel, fixed_mode, downclock_mode);
+	drrs->connector->panel.target_mode = NULL;
+
+	drrs->drrs_state.type = SEAMLESS_DRRS_SUPPORT;
+	return ret;
+}
+
+void intel_edp_drrs_exit(struct i915_drrs *drrs)
+{
+	struct intel_encoder *intel_encoder = drrs->connector->encoder;
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+	if (intel_dp->drrs_ops->exit)
+		intel_dp->drrs_ops->exit(intel_encoder);
+
+	drrs->drrs_state.type = DRRS_NOT_SUPPORTED;
+}
+
+struct drrs_encoder_ops edp_drrs_ops = {
+	.init = intel_edp_drrs_init,
+	.exit = intel_edp_drrs_exit,
+	.set_drrs_state = intel_edp_set_drrs_state,
+};
+
+/* Called by intel_drrs_init() to get ->ops for edp panel */
+struct drrs_encoder_ops *get_intel_edp_drrs_ops(void)
+{
+	return &edp_drrs_ops;
+}
diff --git a/drivers/gpu/drm/i915/intel_edp_drrs.h b/drivers/gpu/drm/i915/intel_edp_drrs.h
new file mode 100644
index 0000000..5a23f004
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_edp_drrs.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef INTEL_EDP_DRRS_H
+#define INTEL_EDP_DRRS_H
+
+struct intel_encoder;
+struct edp_drrs_platform_ops {
+	int (*init)(struct intel_encoder *encoder);
+	void (*exit)(struct intel_encoder *encoder);
+	int (*set_drrs_state)(struct intel_encoder *encoder,
+				enum drrs_refresh_rate_type target_rr_type);
+};
+
+extern inline struct drrs_encoder_ops *get_intel_edp_drrs_ops(void);
+#endif /* INTEL_EDP_DRRS_H */
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 08/18] drm/i915: VLV eDP DRRS methods
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (6 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 07/18] drm/i915: Generic eDP DRRS implementation Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 09/18] drm/i915: Cloned mode check Ramalingam C
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

VLV related ePD drrs functions are implemented and registered
with generic eDP drrs module.

This will provide the platform specific services to generic ePD drrs
stack, like program the pll registers for DRRS functionality.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_edp_drrs.c |   72 +++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_edp_drrs.c b/drivers/gpu/drm/i915/intel_edp_drrs.c
index 606271b..8968e4c 100644
--- a/drivers/gpu/drm/i915/intel_edp_drrs.c
+++ b/drivers/gpu/drm/i915/intel_edp_drrs.c
@@ -20,6 +20,71 @@
 
 #include "i915_drv.h"
 
+/*
+ * VLV eDP DRRS Support
+ */
+
+static int vlv_edp_drrs_init(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+
+	if (dev_priv->psr.enabled) {
+		DRM_ERROR("eDP DRRS is disabled as PSR is enabled already\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void vlv_edp_drrs_exit(struct intel_encoder *encoder)
+{
+}
+
+static int vlv_edp_set_drrs_state(struct intel_encoder *encoder,
+				enum drrs_refresh_rate_type target_rr_type)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	u32 reg, val;
+
+	if (!crtc)
+		return -EINVAL;
+
+	reg = PIPECONF(crtc->config->cpu_transcoder);
+	val = I915_READ(reg);
+
+	switch (target_rr_type) {
+	case DRRS_HIGH_RR:
+		if (IS_VALLEYVIEW(dev))
+			val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+		break;
+	case DRRS_LOW_RR:
+		if (IS_VALLEYVIEW(dev))
+			val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+		break;
+	default:
+		DRM_ERROR("invalid refresh rate type\n");
+		return -EINVAL;
+	}
+
+	I915_WRITE(reg, val);
+	return 0;
+}
+
+struct edp_drrs_platform_ops vlv_edp_drrs_ops = {
+	.init = vlv_edp_drrs_init,
+	.exit = vlv_edp_drrs_exit,
+	.set_drrs_state = vlv_edp_set_drrs_state,
+};
+
+struct edp_drrs_platform_ops *get_vlv_edp_drrs_ops(void)
+{
+	return &vlv_edp_drrs_ops;
+}
+
+/*
+ * Generic eDP DRRS implementation
+ */
 void intel_edp_set_drrs_state(struct i915_drrs *drrs)
 {
 	struct intel_encoder *intel_encoder = drrs->connector->encoder;
@@ -37,6 +102,13 @@ int intel_edp_drrs_init(struct i915_drrs *drrs,
 	struct drm_display_mode *downclock_mode;
 	int ret = -EINVAL;
 
+	if (IS_VALLEYVIEW(intel_encoder->base.dev))
+
+		/* VLV and CHV */
+		intel_dp->drrs_ops = get_vlv_edp_drrs_ops();
+	else
+		intel_dp->drrs_ops = NULL;
+
 	if (!intel_dp->drrs_ops ||
 			!intel_dp->drrs_ops->set_drrs_state) {
 		DRM_ERROR("Required platform ops are NULL\n");
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 09/18] drm/i915: Cloned mode check
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (7 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 08/18] drm/i915: VLV eDP DRRS methods Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 17:08   ` Daniel Vetter
  2015-06-26 13:51 ` [RFC PATCH 10/18] drm/i915: Initializing DRRS for all connectors Ramalingam C
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

If crtc is in clone mode, DRRS will be disabled. Because if the both
the displays are not sharing the same vrefresh, then userspace
activities based on vsync will go for toss.

Clone mode will be rechecked on every restarting Idleness DRRS events.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_drrs.c |   36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index e5d8bcd..42b420d 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -16,6 +16,7 @@
 
 #include <drm/i915_drm.h>
 #include <linux/delay.h>
+#include <linux/list.h>
 
 #include "i915_drv.h"
 #include "intel_drv.h"
@@ -85,6 +86,31 @@ int get_free_drrs_struct_index(struct drm_i915_private *dev_priv)
 	return -EBUSY;
 }
 
+/*
+ * TODO: This is identifying the multiple active crtcs at a time.
+ * Here we assume that this is clone state and disable DRRS.
+ * But need to implement a proper method to find the real cloned mode
+ * state. DRRS need not be disabled incase of multiple crtcs with
+ * different content.
+ */
+
+bool is_cloned_mode_active(struct drm_device *dev)
+{
+	struct drm_crtc *crtc = NULL, *tmp_crtc;
+
+	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc && intel_crtc_active(tmp_crtc)) {
+			DRM_DEBUG_KMS(
+			"more than one crtc active. Declared as clonec mode\n");
+			return true;
+		}
+
+		if (intel_crtc_active(tmp_crtc))
+			crtc = tmp_crtc;
+	}
+	return false;
+}
+
 void intel_set_drrs_state(struct i915_drrs *drrs)
 {
 	struct drrs_info *drrs_state;
@@ -158,7 +184,10 @@ static void intel_idleness_drrs_work_fn(struct work_struct *__work)
 
 	panel = &drrs->connector->panel;
 
-	/* TODO: If DRRS is not supported on clone mode act here */
+	/* Double check if the dual-display mode is active. */
+	if (drrs->is_clone)
+		return;
+
 	mutex_lock(&drrs->drrs_mutex);
 	if (panel->target_mode != NULL)
 		DRM_ERROR("FIXME: We shouldn't be here\n");
@@ -192,6 +221,11 @@ static void intel_enable_idleness_drrs(struct i915_drrs *drrs)
 
 	mutex_lock(&drrs->drrs_mutex);
 
+	drrs->is_clone = is_cloned_mode_active(drrs->connector->base.dev);
+
+	if (drrs->is_clone)
+		return;
+
 	/* Capturing the deferred request for disable_drrs */
 	if (drrs->drrs_state.type == SEAMLESS_DRRS_SUPPORT_SW &&
 				drrs->encoder_ops->is_drrs_hr_state_pending) {
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 10/18] drm/i915: Initializing DRRS for all connectors
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (8 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 09/18] drm/i915: Cloned mode check Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 17:12   ` Daniel Vetter
  2015-06-26 13:51 ` [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions Ramalingam C
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

For all the connectors drrs init is invoked. drrs_init will
initialize the drrs for those connectors that support DRRS.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3f48917..0e8467c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15021,6 +15021,7 @@ void intel_modeset_init(struct drm_device *dev)
 	int sprite, ret;
 	enum pipe pipe;
 	struct intel_crtc *crtc;
+	struct intel_connector *connector;
 
 	drm_mode_config_init(dev);
 
@@ -15090,6 +15091,10 @@ void intel_modeset_init(struct drm_device *dev)
 	i915_disable_vga(dev);
 	intel_setup_outputs(dev);
 
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+								base.head)
+		intel_drrs_init(dev, connector, connector->panel.fixed_mode);
+
 	/* Just in case the BIOS is doing something questionable. */
 	intel_fbc_disable(dev);
 
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (9 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 10/18] drm/i915: Initializing DRRS for all connectors Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 17:11   ` Daniel Vetter
  2015-06-26 13:51 ` [RFC PATCH 12/18] drm/i915: Redesigning dp_set_m_n to receive divider values Ramalingam C
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

During the DRRS state transitions we are modifying the clock and
hence the vrefresh rate.

So we need to update the drm_crtc->mode and the adjusted
mode in intel_crtc. So that watermark calculations will be as per the
new modified clock.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_drrs.c     |   14 ++++++++++++++
 drivers/gpu/drm/i915/intel_dsi_drrs.c |   14 +++++++++++++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index 42b420d..2901832 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -169,6 +169,20 @@ void intel_set_drrs_state(struct i915_drrs *drrs)
 		 * If it is non-DSI encoders.
 		 * As only DSI has SEAMLESS_DRRS_SUPPORT_SW.
 		 */
+		/*
+		 * TODO: Protect the access to the crtc mode with corresponding
+		 * mutex in case of Idleness DRRS. As media playback update
+		 * will happen under crtc modeset lock protection
+		 */
+		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
+		intel_crtc->base.mode.clock = target_mode->clock;
+		intel_crtc->base.mode.vrefresh = target_mode->vrefresh;
+		intel_crtc->config->base.adjusted_mode.clock =
+							target_mode->clock;
+		intel_crtc->config->base.adjusted_mode.vrefresh =
+							target_mode->vrefresh;
+		drm_modeset_unlock(&intel_crtc->base.mutex);
+
 		drrs_state->current_rr_type = drrs_state->target_rr_type;
 		DRM_INFO("Refresh Rate set to : %dHz\n", refresh_rate);
 	}
diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
index eb0758a..d4bb70a 100644
--- a/drivers/gpu/drm/i915/intel_dsi_drrs.c
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
@@ -46,6 +46,7 @@ static void intel_mipi_drrs_work_fn(struct work_struct *__work)
 	struct i915_drrs *drrs = work->drrs;
 	struct intel_encoder *intel_encoder = drrs->connector->encoder;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
 	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
 	struct dsi_mnp *dsi_mnp;
 	struct drm_display_mode *prev_mode = NULL;
@@ -69,11 +70,22 @@ retry:
 		/* PLL Programming is successful */
 		mutex_lock(&drrs->drrs_mutex);
 		drrs->drrs_state.current_rr_type = work->target_rr_type;
+
+		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
+		intel_crtc->base.mode.clock = work->target_mode->clock;
+		intel_crtc->base.mode.vrefresh = work->target_mode->vrefresh;
+		intel_crtc->config->base.adjusted_mode.clock =
+						work->target_mode->clock;
+		intel_crtc->config->base.adjusted_mode.vrefresh =
+						work->target_mode->vrefresh;
+		drm_modeset_unlock(&intel_crtc->base.mutex);
+
 		mutex_unlock(&drrs->drrs_mutex);
+
 		DRM_INFO("Refresh Rate set to : %dHz\n",
 						work->target_mode->vrefresh);
 
-		/* TODO: Update crtc mode and drain ladency with watermark */
+		/* TODO: Update drain ladency with watermark */
 
 	} else if (ret == -ETIMEDOUT && retry_cnt) {
 
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 12/18] drm/i915: Redesigning dp_set_m_n to receive divider values
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (10 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 13/18] drm/i915: MEDIA_RR support in general DRRS state machine Ramalingam C
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

This will enable the called to decide the combination of divider
values that needs to be programmed.

First divider value will go into primary divider and the second divider
value will be taken for drrs divider register, if that is supported
on platform.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   38 ++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_drv.h     |   23 ++------------------
 2 files changed, 20 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0e8467c..b36fde6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4819,7 +4819,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		intel_prepare_shared_dpll(intel_crtc);
 
 	if (intel_crtc->config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+		intel_dp_set_m_n(intel_crtc,
+				&intel_crtc->config->dp_m_n,
+				&intel_crtc->config->dp_m2_n2);
 
 	intel_set_pipe_timings(intel_crtc);
 
@@ -4896,7 +4898,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 		intel_enable_shared_dpll(intel_crtc);
 
 	if (intel_crtc->config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+		intel_dp_set_m_n(intel_crtc,
+				&intel_crtc->config->dp_m_n,
+				&intel_crtc->config->dp_m2_n2);
 
 	intel_set_pipe_timings(intel_crtc);
 
@@ -6036,7 +6040,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 	}
 
 	if (intel_crtc->config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+		intel_dp_set_m_n(intel_crtc,
+				&intel_crtc->config->dp_m_n,
+				&intel_crtc->config->dp_m2_n2);
 
 	intel_set_pipe_timings(intel_crtc);
 
@@ -6105,7 +6111,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	i9xx_set_pll_dividers(intel_crtc);
 
 	if (intel_crtc->config->has_dp_encoder)
-		intel_dp_set_m_n(intel_crtc, M1_N1);
+		intel_dp_set_m_n(intel_crtc,
+				&intel_crtc->config->dp_m_n,
+				&intel_crtc->config->dp_m2_n2);
 
 	intel_set_pipe_timings(intel_crtc);
 
@@ -7208,29 +7216,19 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
 	}
 }
 
-void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n)
+void intel_dp_set_m_n(struct intel_crtc *crtc,
+				struct intel_link_m_n *m1_n1,
+					struct intel_link_m_n *m2_n2)
 {
-	struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
-
-	if (m_n == M1_N1) {
-		dp_m_n = &crtc->config->dp_m_n;
-		dp_m2_n2 = &crtc->config->dp_m2_n2;
-	} else if (m_n == M2_N2) {
-
-		/*
-		 * M2_N2 registers are not supported. Hence m2_n2 divider value
-		 * needs to be programmed into M1_N1.
-		 */
-		dp_m_n = &crtc->config->dp_m2_n2;
-	} else {
+	if (!m1_n1) {
 		DRM_ERROR("Unsupported divider value\n");
 		return;
 	}
 
 	if (crtc->config->has_pch_encoder)
-		intel_pch_transcoder_set_m_n(crtc, &crtc->config->dp_m_n);
+		intel_pch_transcoder_set_m_n(crtc, m1_n1);
 	else
-		intel_cpu_transcoder_set_m_n(crtc, dp_m_n, dp_m2_n2);
+		intel_cpu_transcoder_set_m_n(crtc, m1_n1, m2_n2);
 }
 
 static void vlv_update_pll(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d5354f3..b364a68 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -674,26 +674,6 @@ struct intel_hdmi {
 struct intel_dp_mst_encoder;
 #define DP_MAX_DOWNSTREAM_PORTS		0x10
 
-/*
- * enum link_m_n_set:
- *	When platform provides two set of M_N registers for dp, we can
- *	program them and switch between them incase of DRRS.
- *	But When only one such register is provided, we have to program the
- *	required divider value on that registers itself based on the DRRS state.
- *
- * M1_N1	: Program dp_m_n on M1_N1 registers
- *			  dp_m2_n2 on M2_N2 registers (If supported)
- *
- * M2_N2	: Program dp_m2_n2 on M1_N1 registers
- *			  M2_N2 registers are not supported
- */
-
-enum link_m_n_set {
-	/* Sets the m1_n1 and m2_n2 */
-	M1_N1 = 0,
-	M2_N2
-};
-
 struct intel_dp {
 	uint32_t output_reg;
 	uint32_t aux_ch_ctl_reg;
@@ -1138,7 +1118,8 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv);
 void skl_uninit_cdclk(struct drm_i915_private *dev_priv);
 void intel_dp_get_m_n(struct intel_crtc *crtc,
 		      struct intel_crtc_state *pipe_config);
-void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
+void intel_dp_set_m_n(struct intel_crtc *crtc, struct intel_link_m_n *m1_n1,
+						struct intel_link_m_n *m2_n2);
 int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
 void
 ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 13/18] drm/i915: MEDIA_RR support in general DRRS state machine
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (11 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 12/18] drm/i915: Redesigning dp_set_m_n to receive divider values Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 14/18] drm/i915: MEDIA_RR support in eDP DRRS module Ramalingam C
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

Based on the minimum requirement of the vrefresh to support a
content's playback, we can place a drrs request from userspace
to kernel. For example 24FPS video content can be played at
48 vrefresh without any quality degradation.

This patch implements required changes in generic DRRS state machine.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h   |    7 ++
 drivers/gpu/drm/i915/intel_drrs.c |  161 +++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_drrs.h |    5 +-
 3 files changed, 166 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 677293d..dbdba44 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -948,10 +948,12 @@ enum drrs_support_type {
  * Different DRRS States:
  * DRRS_HIGH_RR	: Refreshrate of Fixed mode. [Maximum Vrefresh]
  * DRRS_LOW_RR	: Refreshrate of Downclock mode. [Minimum vrefresh]
+ * DRRS_MEDIA_RR: Refreshrate of requested from userspace. [<Max && >= Min]
  */
 enum drrs_refresh_rate_type {
 	DRRS_HIGH_RR,
 	DRRS_LOW_RR,
+	DRRS_MEDIA_RR,
 	DRRS_MAX_RR,
 };
 
@@ -983,6 +985,8 @@ struct drrs_encoder_ops {
 	void (*exit)(struct i915_drrs *);
 	void (*set_drrs_state)(struct i915_drrs *);
 	bool (*is_drrs_hr_state_pending)(struct i915_drrs *);
+	bool (*is_mp_drrs_req)(struct i915_drrs *,
+						struct drm_display_mode *);
 };
 
 struct i915_drrs {
@@ -992,6 +996,9 @@ struct i915_drrs {
 	/* Whether DRRS is supported on this Panel */
 	bool has_drrs;
 
+	/* Flag to resume the Idleness DRRS from Media Playback */
+	bool resume_idleness_detection;
+
 	/* Holds the DRRS state machine states */
 	struct drrs_info drrs_state;
 
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index 2901832..7f66be4 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -111,6 +111,13 @@ bool is_cloned_mode_active(struct drm_device *dev)
 	return false;
 }
 
+static inline bool
+is_media_playback_drrs_in_progress(struct drrs_info *drrs_state)
+{
+	return drrs_state->current_rr_type == DRRS_MEDIA_RR ||
+		drrs_state->target_rr_type == DRRS_MEDIA_RR;
+}
+
 void intel_set_drrs_state(struct i915_drrs *drrs)
 {
 	struct drrs_info *drrs_state;
@@ -157,7 +164,8 @@ void intel_set_drrs_state(struct i915_drrs *drrs)
 		return;
 	}
 
-	if (drrs_state->target_rr_type == drrs_state->current_rr_type) {
+	if (drrs_state->target_rr_type == drrs_state->current_rr_type &&
+			drrs_state->current_rr_type != DRRS_MEDIA_RR) {
 		DRM_INFO("Requested for previously set RR. Ignoring\n");
 		return;
 	}
@@ -170,19 +178,24 @@ void intel_set_drrs_state(struct i915_drrs *drrs)
 		 * As only DSI has SEAMLESS_DRRS_SUPPORT_SW.
 		 */
 		/*
-		 * TODO: Protect the access to the crtc mode with corresponding
+		 * Protect the access to the crtc mode with corresponding
 		 * mutex in case of Idleness DRRS. As media playback update
 		 * will happen under crtc modeset lock protection
 		 */
-		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
+		if (!is_media_playback_drrs_in_progress(drrs_state))
+			drm_modeset_lock(&intel_crtc->base.mutex, NULL);
 		intel_crtc->base.mode.clock = target_mode->clock;
 		intel_crtc->base.mode.vrefresh = target_mode->vrefresh;
 		intel_crtc->config->base.adjusted_mode.clock =
 							target_mode->clock;
 		intel_crtc->config->base.adjusted_mode.vrefresh =
 							target_mode->vrefresh;
-		drm_modeset_unlock(&intel_crtc->base.mutex);
+		if (!is_media_playback_drrs_in_progress(drrs_state))
+			drm_modeset_unlock(&intel_crtc->base.mutex);
 
+		if (drrs_state->current_rr_type == DRRS_MEDIA_RR &&
+				drrs_state->target_rr_type == DRRS_HIGH_RR)
+			drrs->resume_idleness_detection = true;
 		drrs_state->current_rr_type = drrs_state->target_rr_type;
 		DRM_INFO("Refresh Rate set to : %dHz\n", refresh_rate);
 	}
@@ -203,6 +216,11 @@ static void intel_idleness_drrs_work_fn(struct work_struct *__work)
 		return;
 
 	mutex_lock(&drrs->drrs_mutex);
+	if (is_media_playback_drrs_in_progress(&drrs->drrs_state)) {
+		mutex_unlock(&drrs->drrs_mutex);
+		return;
+	}
+
 	if (panel->target_mode != NULL)
 		DRM_ERROR("FIXME: We shouldn't be here\n");
 
@@ -229,7 +247,7 @@ static void intel_cancel_idleness_drrs_work(struct i915_drrs *drrs, bool sync)
 	drrs->connector->panel.target_mode = NULL;
 }
 
-static void intel_enable_idleness_drrs(struct i915_drrs *drrs)
+void intel_enable_idleness_drrs(struct i915_drrs *drrs)
 {
 	bool force_enable_drrs = false;
 
@@ -240,6 +258,11 @@ static void intel_enable_idleness_drrs(struct i915_drrs *drrs)
 	if (drrs->is_clone)
 		return;
 
+	if (is_media_playback_drrs_in_progress(&drrs->drrs_state)) {
+		mutex_unlock(&drrs->drrs_mutex);
+		return;
+	}
+
 	/* Capturing the deferred request for disable_drrs */
 	if (drrs->drrs_state.type == SEAMLESS_DRRS_SUPPORT_SW &&
 				drrs->encoder_ops->is_drrs_hr_state_pending) {
@@ -267,6 +290,12 @@ void intel_disable_idleness_drrs(struct i915_drrs *drrs)
 	struct intel_panel *panel;
 
 	mutex_lock(&drrs->drrs_mutex);
+
+	if (is_media_playback_drrs_in_progress(&drrs->drrs_state)) {
+		mutex_unlock(&drrs->drrs_mutex);
+		return;
+	}
+
 	panel = &drrs->connector->panel;
 
 	/* as part of disable DRRS, reset refresh rate to HIGH_RR */
@@ -301,7 +330,6 @@ void intel_drrs_invalidate(struct drm_device *dev,
 	int pipe;
 	int index;
 
-
 	for (pipe = 0; pipe < 4; pipe++) {
 		if (frontbuffer_bits & (0xf << (16 * pipe))) {
 			index = get_drrs_struct_index_for_pipe(dev_priv, pipe);
@@ -375,6 +403,126 @@ void intel_drrs_flush(struct drm_device *dev,
 	}
 }
 
+/*
+ * Handles the userspace request for MEDIA_RR.
+ */
+int intel_media_playback_drrs_configure(struct intel_crtc *crtc,
+					struct drm_display_mode *mode)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct i915_drrs *drrs;
+	struct drrs_info *drrs_state;
+	struct intel_panel *panel;
+	struct drm_crtc *tmp_crtc = NULL;
+	int refresh_rate = mode->vrefresh;
+	int index, crtc_cnt = 0;
+
+	index = get_drrs_struct_index_for_crtc(dev_priv, crtc);
+	if (index < 0)
+		return -EINVAL;
+
+	drrs = dev_priv->drrs[index];
+	if (!drrs || !drrs->has_drrs) {
+		DRM_ERROR("DRRS is not supported\n");
+		return -EPERM;
+	}
+
+	drrs_state = &drrs->drrs_state;
+	panel = &drrs->connector->panel;
+
+	if (refresh_rate < panel->downclock_mode->vrefresh &&
+			refresh_rate > panel->fixed_mode->vrefresh) {
+		DRM_ERROR("Invalid refresh_rate\n");
+		return -EINVAL;
+	}
+
+	intel_cancel_idleness_drrs_work(drrs, false);
+
+	mutex_lock(&drrs->drrs_mutex);
+
+	if (refresh_rate == panel->fixed_mode->vrefresh) {
+		if (drrs_state->current_rr_type == DRRS_MEDIA_RR) {
+
+			/* DRRS_MEDIA_RR -> DRRS_HIGH_RR */
+			if (panel->target_mode)
+				drm_mode_destroy(dev, panel->target_mode);
+			panel->target_mode = panel->fixed_mode;
+			drrs_state->target_rr_type = DRRS_HIGH_RR;
+		} else {
+
+			/*
+			 * Invalid Media Playback DRRS request.
+			 * Resume the Idleness Detection
+			 */
+			DRM_ERROR("Invalid Entry req for mode DRRS_MEDIA_RR\n");
+			mutex_unlock(&drrs->drrs_mutex);
+			intel_disable_idleness_drrs(drrs);
+			intel_enable_idleness_drrs(drrs);
+			return 0;
+		}
+	} else {
+		drrs->is_clone = false;
+		list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list,
+									head) {
+			if (intel_crtc_active(tmp_crtc)) {
+				if (crtc_cnt) {
+					DRM_DEBUG_KMS(
+						"more than one pipe active\n");
+					drrs->is_clone = true;
+					break;
+				}
+				crtc_cnt++;
+			}
+		}
+
+		if (drrs->is_clone) {
+			if (panel->target_mode &&
+				drrs_state->current_rr_type == DRRS_MEDIA_RR)
+				drm_mode_destroy(dev, panel->target_mode);
+			panel->target_mode = panel->fixed_mode;
+			drrs_state->target_rr_type = DRRS_HIGH_RR;
+			goto set_state;
+		}
+
+		drrs_state->target_rr_type = DRRS_MEDIA_RR;
+
+		if (drrs_state->current_rr_type == DRRS_MEDIA_RR) {
+
+			/* Refresh rate change in Media playback DRRS */
+			if (refresh_rate == panel->target_mode->vrefresh) {
+				DRM_DEBUG("Request for current RR.<%d>\n",
+					panel->target_mode->vrefresh);
+				mutex_unlock(&drrs->drrs_mutex);
+				return 0;
+			}
+			panel->target_mode->vrefresh = refresh_rate;
+		} else {
+
+			/* Entering MEDIA Playback DRRS state */
+			panel->target_mode = drm_mode_duplicate(dev, mode);
+		}
+
+		panel->target_mode->clock = mode->vrefresh * mode->vtotal *
+							mode->htotal / 1000;
+	}
+
+set_state:
+	DRM_DEBUG("cur_rr_type: %d, target_rr_type: %d, target_rr: %d\n",
+						drrs_state->current_rr_type,
+						drrs_state->target_rr_type,
+						panel->target_mode->vrefresh);
+
+	intel_set_drrs_state(drrs);
+	mutex_unlock(&drrs->drrs_mutex);
+
+	if (drrs->resume_idleness_detection) {
+		intel_disable_idleness_drrs(drrs);
+		intel_enable_idleness_drrs(drrs);
+	}
+	return 0;
+}
+
 /* Idleness detection logic is initialized */
 int intel_drrs_idleness_detection_init(struct i915_drrs *drrs)
 {
@@ -480,6 +628,7 @@ int intel_drrs_init(struct drm_device *dev,
 	drrs->has_drrs = true;
 	to_intel_crtc(intel_encoder->base.crtc)->config->has_drrs = true;
 	mutex_init(&drrs->drrs_mutex);
+	drrs->resume_idleness_detection = false;
 	drrs->drrs_state.current_rr_type = DRRS_HIGH_RR;
 	DRM_INFO("SEAMLESS DRRS supported on this panel.\n");
 
diff --git a/drivers/gpu/drm/i915/intel_drrs.h b/drivers/gpu/drm/i915/intel_drrs.h
index a07f023..7f9985c0 100644
--- a/drivers/gpu/drm/i915/intel_drrs.h
+++ b/drivers/gpu/drm/i915/intel_drrs.h
@@ -26,7 +26,10 @@ int get_drrs_struct_index_for_crtc(struct drm_i915_private *dev_priv,
 int get_drrs_struct_index_for_connector(struct drm_i915_private *dev_priv,
 				struct intel_connector *intel_connector);
 int get_free_drrs_struct_index(struct drm_i915_private *dev_priv);
-
+void intel_disable_idleness_drrs(struct i915_drrs *drrs);
+void intel_enable_idleness_drrs(struct i915_drrs *drrs);
+int intel_media_playback_drrs_configure(struct intel_crtc *crtc,
+					struct drm_display_mode *mode);
 int intel_drrs_init(struct drm_device *dev,
 			struct intel_connector *intel_connector,
 				struct drm_display_mode *fixed_mode);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 14/18] drm/i915: MEDIA_RR support in eDP DRRS module
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (12 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 13/18] drm/i915: MEDIA_RR support in general DRRS state machine Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:51 ` [RFC PATCH 15/18] drm/i915: MEDIA_RR support in DSI " Ramalingam C
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

Content based DRRS support is implemented in
eDP DRRS module also.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h      |    3 +++
 drivers/gpu/drm/i915/intel_edp_drrs.c |   29 +++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index b364a68..3a5cff8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -419,6 +419,9 @@ struct intel_crtc_state {
 
 	/* m2_n2 for eDP downclock */
 	struct intel_link_m_n dp_m2_n2;
+
+	/* m3_n3 for eDP Media playback DRRS */
+	struct intel_link_m_n dp_m3_n3;
 	bool has_drrs;
 
 	/*
diff --git a/drivers/gpu/drm/i915/intel_edp_drrs.c b/drivers/gpu/drm/i915/intel_edp_drrs.c
index 8968e4c..173c281 100644
--- a/drivers/gpu/drm/i915/intel_edp_drrs.c
+++ b/drivers/gpu/drm/i915/intel_edp_drrs.c
@@ -45,6 +45,8 @@ static int vlv_edp_set_drrs_state(struct intel_encoder *encoder,
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct i915_drrs *drrs;
 	u32 reg, val;
 
 	if (!crtc)
@@ -53,6 +55,10 @@ static int vlv_edp_set_drrs_state(struct intel_encoder *encoder,
 	reg = PIPECONF(crtc->config->cpu_transcoder);
 	val = I915_READ(reg);
 
+	drrs = dev_priv->drrs[get_drrs_struct_index_for_crtc(dev_priv, crtc)];
+	if (!drrs || !drrs->has_drrs)
+		return -EINVAL;
+
 	switch (target_rr_type) {
 	case DRRS_HIGH_RR:
 		if (IS_VALLEYVIEW(dev))
@@ -62,6 +68,29 @@ static int vlv_edp_set_drrs_state(struct intel_encoder *encoder,
 		if (IS_VALLEYVIEW(dev))
 			val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
 		break;
+	case DRRS_MEDIA_RR:
+		if (drrs->connector->panel.target_mode->vrefresh ==
+				drrs->connector->panel.fixed_mode->vrefresh) {
+			/* Exiting from MEDIA_RR */
+			if (IS_VALLEYVIEW(dev))
+				val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+
+			intel_dp_set_m_n(crtc, &crtc->config->dp_m_n,
+						&crtc->config->dp_m2_n2);
+		} else {
+			intel_link_compute_m_n(crtc->config->pipe_bpp,
+				intel_dp->lane_count,
+				drrs->connector->panel.target_mode->clock,
+				crtc->config->port_clock,
+				&crtc->config->dp_m3_n3);
+
+			if (IS_VALLEYVIEW(dev))
+				val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+
+			intel_dp_set_m_n(crtc, &crtc->config->dp_m_n,
+						&crtc->config->dp_m3_n3);
+		}
+		break;
 	default:
 		DRM_ERROR("invalid refresh rate type\n");
 		return -EINVAL;
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 15/18] drm/i915: MEDIA_RR support in DSI DRRS module
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (13 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 14/18] drm/i915: MEDIA_RR support in eDP DRRS module Ramalingam C
@ 2015-06-26 13:51 ` Ramalingam C
  2015-06-26 13:52 ` [RFC PATCH 16/18] drm/i915: Filtering media playback DRRS requests Ramalingam C
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:51 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

Content based DRRS support is implemented in
DSI DRRS module also.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_dsi_drrs.c |   60 +++++++++++++++++++++++++++++++--
 1 file changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
index d4bb70a..4ff06b8 100644
--- a/drivers/gpu/drm/i915/intel_dsi_drrs.c
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
@@ -19,6 +19,7 @@
 
 #include "intel_drv.h"
 #include "intel_dsi.h"
+#include "intel_drrs.h"
 
 /*
  * VLV and CHV platform code
@@ -50,9 +51,19 @@ static void intel_mipi_drrs_work_fn(struct work_struct *__work)
 	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
 	struct dsi_mnp *dsi_mnp;
 	struct drm_display_mode *prev_mode = NULL;
+	bool resume_idleness_detection = false;
 	bool fallback_attempt = false;
 	int ret, retry_cnt = 3;
 
+	if (work->target_rr_type == DRRS_MEDIA_RR) {
+		ret = dsi_drrs->ops->mnp_calculate_for_mode(
+				intel_encoder, &dsi_drrs->mnp[DRRS_MEDIA_RR],
+				drrs->connector->panel.target_mode);
+		if (ret < 0) {
+			DRM_ERROR("mnp calculation failed\n");
+			goto out;
+		}
+	}
 init:
 	dsi_mnp = &dsi_drrs->mnp[work->target_rr_type];
 	DRM_DEBUG("Refresh rate Type: %d-->%d\n",
@@ -60,6 +71,10 @@ init:
 						work->target_rr_type);
 	DRM_DEBUG("Target RR: %d\n", work->target_mode->vrefresh);
 
+	if (drrs->drrs_state.current_rr_type == DRRS_MEDIA_RR &&
+			work->target_rr_type == DRRS_HIGH_RR)
+		resume_idleness_detection = true;
+
 retry:
 	if (!intel_crtc || !intel_crtc->active)
 		goto out;
@@ -87,6 +102,11 @@ retry:
 
 		/* TODO: Update drain ladency with watermark */
 
+		if (resume_idleness_detection) {
+			intel_disable_idleness_drrs(drrs);
+			intel_enable_idleness_drrs(drrs);
+		}
+
 	} else if (ret == -ETIMEDOUT && retry_cnt) {
 
 		/* Timed out. But still attempts are allowed */
@@ -111,10 +131,14 @@ retry:
 		work->target_rr_type = drrs->drrs_state.target_rr_type;
 		drm_mode_destroy(intel_encoder->base.dev, work->target_mode);
 
-		if (work->target_rr_type == DRRS_HIGH_RR)
+		if (work->target_rr_type == DRRS_HIGH_RR) {
 			prev_mode = drrs->connector->panel.fixed_mode;
-		else if (work->target_rr_type == DRRS_LOW_RR)
+			resume_idleness_detection = true;
+		} else if (work->target_rr_type == DRRS_LOW_RR) {
 			prev_mode = drrs->connector->panel.downclock_mode;
+		} else if (work->target_rr_type == DRRS_MEDIA_RR) {
+			prev_mode = drrs->connector->panel.target_mode;
+		}
 
 		work->target_mode = drm_mode_duplicate(intel_encoder->base.dev,
 								prev_mode);
@@ -137,6 +161,37 @@ out:
 	work->work_completed = true;
 }
 
+/*
+ * As a part of Media playback request filtering
+ * we validate the incoming request wrt deferred works
+ * of MIPI PLL programming
+ */
+bool intel_dsi_is_mp_drrs_req(struct i915_drrs *drrs,
+					struct drm_display_mode *mode)
+{
+	struct intel_dsi *intel_dsi =
+			enc_to_intel_dsi(&drrs->connector->encoder->base);
+	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+	struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+	bool ret = false;
+
+	if (work_busy(&work->work.work)) {
+		if (work->target_mode->vrefresh != mode->vrefresh ||
+			drrs->drrs_state.current_rr_type != DRRS_MEDIA_RR)
+
+			/*
+			 * First condition: Deferred work is in place to change
+			 * the DRRS state. Hence this call is valid Media
+			 * playback DRRS request.
+			 *
+			 * Second Condition: Might be same as deffered work but
+			 * this is from media playback request. So honor it.
+			 */
+			ret = true;
+	}
+	return ret;
+}
+
 /* Whether DRRS_HR_STATE is pending in the dsi deferred work */
 bool intel_dsi_is_drrs_hr_state_pending(struct i915_drrs *drrs)
 {
@@ -350,6 +405,7 @@ struct drrs_encoder_ops drrs_dsi_ops = {
 	.exit = intel_dsi_drrs_exit,
 	.set_drrs_state = intel_dsi_set_drrs_state,
 	.is_drrs_hr_state_pending = intel_dsi_is_drrs_hr_state_pending,
+	.is_mp_drrs_req = intel_dsi_is_mp_drrs_req,
 };
 
 /* Call back Function for Intel_drrs module to get the dsi func ptr */
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 16/18] drm/i915: Filtering media playback DRRS requests
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (14 preceding siblings ...)
  2015-06-26 13:51 ` [RFC PATCH 15/18] drm/i915: MEDIA_RR support in DSI " Ramalingam C
@ 2015-06-26 13:52 ` Ramalingam C
  2015-06-26 13:52 ` [RFC PATCH 17/18] drm/i915: Addition of downclock mode to connector modelist Ramalingam C
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:52 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

If the platform supports the media playback DRRS, Userspace can provide
a request for Media playback DRRS. This is done by placing the modeset
request with the same mode and FB but with different vrefresh.

This change implements the algorithm to identify the Media playback
DRRS requests from the normal modeset requests.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   14 +++++++++
 drivers/gpu/drm/i915/intel_drrs.c    |   54 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drrs.h    |    1 +
 3 files changed, 69 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b36fde6..0335c09 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13295,6 +13295,20 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
 	dev = set->crtc->dev;
 
+	/* Identifying the Media Playback DRRS request */
+	if (is_media_playback_drrs_request(set)) {
+
+		/*
+		 * While requesting for Media Playback DRRS Userspace should
+		 * make sure that fb passed is same as that is in use.
+		 * Else at successful drrs request, we will hit a warn_on on
+		 * return path for fb mismatch
+		 */
+		ret = intel_media_playback_drrs_configure(
+					to_intel_crtc(set->crtc), set->mode);
+		return ret;
+	}
+
 	state = drm_atomic_state_alloc(dev);
 	if (!state)
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index 7f66be4..9634254 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -523,6 +523,60 @@ set_state:
 	return 0;
 }
 
+/* Function to filter the Media playback DRRS request from the normal
+ * mode set */
+bool is_media_playback_drrs_request(struct drm_mode_set *set)
+{
+	struct drm_device *dev = set->crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc);
+	struct i915_drrs *drrs;
+	struct intel_encoder *encoder;
+	struct drrs_info *drrs_state;
+	bool ret = false;
+	int index;
+
+	index = get_drrs_struct_index_for_crtc(dev_priv, intel_crtc);
+	if (index < 0)
+		return ret;
+
+	drrs = dev_priv->drrs[index];
+	if (!drrs || !drrs->has_drrs)
+		return ret;
+
+	/* Return if the current crtc mode's vrefresh is 0 */
+	if (!set->mode || !set->crtc->mode.vrefresh)
+		return ret;
+
+	/* Crtc should be active */
+	if (!intel_crtc->active)
+		return ret;
+
+	drrs_state = &drrs->drrs_state;
+	encoder = drrs->connector->encoder;
+
+	/* At present only DSI and eDP support DRRS */
+	if (encoder->type != INTEL_OUTPUT_EDP &&
+				encoder->type != INTEL_OUTPUT_DSI)
+		return ret;
+
+	DRM_DEBUG_KMS("mode_vr: %d, crtc_vr: %d, cur_rr_type: %d\n",
+				set->mode->vrefresh, set->crtc->mode.vrefresh,
+						drrs_state->current_rr_type);
+
+	if (drm_mode_equal_no_clocks_no_stereo(set->mode, &set->crtc->mode)) {
+		if (set->mode->vrefresh != set->crtc->mode.vrefresh)
+			ret = true;
+
+		if (drrs_state->type == SEAMLESS_DRRS_SUPPORT_SW &&
+					drrs->encoder_ops->is_mp_drrs_req)
+			if (drrs->encoder_ops->is_mp_drrs_req(drrs, set->mode))
+				ret = true;
+	}
+
+	return ret;
+}
+
 /* Idleness detection logic is initialized */
 int intel_drrs_idleness_detection_init(struct i915_drrs *drrs)
 {
diff --git a/drivers/gpu/drm/i915/intel_drrs.h b/drivers/gpu/drm/i915/intel_drrs.h
index 7f9985c0..72b4aeb 100644
--- a/drivers/gpu/drm/i915/intel_drrs.h
+++ b/drivers/gpu/drm/i915/intel_drrs.h
@@ -30,6 +30,7 @@ void intel_disable_idleness_drrs(struct i915_drrs *drrs);
 void intel_enable_idleness_drrs(struct i915_drrs *drrs);
 int intel_media_playback_drrs_configure(struct intel_crtc *crtc,
 					struct drm_display_mode *mode);
+bool is_media_playback_drrs_request(struct drm_mode_set *set);
 int intel_drrs_init(struct drm_device *dev,
 			struct intel_connector *intel_connector,
 				struct drm_display_mode *fixed_mode);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 17/18] drm/i915: Addition of downclock mode to connector modelist
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (15 preceding siblings ...)
  2015-06-26 13:52 ` [RFC PATCH 16/18] drm/i915: Filtering media playback DRRS requests Ramalingam C
@ 2015-06-26 13:52 ` Ramalingam C
  2015-06-26 13:52 ` [RFC PATCH 18/18] drm/i915: Connector property for DRRS capability Ramalingam C
  2015-06-26 17:16 ` [RFC PATCH 00/18] Generic DRRS implementation across the encoders Daniel Vetter
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:52 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

If DSI panel has the downclock mode supported, add that in the
connector's mode list.

This is needed by userspace apps to identify the range of vrefresh
rates supported by panel incase of the media playback DRRS.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_dsi.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 98998e9..503f3de 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -912,23 +912,38 @@ static int intel_dsi_get_modes(struct drm_connector *connector)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct drm_display_mode *mode;
+	int count = 0;
 
 	DRM_DEBUG_KMS("\n");
 
 	if (!intel_connector->panel.fixed_mode) {
 		DRM_DEBUG_KMS("no fixed mode\n");
-		return 0;
+		return count;
 	}
 
 	mode = drm_mode_duplicate(connector->dev,
 				  intel_connector->panel.fixed_mode);
 	if (!mode) {
 		DRM_DEBUG_KMS("drm_mode_duplicate failed\n");
-		return 0;
+		return count;
 	}
 
 	drm_mode_probed_add(connector, mode);
-	return 1;
+	count++;
+
+	if (intel_connector->panel.downclock_mode) {
+		mode = drm_mode_duplicate(connector->dev,
+			intel_connector->panel.downclock_mode);
+		if (!mode) {
+			DRM_DEBUG_KMS("drm_mode_duplicate failed\n");
+			return count;
+		}
+
+		drm_mode_probed_add(connector, mode);
+		count++;
+	}
+
+	return count;
 }
 
 static void intel_dsi_connector_destroy(struct drm_connector *connector)
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [RFC PATCH 18/18] drm/i915: Connector property for DRRS capability
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (16 preceding siblings ...)
  2015-06-26 13:52 ` [RFC PATCH 17/18] drm/i915: Addition of downclock mode to connector modelist Ramalingam C
@ 2015-06-26 13:52 ` Ramalingam C
  2015-06-26 17:16 ` [RFC PATCH 00/18] Generic DRRS implementation across the encoders Daniel Vetter
  18 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-26 13:52 UTC (permalink / raw)
  To: intel-gfx, daniel.vetter, chris, rodrigo.vivi; +Cc: paulo.r.zanoni

DRRS capability on each connector is exposed to userspace through
drm connector property.

In this change one drm property is created and attached with each
connector. And when DRRS is successfully initialized for a connector,
drrs connector property is set with appropriate value.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c    |    1 +
 drivers/gpu/drm/i915/intel_drrs.c  |    5 +++++
 drivers/gpu/drm/i915/intel_drv.h   |    6 ++++++
 drivers/gpu/drm/i915/intel_dsi.c   |    8 ++++++++
 drivers/gpu/drm/i915/intel_modes.c |   28 ++++++++++++++++++++++++++++
 5 files changed, 48 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9ded4d1..22001b6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5063,6 +5063,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 
 	intel_attach_force_audio_property(connector);
 	intel_attach_broadcast_rgb_property(connector);
+	intel_attach_drrs_capability_property(connector);
 	intel_dp->color_range_auto = true;
 
 	if (is_edp(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index 9634254..89f2d39 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -684,6 +684,11 @@ int intel_drrs_init(struct drm_device *dev,
 	mutex_init(&drrs->drrs_mutex);
 	drrs->resume_idleness_detection = false;
 	drrs->drrs_state.current_rr_type = DRRS_HIGH_RR;
+
+	/* DRRS connector property */
+	drm_object_property_set_value(&intel_connector->base.base,
+				intel_connector->drrs_capability_property,
+				drrs->drrs_state.type);
 	DRM_INFO("SEAMLESS DRRS supported on this panel.\n");
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3a5cff8..97a5af8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -231,6 +231,9 @@ struct intel_connector {
 	void *port; /* store this opaque as its illegal to dereference it */
 
 	struct intel_dp *mst_port;
+
+	/* DRRS capability */
+	struct drm_property *drrs_capability_property;
 };
 
 typedef struct dpll {
@@ -1266,6 +1269,9 @@ int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
 void intel_attach_force_audio_property(struct drm_connector *connector);
 void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 
+/* DRRS function */
+void intel_attach_drrs_capability_property(struct drm_connector *connector);
+
 
 /* intel_overlay.c */
 void intel_setup_overlay(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 503f3de..2efad4b 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -968,6 +968,13 @@ static void intel_dsi_encoder_destroy(struct drm_encoder *encoder)
 	intel_encoder_destroy(encoder);
 }
 
+static void
+intel_dsi_add_properties(struct intel_dsi *intel_dsi,
+				struct drm_connector *connector)
+{
+	intel_attach_drrs_capability_property(connector);
+}
+
 static const struct drm_encoder_funcs intel_dsi_funcs = {
 	.destroy = intel_dsi_encoder_destroy,
 };
@@ -1091,6 +1098,7 @@ void intel_dsi_init(struct drm_device *dev)
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
 
+	intel_dsi_add_properties(intel_dsi, connector);
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 
 	drm_connector_register(connector);
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 0e860f3..f6c466c 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -126,3 +126,31 @@ intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 
 	drm_object_attach_property(&connector->base, prop, 0);
 }
+
+static const struct drm_prop_enum_list drrs_capability_names[] = {
+	{ DRRS_NOT_SUPPORTED, "Off" },
+	{ STATIC_DRRS_SUPPORT, "Off-Static" },
+	{ SEAMLESS_DRRS_SUPPORT, "Seamless-HW" },
+	{ SEAMLESS_DRRS_SUPPORT_SW, "Seamless-SW" },
+};
+
+void intel_attach_drrs_capability_property(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct drm_property *prop;
+
+	prop = intel_connector->drrs_capability_property;
+	if (prop == NULL) {
+		prop = drm_property_create_enum(dev, 0,
+					"drrs_capability",
+					drrs_capability_names,
+					ARRAY_SIZE(drrs_capability_names));
+		if (prop == NULL) {
+			DRM_ERROR("Drm property enum creation failed\n");
+			return;
+		}
+		intel_connector->drrs_capability_property = prop;
+	}
+	drm_object_attach_property(&connector->base, prop, DRRS_NOT_SUPPORTED);
+}
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation
  2015-06-26 13:51 ` [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation Ramalingam C
@ 2015-06-26 16:50   ` Daniel Vetter
  2015-06-29 11:24     ` Ramalingam C
  0 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2015-06-26 16:50 UTC (permalink / raw)
  To: Ramalingam C; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi

On Fri, Jun 26, 2015 at 07:21:45PM +0530, Ramalingam C wrote:
> EDP specific DRRS implementation is removed to implement a
> generic DRRS stack extentable accross the supportable encoders.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>

Nack. You don't make something generic by first throwing out the existing
solution (and all the lessons learned implementing that).

Instead convert the edp DRRS implementation over to use generic
structures, step-by-step, and then once that's done it should be simply to
implement DRRS for other outputs.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_debugfs.c      |  110 ---------
>  drivers/gpu/drm/i915/i915_drv.h          |   22 --
>  drivers/gpu/drm/i915/intel_ddi.c         |    2 -
>  drivers/gpu/drm/i915/intel_dp.c          |  392 ------------------------------
>  drivers/gpu/drm/i915/intel_drv.h         |    5 -
>  drivers/gpu/drm/i915/intel_frontbuffer.c |    2 -
>  6 files changed, 533 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index c49fe2a..7dbf170 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2962,115 +2962,6 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
>  	return 0;
>  }
>  
> -static void drrs_status_per_crtc(struct seq_file *m,
> -		struct drm_device *dev, struct intel_crtc *intel_crtc)
> -{
> -	struct intel_encoder *intel_encoder;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct i915_drrs *drrs = &dev_priv->drrs;
> -	int vrefresh = 0;
> -
> -	for_each_encoder_on_crtc(dev, &intel_crtc->base, intel_encoder) {
> -		/* Encoder connected on this CRTC */
> -		switch (intel_encoder->type) {
> -		case INTEL_OUTPUT_EDP:
> -			seq_puts(m, "eDP:\n");
> -			break;
> -		case INTEL_OUTPUT_DSI:
> -			seq_puts(m, "DSI:\n");
> -			break;
> -		case INTEL_OUTPUT_HDMI:
> -			seq_puts(m, "HDMI:\n");
> -			break;
> -		case INTEL_OUTPUT_DISPLAYPORT:
> -			seq_puts(m, "DP:\n");
> -			break;
> -		default:
> -			seq_printf(m, "Other encoder (id=%d).\n",
> -						intel_encoder->type);
> -			return;
> -		}
> -	}
> -
> -	if (dev_priv->vbt.drrs_type == STATIC_DRRS_SUPPORT)
> -		seq_puts(m, "\tVBT: DRRS_type: Static");
> -	else if (dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT)
> -		seq_puts(m, "\tVBT: DRRS_type: Seamless");
> -	else if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED)
> -		seq_puts(m, "\tVBT: DRRS_type: None");
> -	else
> -		seq_puts(m, "\tVBT: DRRS_type: FIXME: Unrecognized Value");
> -
> -	seq_puts(m, "\n\n");
> -
> -	if (to_intel_crtc_state(intel_crtc->base.state)->has_drrs) {
> -		struct intel_panel *panel;
> -
> -		mutex_lock(&drrs->mutex);
> -		/* DRRS Supported */
> -		seq_puts(m, "\tDRRS Supported: Yes\n");
> -
> -		/* disable_drrs() will make drrs->dp NULL */
> -		if (!drrs->dp) {
> -			seq_puts(m, "Idleness DRRS: Disabled");
> -			mutex_unlock(&drrs->mutex);
> -			return;
> -		}
> -
> -		panel = &drrs->dp->attached_connector->panel;
> -		seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X",
> -					drrs->busy_frontbuffer_bits);
> -
> -		seq_puts(m, "\n\t\t");
> -		if (drrs->refresh_rate_type == DRRS_HIGH_RR) {
> -			seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n");
> -			vrefresh = panel->fixed_mode->vrefresh;
> -		} else if (drrs->refresh_rate_type == DRRS_LOW_RR) {
> -			seq_puts(m, "DRRS_State: DRRS_LOW_RR\n");
> -			vrefresh = panel->downclock_mode->vrefresh;
> -		} else {
> -			seq_printf(m, "DRRS_State: Unknown(%d)\n",
> -						drrs->refresh_rate_type);
> -			mutex_unlock(&drrs->mutex);
> -			return;
> -		}
> -		seq_printf(m, "\t\tVrefresh: %d", vrefresh);
> -
> -		seq_puts(m, "\n\t\t");
> -		mutex_unlock(&drrs->mutex);
> -	} else {
> -		/* DRRS not supported. Print the VBT parameter*/
> -		seq_puts(m, "\tDRRS Supported : No");
> -	}
> -	seq_puts(m, "\n");
> -}
> -
> -static int i915_drrs_status(struct seq_file *m, void *unused)
> -{
> -	struct drm_info_node *node = m->private;
> -	struct drm_device *dev = node->minor->dev;
> -	struct intel_crtc *intel_crtc;
> -	int active_crtc_cnt = 0;
> -
> -	for_each_intel_crtc(dev, intel_crtc) {
> -		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
> -
> -		if (intel_crtc->base.state->active) {
> -			active_crtc_cnt++;
> -			seq_printf(m, "\nCRTC %d:  ", active_crtc_cnt);
> -
> -			drrs_status_per_crtc(m, dev, intel_crtc);
> -		}
> -
> -		drm_modeset_unlock(&intel_crtc->base.mutex);
> -	}
> -
> -	if (!active_crtc_cnt)
> -		seq_puts(m, "No active crtc found\n");
> -
> -	return 0;
> -}
> -
>  struct pipe_crc_info {
>  	const char *name;
>  	struct drm_device *dev;
> @@ -5048,7 +4939,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
>  	{"i915_wa_registers", i915_wa_registers, 0},
>  	{"i915_ddb_info", i915_ddb_info, 0},
>  	{"i915_sseu_status", i915_sseu_status, 0},
> -	{"i915_drrs_status", i915_drrs_status, 0},
>  	{"i915_rps_boost_info", i915_rps_boost_info, 0},
>  };
>  #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 491ef0c..922dd68 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -930,33 +930,12 @@ struct i915_fbc {
>  	} no_fbc_reason;
>  };
>  
> -/**
> - * HIGH_RR is the highest eDP panel refresh rate read from EDID
> - * LOW_RR is the lowest eDP panel refresh rate found from EDID
> - * parsing for same resolution.
> - */
> -enum drrs_refresh_rate_type {
> -	DRRS_HIGH_RR,
> -	DRRS_LOW_RR,
> -	DRRS_MAX_RR, /* RR count */
> -};
> -
>  enum drrs_support_type {
>  	DRRS_NOT_SUPPORTED = 0,
>  	STATIC_DRRS_SUPPORT = 1,
>  	SEAMLESS_DRRS_SUPPORT = 2
>  };
>  
> -struct intel_dp;
> -struct i915_drrs {
> -	struct mutex mutex;
> -	struct delayed_work work;
> -	struct intel_dp *dp;
> -	unsigned busy_frontbuffer_bits;
> -	enum drrs_refresh_rate_type refresh_rate_type;
> -	enum drrs_support_type type;
> -};
> -
>  struct i915_psr {
>  	struct mutex lock;
>  	bool sink_support;
> @@ -1718,7 +1697,6 @@ struct drm_i915_private {
>  
>  	struct i915_hotplug hotplug;
>  	struct i915_fbc fbc;
> -	struct i915_drrs drrs;
>  	struct intel_opregion opregion;
>  	struct intel_vbt_data vbt;
>  
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 31b29e8..75afbd7 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2012,7 +2012,6 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
>  
>  		intel_edp_backlight_on(intel_dp);
>  		intel_psr_enable(intel_dp);
> -		intel_edp_drrs_enable(intel_dp);
>  	}
>  
>  	if (intel_crtc->config->has_audio) {
> @@ -2038,7 +2037,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
>  	if (type == INTEL_OUTPUT_EDP) {
>  		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>  
> -		intel_edp_drrs_disable(intel_dp);
>  		intel_psr_disable(intel_dp);
>  		intel_edp_backlight_off(intel_dp);
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index f52eef1..738e98e 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1483,15 +1483,6 @@ found:
>  			       pipe_config->port_clock,
>  			       &pipe_config->dp_m_n);
>  
> -	if (intel_connector->panel.downclock_mode != NULL &&
> -		dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) {
> -			pipe_config->has_drrs = true;
> -			intel_link_compute_m_n(bpp, lane_count,
> -				intel_connector->panel.downclock_mode->clock,
> -				pipe_config->port_clock,
> -				&pipe_config->dp_m2_n2);
> -	}
> -
>  	if (IS_SKYLAKE(dev) && is_edp(intel_dp))
>  		skl_edp_set_pll_config(pipe_config, common_rates[clock]);
>  	else if (IS_BROXTON(dev))
> @@ -5254,387 +5245,6 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>  		      I915_READ(pp_div_reg));
>  }
>  
> -/**
> - * intel_dp_set_drrs_state - program registers for RR switch to take effect
> - * @dev: DRM device
> - * @refresh_rate: RR to be programmed
> - *
> - * This function gets called when refresh rate (RR) has to be changed from
> - * one frequency to another. Switches can be between high and low RR
> - * supported by the panel or to any other RR based on media playback (in
> - * this case, RR value needs to be passed from user space).
> - *
> - * The caller of this function needs to take a lock on dev_priv->drrs.
> - */
> -static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
> -{
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_encoder *encoder;
> -	struct intel_digital_port *dig_port = NULL;
> -	struct intel_dp *intel_dp = dev_priv->drrs.dp;
> -	struct intel_crtc_state *config = NULL;
> -	struct intel_crtc *intel_crtc = NULL;
> -	u32 reg, val;
> -	enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
> -
> -	if (refresh_rate <= 0) {
> -		DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n");
> -		return;
> -	}
> -
> -	if (intel_dp == NULL) {
> -		DRM_DEBUG_KMS("DRRS not supported.\n");
> -		return;
> -	}
> -
> -	/*
> -	 * FIXME: This needs proper synchronization with psr state for some
> -	 * platforms that cannot have PSR and DRRS enabled at the same time.
> -	 */
> -
> -	dig_port = dp_to_dig_port(intel_dp);
> -	encoder = &dig_port->base;
> -	intel_crtc = to_intel_crtc(encoder->base.crtc);
> -
> -	if (!intel_crtc) {
> -		DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
> -		return;
> -	}
> -
> -	config = intel_crtc->config;
> -
> -	if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
> -		DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
> -		return;
> -	}
> -
> -	if (intel_dp->attached_connector->panel.downclock_mode->vrefresh ==
> -			refresh_rate)
> -		index = DRRS_LOW_RR;
> -
> -	if (index == dev_priv->drrs.refresh_rate_type) {
> -		DRM_DEBUG_KMS(
> -			"DRRS requested for previously set RR...ignoring\n");
> -		return;
> -	}
> -
> -	if (!intel_crtc->active) {
> -		DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n");
> -		return;
> -	}
> -
> -	if (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev)) {
> -		switch (index) {
> -		case DRRS_HIGH_RR:
> -			intel_dp_set_m_n(intel_crtc, M1_N1);
> -			break;
> -		case DRRS_LOW_RR:
> -			intel_dp_set_m_n(intel_crtc, M2_N2);
> -			break;
> -		case DRRS_MAX_RR:
> -		default:
> -			DRM_ERROR("Unsupported refreshrate type\n");
> -		}
> -	} else if (INTEL_INFO(dev)->gen > 6) {
> -		reg = PIPECONF(intel_crtc->config->cpu_transcoder);
> -		val = I915_READ(reg);
> -
> -		if (index > DRRS_HIGH_RR) {
> -			if (IS_VALLEYVIEW(dev))
> -				val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
> -			else
> -				val |= PIPECONF_EDP_RR_MODE_SWITCH;
> -		} else {
> -			if (IS_VALLEYVIEW(dev))
> -				val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
> -			else
> -				val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
> -		}
> -		I915_WRITE(reg, val);
> -	}
> -
> -	dev_priv->drrs.refresh_rate_type = index;
> -
> -	DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
> -}
> -
> -/**
> - * intel_edp_drrs_enable - init drrs struct if supported
> - * @intel_dp: DP struct
> - *
> - * Initializes frontbuffer_bits and drrs.dp
> - */
> -void intel_edp_drrs_enable(struct intel_dp *intel_dp)
> -{
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_crtc *crtc = dig_port->base.base.crtc;
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -
> -	if (!intel_crtc->config->has_drrs) {
> -		DRM_DEBUG_KMS("Panel doesn't support DRRS\n");
> -		return;
> -	}
> -
> -	mutex_lock(&dev_priv->drrs.mutex);
> -	if (WARN_ON(dev_priv->drrs.dp)) {
> -		DRM_ERROR("DRRS already enabled\n");
> -		goto unlock;
> -	}
> -
> -	dev_priv->drrs.busy_frontbuffer_bits = 0;
> -
> -	dev_priv->drrs.dp = intel_dp;
> -
> -unlock:
> -	mutex_unlock(&dev_priv->drrs.mutex);
> -}
> -
> -/**
> - * intel_edp_drrs_disable - Disable DRRS
> - * @intel_dp: DP struct
> - *
> - */
> -void intel_edp_drrs_disable(struct intel_dp *intel_dp)
> -{
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_crtc *crtc = dig_port->base.base.crtc;
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -
> -	if (!intel_crtc->config->has_drrs)
> -		return;
> -
> -	mutex_lock(&dev_priv->drrs.mutex);
> -	if (!dev_priv->drrs.dp) {
> -		mutex_unlock(&dev_priv->drrs.mutex);
> -		return;
> -	}
> -
> -	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
> -		intel_dp_set_drrs_state(dev_priv->dev,
> -			intel_dp->attached_connector->panel.
> -			fixed_mode->vrefresh);
> -
> -	dev_priv->drrs.dp = NULL;
> -	mutex_unlock(&dev_priv->drrs.mutex);
> -
> -	cancel_delayed_work_sync(&dev_priv->drrs.work);
> -}
> -
> -static void intel_edp_drrs_downclock_work(struct work_struct *work)
> -{
> -	struct drm_i915_private *dev_priv =
> -		container_of(work, typeof(*dev_priv), drrs.work.work);
> -	struct intel_dp *intel_dp;
> -
> -	mutex_lock(&dev_priv->drrs.mutex);
> -
> -	intel_dp = dev_priv->drrs.dp;
> -
> -	if (!intel_dp)
> -		goto unlock;
> -
> -	/*
> -	 * The delayed work can race with an invalidate hence we need to
> -	 * recheck.
> -	 */
> -
> -	if (dev_priv->drrs.busy_frontbuffer_bits)
> -		goto unlock;
> -
> -	if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR)
> -		intel_dp_set_drrs_state(dev_priv->dev,
> -			intel_dp->attached_connector->panel.
> -			downclock_mode->vrefresh);
> -
> -unlock:
> -	mutex_unlock(&dev_priv->drrs.mutex);
> -}
> -
> -/**
> - * intel_edp_drrs_invalidate - Disable Idleness DRRS
> - * @dev: DRM device
> - * @frontbuffer_bits: frontbuffer plane tracking bits
> - *
> - * This function gets called everytime rendering on the given planes start.
> - * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
> - *
> - * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
> - */
> -void intel_edp_drrs_invalidate(struct drm_device *dev,
> -		unsigned frontbuffer_bits)
> -{
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_crtc *crtc;
> -	enum pipe pipe;
> -
> -	if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
> -		return;
> -
> -	cancel_delayed_work(&dev_priv->drrs.work);
> -
> -	mutex_lock(&dev_priv->drrs.mutex);
> -	if (!dev_priv->drrs.dp) {
> -		mutex_unlock(&dev_priv->drrs.mutex);
> -		return;
> -	}
> -
> -	crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
> -	pipe = to_intel_crtc(crtc)->pipe;
> -
> -	/* invalidate means busy screen hence upclock */
> -	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
> -		intel_dp_set_drrs_state(dev_priv->dev,
> -				dev_priv->drrs.dp->attached_connector->panel.
> -				fixed_mode->vrefresh);
> -	}
> -
> -	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
> -
> -	dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
> -	mutex_unlock(&dev_priv->drrs.mutex);
> -}
> -
> -/**
> - * intel_edp_drrs_flush - Restart Idleness DRRS
> - * @dev: DRM device
> - * @frontbuffer_bits: frontbuffer plane tracking bits
> - *
> - * This function gets called every time rendering on the given planes has
> - * completed or flip on a crtc is completed. So DRRS should be upclocked
> - * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
> - * if no other planes are dirty.
> - *
> - * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
> - */
> -void intel_edp_drrs_flush(struct drm_device *dev,
> -		unsigned frontbuffer_bits)
> -{
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_crtc *crtc;
> -	enum pipe pipe;
> -
> -	if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
> -		return;
> -
> -	cancel_delayed_work(&dev_priv->drrs.work);
> -
> -	mutex_lock(&dev_priv->drrs.mutex);
> -	if (!dev_priv->drrs.dp) {
> -		mutex_unlock(&dev_priv->drrs.mutex);
> -		return;
> -	}
> -
> -	crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
> -	pipe = to_intel_crtc(crtc)->pipe;
> -	dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
> -
> -	/* flush means busy screen hence upclock */
> -	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
> -		intel_dp_set_drrs_state(dev_priv->dev,
> -				dev_priv->drrs.dp->attached_connector->panel.
> -				fixed_mode->vrefresh);
> -
> -	/*
> -	 * flush also means no more activity hence schedule downclock, if all
> -	 * other fbs are quiescent too
> -	 */
> -	if (!dev_priv->drrs.busy_frontbuffer_bits)
> -		schedule_delayed_work(&dev_priv->drrs.work,
> -				msecs_to_jiffies(1000));
> -	mutex_unlock(&dev_priv->drrs.mutex);
> -}
> -
> -/**
> - * DOC: Display Refresh Rate Switching (DRRS)
> - *
> - * Display Refresh Rate Switching (DRRS) is a power conservation feature
> - * which enables swtching between low and high refresh rates,
> - * dynamically, based on the usage scenario. This feature is applicable
> - * for internal panels.
> - *
> - * Indication that the panel supports DRRS is given by the panel EDID, which
> - * would list multiple refresh rates for one resolution.
> - *
> - * DRRS is of 2 types - static and seamless.
> - * Static DRRS involves changing refresh rate (RR) by doing a full modeset
> - * (may appear as a blink on screen) and is used in dock-undock scenario.
> - * Seamless DRRS involves changing RR without any visual effect to the user
> - * and can be used during normal system usage. This is done by programming
> - * certain registers.
> - *
> - * Support for static/seamless DRRS may be indicated in the VBT based on
> - * inputs from the panel spec.
> - *
> - * DRRS saves power by switching to low RR based on usage scenarios.
> - *
> - * eDP DRRS:-
> - *        The implementation is based on frontbuffer tracking implementation.
> - * When there is a disturbance on the screen triggered by user activity or a
> - * periodic system activity, DRRS is disabled (RR is changed to high RR).
> - * When there is no movement on screen, after a timeout of 1 second, a switch
> - * to low RR is made.
> - *        For integration with frontbuffer tracking code,
> - * intel_edp_drrs_invalidate() and intel_edp_drrs_flush() are called.
> - *
> - * DRRS can be further extended to support other internal panels and also
> - * the scenario of video playback wherein RR is set based on the rate
> - * requested by userspace.
> - */
> -
> -/**
> - * intel_dp_drrs_init - Init basic DRRS work and mutex.
> - * @intel_connector: eDP connector
> - * @fixed_mode: preferred mode of panel
> - *
> - * This function is  called only once at driver load to initialize basic
> - * DRRS stuff.
> - *
> - * Returns:
> - * Downclock mode if panel supports it, else return NULL.
> - * DRRS support is determined by the presence of downclock mode (apart
> - * from VBT setting).
> - */
> -static struct drm_display_mode *
> -intel_dp_drrs_init(struct intel_connector *intel_connector,
> -		struct drm_display_mode *fixed_mode)
> -{
> -	struct drm_connector *connector = &intel_connector->base;
> -	struct drm_device *dev = connector->dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct drm_display_mode *downclock_mode = NULL;
> -
> -	INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
> -	mutex_init(&dev_priv->drrs.mutex);
> -
> -	if (INTEL_INFO(dev)->gen <= 6) {
> -		DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
> -		return NULL;
> -	}
> -
> -	if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
> -		DRM_DEBUG_KMS("VBT doesn't support DRRS\n");
> -		return NULL;
> -	}
> -
> -	downclock_mode = intel_find_panel_downclock
> -					(dev, fixed_mode, connector);
> -
> -	if (!downclock_mode) {
> -		DRM_DEBUG_KMS("Downclock mode is not found. DRRS not supported\n");
> -		return NULL;
> -	}
> -
> -	dev_priv->drrs.type = dev_priv->vbt.drrs_type;
> -
> -	dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
> -	DRM_DEBUG_KMS("seamless DRRS supported for eDP panel.\n");
> -	return downclock_mode;
> -}
> -
>  static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  				     struct intel_connector *intel_connector)
>  {
> @@ -5696,8 +5306,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	list_for_each_entry(scan, &connector->probed_modes, head) {
>  		if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
>  			fixed_mode = drm_mode_duplicate(dev, scan);
> -			downclock_mode = intel_dp_drrs_init(
> -						intel_connector, fixed_mode);
>  			break;
>  		}
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index bcafefc..e2f534a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1198,11 +1198,6 @@ void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
>  void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
>  uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
>  void intel_plane_destroy(struct drm_plane *plane);
> -void intel_edp_drrs_enable(struct intel_dp *intel_dp);
> -void intel_edp_drrs_disable(struct intel_dp *intel_dp);
> -void intel_edp_drrs_invalidate(struct drm_device *dev,
> -		unsigned frontbuffer_bits);
> -void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
>  
>  /* intel_dp_mst.c */
>  int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
> diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c
> index 57095f5..249d0b3 100644
> --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
> @@ -154,7 +154,6 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
>  	intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
>  
>  	intel_psr_invalidate(dev, obj->frontbuffer_bits);
> -	intel_edp_drrs_invalidate(dev, obj->frontbuffer_bits);
>  	intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin);
>  }
>  
> @@ -181,7 +180,6 @@ void intel_frontbuffer_flush(struct drm_device *dev,
>  
>  	intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
>  
> -	intel_edp_drrs_flush(dev, frontbuffer_bits);
>  	intel_psr_flush(dev, frontbuffer_bits);
>  	intel_fbc_flush(dev_priv, frontbuffer_bits);
>  }
> -- 
> 1.7.9.5
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 09/18] drm/i915: Cloned mode check
  2015-06-26 13:51 ` [RFC PATCH 09/18] drm/i915: Cloned mode check Ramalingam C
@ 2015-06-26 17:08   ` Daniel Vetter
  2015-06-26 17:14     ` Chris Wilson
  2015-06-29 11:48     ` Ramalingam C
  0 siblings, 2 replies; 36+ messages in thread
From: Daniel Vetter @ 2015-06-26 17:08 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, rodrigo.vivi, paulo.r.zanoni

On Fri, Jun 26, 2015 at 07:21:53PM +0530, Ramalingam C wrote:
> If crtc is in clone mode, DRRS will be disabled. Because if the both
> the displays are not sharing the same vrefresh, then userspace
> activities based on vsync will go for toss.
> 
> Clone mode will be rechecked on every restarting Idleness DRRS events.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drrs.c |   36 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 35 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
> index e5d8bcd..42b420d 100644
> --- a/drivers/gpu/drm/i915/intel_drrs.c
> +++ b/drivers/gpu/drm/i915/intel_drrs.c
> @@ -16,6 +16,7 @@
>  
>  #include <drm/i915_drm.h>
>  #include <linux/delay.h>
> +#include <linux/list.h>
>  
>  #include "i915_drv.h"
>  #include "intel_drv.h"
> @@ -85,6 +86,31 @@ int get_free_drrs_struct_index(struct drm_i915_private *dev_priv)
>  	return -EBUSY;
>  }
>  
> +/*
> + * TODO: This is identifying the multiple active crtcs at a time.
> + * Here we assume that this is clone state and disable DRRS.
> + * But need to implement a proper method to find the real cloned mode
> + * state. DRRS need not be disabled incase of multiple crtcs with
> + * different content.
> + */

This is a pretty big hack. Why do you need it? fb tracking should keep any
display in the high mode as long as there's activity, so as long as
userspace flips both buffers for both pipes (which is should for cloned
mode) they'll both be running at max.

And for non-cloned mode (e.g. video only on external TV) things will be
controlled independantly.

Smells a lot like trying to encode policy instead of making sure that the
resulting behaviour matches what we want. And I think it should already.
-Daniel

> +
> +bool is_cloned_mode_active(struct drm_device *dev)
> +{
> +	struct drm_crtc *crtc = NULL, *tmp_crtc;
> +
> +	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
> +		if (crtc && intel_crtc_active(tmp_crtc)) {
> +			DRM_DEBUG_KMS(
> +			"more than one crtc active. Declared as clonec mode\n");
> +			return true;
> +		}
> +
> +		if (intel_crtc_active(tmp_crtc))
> +			crtc = tmp_crtc;
> +	}
> +	return false;
> +}
> +
>  void intel_set_drrs_state(struct i915_drrs *drrs)
>  {
>  	struct drrs_info *drrs_state;
> @@ -158,7 +184,10 @@ static void intel_idleness_drrs_work_fn(struct work_struct *__work)
>  
>  	panel = &drrs->connector->panel;
>  
> -	/* TODO: If DRRS is not supported on clone mode act here */
> +	/* Double check if the dual-display mode is active. */
> +	if (drrs->is_clone)
> +		return;
> +
>  	mutex_lock(&drrs->drrs_mutex);
>  	if (panel->target_mode != NULL)
>  		DRM_ERROR("FIXME: We shouldn't be here\n");
> @@ -192,6 +221,11 @@ static void intel_enable_idleness_drrs(struct i915_drrs *drrs)
>  
>  	mutex_lock(&drrs->drrs_mutex);
>  
> +	drrs->is_clone = is_cloned_mode_active(drrs->connector->base.dev);
> +
> +	if (drrs->is_clone)
> +		return;
> +
>  	/* Capturing the deferred request for disable_drrs */
>  	if (drrs->drrs_state.type == SEAMLESS_DRRS_SUPPORT_SW &&
>  				drrs->encoder_ops->is_drrs_hr_state_pending) {
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions
  2015-06-26 13:51 ` [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions Ramalingam C
@ 2015-06-26 17:11   ` Daniel Vetter
  2015-06-29 14:58     ` Ramalingam C
  0 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2015-06-26 17:11 UTC (permalink / raw)
  To: Ramalingam C; +Cc: daniel.vetter, intel-gfx, rodrigo.vivi, paulo.r.zanoni

On Fri, Jun 26, 2015 at 07:21:55PM +0530, Ramalingam C wrote:
> During the DRRS state transitions we are modifying the clock and
> hence the vrefresh rate.
> 
> So we need to update the drm_crtc->mode and the adjusted
> mode in intel_crtc. So that watermark calculations will be as per the
> new modified clock.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drrs.c     |   14 ++++++++++++++
>  drivers/gpu/drm/i915/intel_dsi_drrs.c |   14 +++++++++++++-
>  2 files changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
> index 42b420d..2901832 100644
> --- a/drivers/gpu/drm/i915/intel_drrs.c
> +++ b/drivers/gpu/drm/i915/intel_drrs.c
> @@ -169,6 +169,20 @@ void intel_set_drrs_state(struct i915_drrs *drrs)
>  		 * If it is non-DSI encoders.
>  		 * As only DSI has SEAMLESS_DRRS_SUPPORT_SW.
>  		 */
> +		/*
> +		 * TODO: Protect the access to the crtc mode with corresponding
> +		 * mutex in case of Idleness DRRS. As media playback update
> +		 * will happen under crtc modeset lock protection
> +		 */
> +		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
> +		intel_crtc->base.mode.clock = target_mode->clock;
> +		intel_crtc->base.mode.vrefresh = target_mode->vrefresh;
> +		intel_crtc->config->base.adjusted_mode.clock =
> +							target_mode->clock;
> +		intel_crtc->config->base.adjusted_mode.vrefresh =
> +							target_mode->vrefresh;
> +		drm_modeset_unlock(&intel_crtc->base.mutex);

No. For video DRRS (i.e. changing the vrefresh rate to exactly what we
want to match media content) userspace needs to do a full modeset. Maarten
is working on infrastructure to avoid full modeset in some special mode
changes (to implement the fast pfit change from Jesse's original fastboot
work). And we can extend this to DRRS too.

For seamless&transparent DRRS we can still keep the current design with
effectively 2 dotclocks.

Also with atomic you can combine the clock change with the first video
frame which is double-awesome ;-)
-Daniel

> +
>  		drrs_state->current_rr_type = drrs_state->target_rr_type;
>  		DRM_INFO("Refresh Rate set to : %dHz\n", refresh_rate);
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
> index eb0758a..d4bb70a 100644
> --- a/drivers/gpu/drm/i915/intel_dsi_drrs.c
> +++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
> @@ -46,6 +46,7 @@ static void intel_mipi_drrs_work_fn(struct work_struct *__work)
>  	struct i915_drrs *drrs = work->drrs;
>  	struct intel_encoder *intel_encoder = drrs->connector->encoder;
>  	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
> +	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
>  	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
>  	struct dsi_mnp *dsi_mnp;
>  	struct drm_display_mode *prev_mode = NULL;
> @@ -69,11 +70,22 @@ retry:
>  		/* PLL Programming is successful */
>  		mutex_lock(&drrs->drrs_mutex);
>  		drrs->drrs_state.current_rr_type = work->target_rr_type;
> +
> +		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
> +		intel_crtc->base.mode.clock = work->target_mode->clock;
> +		intel_crtc->base.mode.vrefresh = work->target_mode->vrefresh;
> +		intel_crtc->config->base.adjusted_mode.clock =
> +						work->target_mode->clock;
> +		intel_crtc->config->base.adjusted_mode.vrefresh =
> +						work->target_mode->vrefresh;
> +		drm_modeset_unlock(&intel_crtc->base.mutex);
> +
>  		mutex_unlock(&drrs->drrs_mutex);
> +
>  		DRM_INFO("Refresh Rate set to : %dHz\n",
>  						work->target_mode->vrefresh);
>  
> -		/* TODO: Update crtc mode and drain ladency with watermark */
> +		/* TODO: Update drain ladency with watermark */
>  
>  	} else if (ret == -ETIMEDOUT && retry_cnt) {
>  
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 10/18] drm/i915: Initializing DRRS for all connectors
  2015-06-26 13:51 ` [RFC PATCH 10/18] drm/i915: Initializing DRRS for all connectors Ramalingam C
@ 2015-06-26 17:12   ` Daniel Vetter
  2015-06-29 14:52     ` Ramalingam C
  0 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2015-06-26 17:12 UTC (permalink / raw)
  To: Ramalingam C; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi

On Fri, Jun 26, 2015 at 07:21:54PM +0530, Ramalingam C wrote:
> For all the connectors drrs init is invoked. drrs_init will
> initialize the drrs for those connectors that support DRRS.
> 
> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c |    5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3f48917..0e8467c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -15021,6 +15021,7 @@ void intel_modeset_init(struct drm_device *dev)
>  	int sprite, ret;
>  	enum pipe pipe;
>  	struct intel_crtc *crtc;
> +	struct intel_connector *connector;
>  
>  	drm_mode_config_init(dev);
>  
> @@ -15090,6 +15091,10 @@ void intel_modeset_init(struct drm_device *dev)
>  	i915_disable_vga(dev);
>  	intel_setup_outputs(dev);
>  
> +	list_for_each_entry(connector, &dev->mode_config.connector_list,
> +								base.head)
> +		intel_drrs_init(dev, connector, connector->panel.fixed_mode);

We initialize all the panel stuff in respective encoder callbacks, this is
a layering violation. If we need to share more panel init code then that's
ok, but the call needs to be in the edp/dsi/lvds/whatever init functions.
-Daniel

> +
>  	/* Just in case the BIOS is doing something questionable. */
>  	intel_fbc_disable(dev);
>  
> -- 
> 1.7.9.5
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 09/18] drm/i915: Cloned mode check
  2015-06-26 17:08   ` Daniel Vetter
@ 2015-06-26 17:14     ` Chris Wilson
  2015-06-26 17:38       ` Daniel Vetter
  2015-06-29 11:48     ` Ramalingam C
  1 sibling, 1 reply; 36+ messages in thread
From: Chris Wilson @ 2015-06-26 17:14 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx, rodrigo.vivi, paulo.r.zanoni, daniel.vetter

On Fri, Jun 26, 2015 at 07:08:40PM +0200, Daniel Vetter wrote:
> On Fri, Jun 26, 2015 at 07:21:53PM +0530, Ramalingam C wrote:
> > If crtc is in clone mode, DRRS will be disabled. Because if the both
> > the displays are not sharing the same vrefresh, then userspace
> > activities based on vsync will go for toss.
> > 
> > Clone mode will be rechecked on every restarting Idleness DRRS events.
> > 
> > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_drrs.c |   36 +++++++++++++++++++++++++++++++++++-
> >  1 file changed, 35 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
> > index e5d8bcd..42b420d 100644
> > --- a/drivers/gpu/drm/i915/intel_drrs.c
> > +++ b/drivers/gpu/drm/i915/intel_drrs.c
> > @@ -16,6 +16,7 @@
> >  
> >  #include <drm/i915_drm.h>
> >  #include <linux/delay.h>
> > +#include <linux/list.h>
> >  
> >  #include "i915_drv.h"
> >  #include "intel_drv.h"
> > @@ -85,6 +86,31 @@ int get_free_drrs_struct_index(struct drm_i915_private *dev_priv)
> >  	return -EBUSY;
> >  }
> >  
> > +/*
> > + * TODO: This is identifying the multiple active crtcs at a time.
> > + * Here we assume that this is clone state and disable DRRS.
> > + * But need to implement a proper method to find the real cloned mode
> > + * state. DRRS need not be disabled incase of multiple crtcs with
> > + * different content.
> > + */
> 
> This is a pretty big hack. Why do you need it? fb tracking should keep any
> display in the high mode as long as there's activity, so as long as
> userspace flips both buffers for both pipes (which is should for cloned
> mode) they'll both be running at max.

It's simpler than than: cloned mode == 1 pipe, 1 framebuffer, 1 pageflip.

Does having a vblank_ref count as activity? There is a large body of
code (like OML_sync_control) that assumes a fixed refresh rate for an
output. (Though OML_sync_control is vague about multiple monitor setups
and ignore mode changed altogether.) 
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 00/18] Generic DRRS implementation across the encoders
  2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
                   ` (17 preceding siblings ...)
  2015-06-26 13:52 ` [RFC PATCH 18/18] drm/i915: Connector property for DRRS capability Ramalingam C
@ 2015-06-26 17:16 ` Daniel Vetter
  2015-06-29 11:22   ` Ramalingam C
  18 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2015-06-26 17:16 UTC (permalink / raw)
  To: Ramalingam C; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi

On Fri, Jun 26, 2015 at 07:21:44PM +0530, Ramalingam C wrote:
> Display Refresh Rate Switching (DRRS) is a power conservation feature
> which enables swtching between low and high refresh rates,
> dynamically, based on the usage scenario to save power.
> 
> This feature is applicable for internal panels.
> 
> Indication that the panel supports DRRS is given by the panel EDID, which
> would list multiple refresh rates for one resolution along with VBT fields
> like drrs_min_vrefresh.
> 
> DRRS is of 2 types - static and seamless.
> Static needs full modeset. Which can be used in docking and undocking
> scenarios.
> Seamless DRRS involves changing RR without any visual effect to the user
> and can be used during normal system usage. This is done by programming
> certain registers.
> 
> Support for static/seamless DRRS may be indicated in the VBT based on
> inputs from the panel spec.
> 
> We have implemented two DRRS use case scenrios :
> 1. Idleness DRRS,	2. Media playback DRRS (Content's FPS based)
> 
> Idleness DRRS:-
> 	The implementation is based on frontbuffer tracking implementation.
> When there is a disturbance on the screen triggered by user activity or a
> periodic system activity, DRRS is disabled (RR is changed to high RR).
> When there is no movement on screen, after a timeout, a switch
> to low RR is made.
> 	For integration with frontbuffer tracking code,
> intel_drrs_invalidate() and intel_drrs_flush() are called.
> 
> Media playback DRRS (Content's FPS based):
> 	Based on the content's Frames Per Second, minimum required vrefresh
> is called in userspace. If the panel supports the minimum required vrefresh
> and if the DRRS is supported on the platform, userspace will make a modeset
> request with same mode and FB but with different vrefresh.
> 	Panel's vrefresh range will be exposed through connector's modelist and
> connector property is created to expose the DRRS capability to the userspace.
> 
> 	In DRRS state machine Media plyabck DRRS holds the highest priority.
> Idleness DRRS is disabled as soon as Media playback DRRS is requested.
> Idleness DRRS is reenabled when the userspace indicates the exit of Media
> playback DRRS by requesting for highest vrefresh supported.
> 
> NOTE:
> 1. DRM documentation will be made once the RFC is closed along with IGT.
> 2. Currently in RFC, platform support is developed only for VLV.
>    it will be extended to other platform once the design is approved.
> 3. Basic design of DSI DRRS and Content based DRRS is functionally tested on
>    Android(VLV & CHT).

I've made a few drive-by comments, but big picture comments repeated here:
- Don't throw existing code away as in patch 1. When extending a
  feature/code, we'll refactor the existing stuff and keep it working all
  the time. Otherwise we invalidate all the previous testing, which throws
  out a lot of value.

- Static DRRS and generalized seamless DRRS are imo separate features and
  we should split the patch series. seamless DRRS is already implemented
  using the fb tracking, maybe extended with some hints to userspace.

  Static DRRS otoh is just a modeset with a different clock (plus a better
  internal implementation to avoid flicker). So from that pov two
  completely different features, both in the implementation and the
  userspace ABI.

- I guess we'll have a proper design discussion in internal mtgs about
  this too?

Thanks, Daniel
> 
> Ramalingam C (18):
>   drm/i915: Removing the eDP specific DRRS implementation
>   drm/i915: Generic DRRS state Machine
>   drm/i915: Addition of the drrs_min_vrefresh in VBT
>   drm/i915: Implementation of Generic DSI DRRS
>   drm/i915: Adjusting the pclk for dual link and burst mode
>   drm/i915: VLV dsi drrs support
>   drm/i915: Generic eDP DRRS implementation
>   drm/i915: VLV eDP DRRS methods
>   drm/i915: Cloned mode check
>   drm/i915: Initializing DRRS for all connectors
>   drm/i915: Updating the crtc modes in DRRS transitions
>   drm/i915: Redesigning dp_set_m_n to receive divider values
>   drm/i915: MEDIA_RR support in general DRRS state machine
>   drm/i915: MEDIA_RR support in eDP DRRS module
>   drm/i915: MEDIA_RR support in DSI DRRS module
>   drm/i915: Filtering media playback DRRS requests
>   drm/i915: Addition of downclock mode to connector modelist
>   drm/i915: Connector property for DRRS capability
> 
>  drivers/gpu/drm/i915/Makefile            |    3 +
>  drivers/gpu/drm/i915/i915_debugfs.c      |  110 -----
>  drivers/gpu/drm/i915/i915_drv.h          |   91 +++-
>  drivers/gpu/drm/i915/i915_reg.h          |    4 +
>  drivers/gpu/drm/i915/intel_bios.c        |    3 +
>  drivers/gpu/drm/i915/intel_bios.h        |    9 +-
>  drivers/gpu/drm/i915/intel_ddi.c         |    2 -
>  drivers/gpu/drm/i915/intel_display.c     |   57 ++-
>  drivers/gpu/drm/i915/intel_dp.c          |  397 +---------------
>  drivers/gpu/drm/i915/intel_drrs.c        |  728 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drrs.h        |   38 ++
>  drivers/gpu/drm/i915/intel_drv.h         |   45 +-
>  drivers/gpu/drm/i915/intel_dsi.c         |   29 +-
>  drivers/gpu/drm/i915/intel_dsi.h         |    3 +
>  drivers/gpu/drm/i915/intel_dsi_drrs.c    |  415 +++++++++++++++++
>  drivers/gpu/drm/i915/intel_dsi_drrs.h    |   66 +++
>  drivers/gpu/drm/i915/intel_dsi_pll.c     |  303 +++++++++++--
>  drivers/gpu/drm/i915/intel_edp_drrs.c    |  196 ++++++++
>  drivers/gpu/drm/i915/intel_edp_drrs.h    |   29 ++
>  drivers/gpu/drm/i915/intel_frontbuffer.c |    4 +-
>  drivers/gpu/drm/i915/intel_modes.c       |   28 ++
>  21 files changed, 1959 insertions(+), 601 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_drrs.c
>  create mode 100644 drivers/gpu/drm/i915/intel_drrs.h
>  create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.c
>  create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.h
>  create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.c
>  create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.h
> 
> -- 
> 1.7.9.5
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 09/18] drm/i915: Cloned mode check
  2015-06-26 17:14     ` Chris Wilson
@ 2015-06-26 17:38       ` Daniel Vetter
  0 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2015-06-26 17:38 UTC (permalink / raw)
  To: Chris Wilson, Daniel Vetter, Ramalingam C, intel-gfx,
	daniel.vetter, rodrigo.vivi, paulo.r.zanoni

On Fri, Jun 26, 2015 at 06:14:07PM +0100, Chris Wilson wrote:
> On Fri, Jun 26, 2015 at 07:08:40PM +0200, Daniel Vetter wrote:
> > On Fri, Jun 26, 2015 at 07:21:53PM +0530, Ramalingam C wrote:
> > > If crtc is in clone mode, DRRS will be disabled. Because if the both
> > > the displays are not sharing the same vrefresh, then userspace
> > > activities based on vsync will go for toss.
> > > 
> > > Clone mode will be rechecked on every restarting Idleness DRRS events.
> > > 
> > > Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_drrs.c |   36 +++++++++++++++++++++++++++++++++++-
> > >  1 file changed, 35 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
> > > index e5d8bcd..42b420d 100644
> > > --- a/drivers/gpu/drm/i915/intel_drrs.c
> > > +++ b/drivers/gpu/drm/i915/intel_drrs.c
> > > @@ -16,6 +16,7 @@
> > >  
> > >  #include <drm/i915_drm.h>
> > >  #include <linux/delay.h>
> > > +#include <linux/list.h>
> > >  
> > >  #include "i915_drv.h"
> > >  #include "intel_drv.h"
> > > @@ -85,6 +86,31 @@ int get_free_drrs_struct_index(struct drm_i915_private *dev_priv)
> > >  	return -EBUSY;
> > >  }
> > >  
> > > +/*
> > > + * TODO: This is identifying the multiple active crtcs at a time.
> > > + * Here we assume that this is clone state and disable DRRS.
> > > + * But need to implement a proper method to find the real cloned mode
> > > + * state. DRRS need not be disabled incase of multiple crtcs with
> > > + * different content.
> > > + */
> > 
> > This is a pretty big hack. Why do you need it? fb tracking should keep any
> > display in the high mode as long as there's activity, so as long as
> > userspace flips both buffers for both pipes (which is should for cloned
> > mode) they'll both be running at max.
> 
> It's simpler than than: cloned mode == 1 pipe, 1 framebuffer, 1 pageflip.
> 
> Does having a vblank_ref count as activity? There is a large body of
> code (like OML_sync_control) that assumes a fixed refresh rate for an
> output. (Though OML_sync_control is vague about multiple monitor setups
> and ignore mode changed altogether.) 

Atm we don't yet count vblank refcounts as activity, but would definitely
make tons of sense. Problem is that drm_irq.c is a mess, so for the
meantime I think we have to live with tuning the idleness timer of DRRS
such that for most timing critical apps it's long enough for them not to
notice the tricks we're playing.

And yeah fixing up drm_irq.c is somewhere on my list too - I want a proper
driver entry point for modeset drivers, where we could intercept vblank
waits and everything as we see fit. Last piece of modern drm that's still
midlayered (well ignoring that most drivers don't have a demidlayered
driver init yet).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 00/18] Generic DRRS implementation across the encoders
  2015-06-26 17:16 ` [RFC PATCH 00/18] Generic DRRS implementation across the encoders Daniel Vetter
@ 2015-06-29 11:22   ` Ramalingam C
  2015-06-29 16:27     ` Daniel Vetter
  0 siblings, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-29 11:22 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi


On Friday 26 June 2015 10:46 PM, Daniel Vetter wrote:
> On Fri, Jun 26, 2015 at 07:21:44PM +0530, Ramalingam C wrote:
>> Display Refresh Rate Switching (DRRS) is a power conservation feature
>> which enables swtching between low and high refresh rates,
>> dynamically, based on the usage scenario to save power.
>>
>> This feature is applicable for internal panels.
>>
>> Indication that the panel supports DRRS is given by the panel EDID, which
>> would list multiple refresh rates for one resolution along with VBT fields
>> like drrs_min_vrefresh.
>>
>> DRRS is of 2 types - static and seamless.
>> Static needs full modeset. Which can be used in docking and undocking
>> scenarios.
>> Seamless DRRS involves changing RR without any visual effect to the user
>> and can be used during normal system usage. This is done by programming
>> certain registers.
>>
>> Support for static/seamless DRRS may be indicated in the VBT based on
>> inputs from the panel spec.
>>
>> We have implemented two DRRS use case scenrios :
>> 1. Idleness DRRS,	2. Media playback DRRS (Content's FPS based)
>>
>> Idleness DRRS:-
>> 	The implementation is based on frontbuffer tracking implementation.
>> When there is a disturbance on the screen triggered by user activity or a
>> periodic system activity, DRRS is disabled (RR is changed to high RR).
>> When there is no movement on screen, after a timeout, a switch
>> to low RR is made.
>> 	For integration with frontbuffer tracking code,
>> intel_drrs_invalidate() and intel_drrs_flush() are called.
>>
>> Media playback DRRS (Content's FPS based):
>> 	Based on the content's Frames Per Second, minimum required vrefresh
>> is called in userspace. If the panel supports the minimum required vrefresh
>> and if the DRRS is supported on the platform, userspace will make a modeset
>> request with same mode and FB but with different vrefresh.
>> 	Panel's vrefresh range will be exposed through connector's modelist and
>> connector property is created to expose the DRRS capability to the userspace.
>>
>> 	In DRRS state machine Media plyabck DRRS holds the highest priority.
>> Idleness DRRS is disabled as soon as Media playback DRRS is requested.
>> Idleness DRRS is reenabled when the userspace indicates the exit of Media
>> playback DRRS by requesting for highest vrefresh supported.
>>
>> NOTE:
>> 1. DRM documentation will be made once the RFC is closed along with IGT.
>> 2. Currently in RFC, platform support is developed only for VLV.
>>     it will be extended to other platform once the design is approved.
>> 3. Basic design of DSI DRRS and Content based DRRS is functionally tested on
>>     Android(VLV & CHT).
Daniel.

First of all Thank you so much for your comments.
Sorry for such a huge patch series. Tolerate me on that one.

> I've made a few drive-by comments, but big picture comments repeated here:
> - Don't throw existing code away as in patch 1. When extending a
>    feature/code, we'll refactor the existing stuff and keep it working all
>    the time. Otherwise we invalidate all the previous testing, which throws
>    out a lot of value.
Ok agreed. I will work on this comment. And will bring the current 
existing eDP DRRS code to the generic design,
retaining the bug fixes we have done.
>
> - Static DRRS and generalized seamless DRRS are imo separate features and
>    we should split the patch series. seamless DRRS is already implemented
>    using the fb tracking, maybe extended with some hints to userspace.
>
>    Static DRRS otoh is just a modeset with a different clock (plus a better
>    internal implementation to avoid flicker). So from that pov two
>    completely different features, both in the implementation and the
>    userspace ABI.
Yup. Static is not even in our development radar :). All the code that I 
have shared is
concerned only with seamless DRRS and it's two usecase scenarios( 
Idleness and Content based).
Mentioned the Static DRRS in cover letter, just to give the two 
different DRRS supports available in general.
>
> - I guess we'll have a proper design discussion in internal mtgs about
>    this too?
Sure Daniel we will have one.
>
> Thanks, Daniel
>> Ramalingam C (18):
>>    drm/i915: Removing the eDP specific DRRS implementation
>>    drm/i915: Generic DRRS state Machine
>>    drm/i915: Addition of the drrs_min_vrefresh in VBT
>>    drm/i915: Implementation of Generic DSI DRRS
>>    drm/i915: Adjusting the pclk for dual link and burst mode
>>    drm/i915: VLV dsi drrs support
>>    drm/i915: Generic eDP DRRS implementation
>>    drm/i915: VLV eDP DRRS methods
>>    drm/i915: Cloned mode check
>>    drm/i915: Initializing DRRS for all connectors
>>    drm/i915: Updating the crtc modes in DRRS transitions
>>    drm/i915: Redesigning dp_set_m_n to receive divider values
>>    drm/i915: MEDIA_RR support in general DRRS state machine
>>    drm/i915: MEDIA_RR support in eDP DRRS module
>>    drm/i915: MEDIA_RR support in DSI DRRS module
>>    drm/i915: Filtering media playback DRRS requests
>>    drm/i915: Addition of downclock mode to connector modelist
>>    drm/i915: Connector property for DRRS capability
>>
>>   drivers/gpu/drm/i915/Makefile            |    3 +
>>   drivers/gpu/drm/i915/i915_debugfs.c      |  110 -----
>>   drivers/gpu/drm/i915/i915_drv.h          |   91 +++-
>>   drivers/gpu/drm/i915/i915_reg.h          |    4 +
>>   drivers/gpu/drm/i915/intel_bios.c        |    3 +
>>   drivers/gpu/drm/i915/intel_bios.h        |    9 +-
>>   drivers/gpu/drm/i915/intel_ddi.c         |    2 -
>>   drivers/gpu/drm/i915/intel_display.c     |   57 ++-
>>   drivers/gpu/drm/i915/intel_dp.c          |  397 +---------------
>>   drivers/gpu/drm/i915/intel_drrs.c        |  728 ++++++++++++++++++++++++++++++
>>   drivers/gpu/drm/i915/intel_drrs.h        |   38 ++
>>   drivers/gpu/drm/i915/intel_drv.h         |   45 +-
>>   drivers/gpu/drm/i915/intel_dsi.c         |   29 +-
>>   drivers/gpu/drm/i915/intel_dsi.h         |    3 +
>>   drivers/gpu/drm/i915/intel_dsi_drrs.c    |  415 +++++++++++++++++
>>   drivers/gpu/drm/i915/intel_dsi_drrs.h    |   66 +++
>>   drivers/gpu/drm/i915/intel_dsi_pll.c     |  303 +++++++++++--
>>   drivers/gpu/drm/i915/intel_edp_drrs.c    |  196 ++++++++
>>   drivers/gpu/drm/i915/intel_edp_drrs.h    |   29 ++
>>   drivers/gpu/drm/i915/intel_frontbuffer.c |    4 +-
>>   drivers/gpu/drm/i915/intel_modes.c       |   28 ++
>>   21 files changed, 1959 insertions(+), 601 deletions(-)
>>   create mode 100644 drivers/gpu/drm/i915/intel_drrs.c
>>   create mode 100644 drivers/gpu/drm/i915/intel_drrs.h
>>   create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.c
>>   create mode 100644 drivers/gpu/drm/i915/intel_dsi_drrs.h
>>   create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.c
>>   create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.h
>>
>> -- 
>> 1.7.9.5
>>
-- Thanks,
Ram
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation
  2015-06-26 16:50   ` Daniel Vetter
@ 2015-06-29 11:24     ` Ramalingam C
  0 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-29 11:24 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi


On Friday 26 June 2015 10:20 PM, Daniel Vetter wrote:
> On Fri, Jun 26, 2015 at 07:21:45PM +0530, Ramalingam C wrote:
>> EDP specific DRRS implementation is removed to implement a
>> generic DRRS stack extentable accross the supportable encoders.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> Nack. You don't make something generic by first throwing out the existing
> solution (and all the lessons learned implementing that).
>
> Instead convert the edp DRRS implementation over to use generic
> structures, step-by-step, and then once that's done it should be simply to
> implement DRRS for other outputs.
Sure agreed. We will make the existing code as generic and implement for 
other encoders too.
I will work on that. thanks.
> -Daniel
>
>> ---
>>   drivers/gpu/drm/i915/i915_debugfs.c      |  110 ---------
>>   drivers/gpu/drm/i915/i915_drv.h          |   22 --
>>   drivers/gpu/drm/i915/intel_ddi.c         |    2 -
>>   drivers/gpu/drm/i915/intel_dp.c          |  392 ------------------------------
>>   drivers/gpu/drm/i915/intel_drv.h         |    5 -
>>   drivers/gpu/drm/i915/intel_frontbuffer.c |    2 -
>>   6 files changed, 533 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> index c49fe2a..7dbf170 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -2962,115 +2962,6 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
>>   	return 0;
>>   }
>>   
>> -static void drrs_status_per_crtc(struct seq_file *m,
>> -		struct drm_device *dev, struct intel_crtc *intel_crtc)
>> -{
>> -	struct intel_encoder *intel_encoder;
>> -	struct drm_i915_private *dev_priv = dev->dev_private;
>> -	struct i915_drrs *drrs = &dev_priv->drrs;
>> -	int vrefresh = 0;
>> -
>> -	for_each_encoder_on_crtc(dev, &intel_crtc->base, intel_encoder) {
>> -		/* Encoder connected on this CRTC */
>> -		switch (intel_encoder->type) {
>> -		case INTEL_OUTPUT_EDP:
>> -			seq_puts(m, "eDP:\n");
>> -			break;
>> -		case INTEL_OUTPUT_DSI:
>> -			seq_puts(m, "DSI:\n");
>> -			break;
>> -		case INTEL_OUTPUT_HDMI:
>> -			seq_puts(m, "HDMI:\n");
>> -			break;
>> -		case INTEL_OUTPUT_DISPLAYPORT:
>> -			seq_puts(m, "DP:\n");
>> -			break;
>> -		default:
>> -			seq_printf(m, "Other encoder (id=%d).\n",
>> -						intel_encoder->type);
>> -			return;
>> -		}
>> -	}
>> -
>> -	if (dev_priv->vbt.drrs_type == STATIC_DRRS_SUPPORT)
>> -		seq_puts(m, "\tVBT: DRRS_type: Static");
>> -	else if (dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT)
>> -		seq_puts(m, "\tVBT: DRRS_type: Seamless");
>> -	else if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED)
>> -		seq_puts(m, "\tVBT: DRRS_type: None");
>> -	else
>> -		seq_puts(m, "\tVBT: DRRS_type: FIXME: Unrecognized Value");
>> -
>> -	seq_puts(m, "\n\n");
>> -
>> -	if (to_intel_crtc_state(intel_crtc->base.state)->has_drrs) {
>> -		struct intel_panel *panel;
>> -
>> -		mutex_lock(&drrs->mutex);
>> -		/* DRRS Supported */
>> -		seq_puts(m, "\tDRRS Supported: Yes\n");
>> -
>> -		/* disable_drrs() will make drrs->dp NULL */
>> -		if (!drrs->dp) {
>> -			seq_puts(m, "Idleness DRRS: Disabled");
>> -			mutex_unlock(&drrs->mutex);
>> -			return;
>> -		}
>> -
>> -		panel = &drrs->dp->attached_connector->panel;
>> -		seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X",
>> -					drrs->busy_frontbuffer_bits);
>> -
>> -		seq_puts(m, "\n\t\t");
>> -		if (drrs->refresh_rate_type == DRRS_HIGH_RR) {
>> -			seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n");
>> -			vrefresh = panel->fixed_mode->vrefresh;
>> -		} else if (drrs->refresh_rate_type == DRRS_LOW_RR) {
>> -			seq_puts(m, "DRRS_State: DRRS_LOW_RR\n");
>> -			vrefresh = panel->downclock_mode->vrefresh;
>> -		} else {
>> -			seq_printf(m, "DRRS_State: Unknown(%d)\n",
>> -						drrs->refresh_rate_type);
>> -			mutex_unlock(&drrs->mutex);
>> -			return;
>> -		}
>> -		seq_printf(m, "\t\tVrefresh: %d", vrefresh);
>> -
>> -		seq_puts(m, "\n\t\t");
>> -		mutex_unlock(&drrs->mutex);
>> -	} else {
>> -		/* DRRS not supported. Print the VBT parameter*/
>> -		seq_puts(m, "\tDRRS Supported : No");
>> -	}
>> -	seq_puts(m, "\n");
>> -}
>> -
>> -static int i915_drrs_status(struct seq_file *m, void *unused)
>> -{
>> -	struct drm_info_node *node = m->private;
>> -	struct drm_device *dev = node->minor->dev;
>> -	struct intel_crtc *intel_crtc;
>> -	int active_crtc_cnt = 0;
>> -
>> -	for_each_intel_crtc(dev, intel_crtc) {
>> -		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
>> -
>> -		if (intel_crtc->base.state->active) {
>> -			active_crtc_cnt++;
>> -			seq_printf(m, "\nCRTC %d:  ", active_crtc_cnt);
>> -
>> -			drrs_status_per_crtc(m, dev, intel_crtc);
>> -		}
>> -
>> -		drm_modeset_unlock(&intel_crtc->base.mutex);
>> -	}
>> -
>> -	if (!active_crtc_cnt)
>> -		seq_puts(m, "No active crtc found\n");
>> -
>> -	return 0;
>> -}
>> -
>>   struct pipe_crc_info {
>>   	const char *name;
>>   	struct drm_device *dev;
>> @@ -5048,7 +4939,6 @@ static const struct drm_info_list i915_debugfs_list[] = {
>>   	{"i915_wa_registers", i915_wa_registers, 0},
>>   	{"i915_ddb_info", i915_ddb_info, 0},
>>   	{"i915_sseu_status", i915_sseu_status, 0},
>> -	{"i915_drrs_status", i915_drrs_status, 0},
>>   	{"i915_rps_boost_info", i915_rps_boost_info, 0},
>>   };
>>   #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 491ef0c..922dd68 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -930,33 +930,12 @@ struct i915_fbc {
>>   	} no_fbc_reason;
>>   };
>>   
>> -/**
>> - * HIGH_RR is the highest eDP panel refresh rate read from EDID
>> - * LOW_RR is the lowest eDP panel refresh rate found from EDID
>> - * parsing for same resolution.
>> - */
>> -enum drrs_refresh_rate_type {
>> -	DRRS_HIGH_RR,
>> -	DRRS_LOW_RR,
>> -	DRRS_MAX_RR, /* RR count */
>> -};
>> -
>>   enum drrs_support_type {
>>   	DRRS_NOT_SUPPORTED = 0,
>>   	STATIC_DRRS_SUPPORT = 1,
>>   	SEAMLESS_DRRS_SUPPORT = 2
>>   };
>>   
>> -struct intel_dp;
>> -struct i915_drrs {
>> -	struct mutex mutex;
>> -	struct delayed_work work;
>> -	struct intel_dp *dp;
>> -	unsigned busy_frontbuffer_bits;
>> -	enum drrs_refresh_rate_type refresh_rate_type;
>> -	enum drrs_support_type type;
>> -};
>> -
>>   struct i915_psr {
>>   	struct mutex lock;
>>   	bool sink_support;
>> @@ -1718,7 +1697,6 @@ struct drm_i915_private {
>>   
>>   	struct i915_hotplug hotplug;
>>   	struct i915_fbc fbc;
>> -	struct i915_drrs drrs;
>>   	struct intel_opregion opregion;
>>   	struct intel_vbt_data vbt;
>>   
>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>> index 31b29e8..75afbd7 100644
>> --- a/drivers/gpu/drm/i915/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
>> @@ -2012,7 +2012,6 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
>>   
>>   		intel_edp_backlight_on(intel_dp);
>>   		intel_psr_enable(intel_dp);
>> -		intel_edp_drrs_enable(intel_dp);
>>   	}
>>   
>>   	if (intel_crtc->config->has_audio) {
>> @@ -2038,7 +2037,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
>>   	if (type == INTEL_OUTPUT_EDP) {
>>   		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>>   
>> -		intel_edp_drrs_disable(intel_dp);
>>   		intel_psr_disable(intel_dp);
>>   		intel_edp_backlight_off(intel_dp);
>>   	}
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index f52eef1..738e98e 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -1483,15 +1483,6 @@ found:
>>   			       pipe_config->port_clock,
>>   			       &pipe_config->dp_m_n);
>>   
>> -	if (intel_connector->panel.downclock_mode != NULL &&
>> -		dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) {
>> -			pipe_config->has_drrs = true;
>> -			intel_link_compute_m_n(bpp, lane_count,
>> -				intel_connector->panel.downclock_mode->clock,
>> -				pipe_config->port_clock,
>> -				&pipe_config->dp_m2_n2);
>> -	}
>> -
>>   	if (IS_SKYLAKE(dev) && is_edp(intel_dp))
>>   		skl_edp_set_pll_config(pipe_config, common_rates[clock]);
>>   	else if (IS_BROXTON(dev))
>> @@ -5254,387 +5245,6 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>>   		      I915_READ(pp_div_reg));
>>   }
>>   
>> -/**
>> - * intel_dp_set_drrs_state - program registers for RR switch to take effect
>> - * @dev: DRM device
>> - * @refresh_rate: RR to be programmed
>> - *
>> - * This function gets called when refresh rate (RR) has to be changed from
>> - * one frequency to another. Switches can be between high and low RR
>> - * supported by the panel or to any other RR based on media playback (in
>> - * this case, RR value needs to be passed from user space).
>> - *
>> - * The caller of this function needs to take a lock on dev_priv->drrs.
>> - */
>> -static void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
>> -{
>> -	struct drm_i915_private *dev_priv = dev->dev_private;
>> -	struct intel_encoder *encoder;
>> -	struct intel_digital_port *dig_port = NULL;
>> -	struct intel_dp *intel_dp = dev_priv->drrs.dp;
>> -	struct intel_crtc_state *config = NULL;
>> -	struct intel_crtc *intel_crtc = NULL;
>> -	u32 reg, val;
>> -	enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
>> -
>> -	if (refresh_rate <= 0) {
>> -		DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n");
>> -		return;
>> -	}
>> -
>> -	if (intel_dp == NULL) {
>> -		DRM_DEBUG_KMS("DRRS not supported.\n");
>> -		return;
>> -	}
>> -
>> -	/*
>> -	 * FIXME: This needs proper synchronization with psr state for some
>> -	 * platforms that cannot have PSR and DRRS enabled at the same time.
>> -	 */
>> -
>> -	dig_port = dp_to_dig_port(intel_dp);
>> -	encoder = &dig_port->base;
>> -	intel_crtc = to_intel_crtc(encoder->base.crtc);
>> -
>> -	if (!intel_crtc) {
>> -		DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
>> -		return;
>> -	}
>> -
>> -	config = intel_crtc->config;
>> -
>> -	if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
>> -		DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
>> -		return;
>> -	}
>> -
>> -	if (intel_dp->attached_connector->panel.downclock_mode->vrefresh ==
>> -			refresh_rate)
>> -		index = DRRS_LOW_RR;
>> -
>> -	if (index == dev_priv->drrs.refresh_rate_type) {
>> -		DRM_DEBUG_KMS(
>> -			"DRRS requested for previously set RR...ignoring\n");
>> -		return;
>> -	}
>> -
>> -	if (!intel_crtc->active) {
>> -		DRM_DEBUG_KMS("eDP encoder disabled. CRTC not Active\n");
>> -		return;
>> -	}
>> -
>> -	if (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev)) {
>> -		switch (index) {
>> -		case DRRS_HIGH_RR:
>> -			intel_dp_set_m_n(intel_crtc, M1_N1);
>> -			break;
>> -		case DRRS_LOW_RR:
>> -			intel_dp_set_m_n(intel_crtc, M2_N2);
>> -			break;
>> -		case DRRS_MAX_RR:
>> -		default:
>> -			DRM_ERROR("Unsupported refreshrate type\n");
>> -		}
>> -	} else if (INTEL_INFO(dev)->gen > 6) {
>> -		reg = PIPECONF(intel_crtc->config->cpu_transcoder);
>> -		val = I915_READ(reg);
>> -
>> -		if (index > DRRS_HIGH_RR) {
>> -			if (IS_VALLEYVIEW(dev))
>> -				val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
>> -			else
>> -				val |= PIPECONF_EDP_RR_MODE_SWITCH;
>> -		} else {
>> -			if (IS_VALLEYVIEW(dev))
>> -				val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
>> -			else
>> -				val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
>> -		}
>> -		I915_WRITE(reg, val);
>> -	}
>> -
>> -	dev_priv->drrs.refresh_rate_type = index;
>> -
>> -	DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
>> -}
>> -
>> -/**
>> - * intel_edp_drrs_enable - init drrs struct if supported
>> - * @intel_dp: DP struct
>> - *
>> - * Initializes frontbuffer_bits and drrs.dp
>> - */
>> -void intel_edp_drrs_enable(struct intel_dp *intel_dp)
>> -{
>> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> -	struct drm_i915_private *dev_priv = dev->dev_private;
>> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>> -	struct drm_crtc *crtc = dig_port->base.base.crtc;
>> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> -
>> -	if (!intel_crtc->config->has_drrs) {
>> -		DRM_DEBUG_KMS("Panel doesn't support DRRS\n");
>> -		return;
>> -	}
>> -
>> -	mutex_lock(&dev_priv->drrs.mutex);
>> -	if (WARN_ON(dev_priv->drrs.dp)) {
>> -		DRM_ERROR("DRRS already enabled\n");
>> -		goto unlock;
>> -	}
>> -
>> -	dev_priv->drrs.busy_frontbuffer_bits = 0;
>> -
>> -	dev_priv->drrs.dp = intel_dp;
>> -
>> -unlock:
>> -	mutex_unlock(&dev_priv->drrs.mutex);
>> -}
>> -
>> -/**
>> - * intel_edp_drrs_disable - Disable DRRS
>> - * @intel_dp: DP struct
>> - *
>> - */
>> -void intel_edp_drrs_disable(struct intel_dp *intel_dp)
>> -{
>> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> -	struct drm_i915_private *dev_priv = dev->dev_private;
>> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>> -	struct drm_crtc *crtc = dig_port->base.base.crtc;
>> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> -
>> -	if (!intel_crtc->config->has_drrs)
>> -		return;
>> -
>> -	mutex_lock(&dev_priv->drrs.mutex);
>> -	if (!dev_priv->drrs.dp) {
>> -		mutex_unlock(&dev_priv->drrs.mutex);
>> -		return;
>> -	}
>> -
>> -	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
>> -		intel_dp_set_drrs_state(dev_priv->dev,
>> -			intel_dp->attached_connector->panel.
>> -			fixed_mode->vrefresh);
>> -
>> -	dev_priv->drrs.dp = NULL;
>> -	mutex_unlock(&dev_priv->drrs.mutex);
>> -
>> -	cancel_delayed_work_sync(&dev_priv->drrs.work);
>> -}
>> -
>> -static void intel_edp_drrs_downclock_work(struct work_struct *work)
>> -{
>> -	struct drm_i915_private *dev_priv =
>> -		container_of(work, typeof(*dev_priv), drrs.work.work);
>> -	struct intel_dp *intel_dp;
>> -
>> -	mutex_lock(&dev_priv->drrs.mutex);
>> -
>> -	intel_dp = dev_priv->drrs.dp;
>> -
>> -	if (!intel_dp)
>> -		goto unlock;
>> -
>> -	/*
>> -	 * The delayed work can race with an invalidate hence we need to
>> -	 * recheck.
>> -	 */
>> -
>> -	if (dev_priv->drrs.busy_frontbuffer_bits)
>> -		goto unlock;
>> -
>> -	if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR)
>> -		intel_dp_set_drrs_state(dev_priv->dev,
>> -			intel_dp->attached_connector->panel.
>> -			downclock_mode->vrefresh);
>> -
>> -unlock:
>> -	mutex_unlock(&dev_priv->drrs.mutex);
>> -}
>> -
>> -/**
>> - * intel_edp_drrs_invalidate - Disable Idleness DRRS
>> - * @dev: DRM device
>> - * @frontbuffer_bits: frontbuffer plane tracking bits
>> - *
>> - * This function gets called everytime rendering on the given planes start.
>> - * Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
>> - *
>> - * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
>> - */
>> -void intel_edp_drrs_invalidate(struct drm_device *dev,
>> -		unsigned frontbuffer_bits)
>> -{
>> -	struct drm_i915_private *dev_priv = dev->dev_private;
>> -	struct drm_crtc *crtc;
>> -	enum pipe pipe;
>> -
>> -	if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
>> -		return;
>> -
>> -	cancel_delayed_work(&dev_priv->drrs.work);
>> -
>> -	mutex_lock(&dev_priv->drrs.mutex);
>> -	if (!dev_priv->drrs.dp) {
>> -		mutex_unlock(&dev_priv->drrs.mutex);
>> -		return;
>> -	}
>> -
>> -	crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
>> -	pipe = to_intel_crtc(crtc)->pipe;
>> -
>> -	/* invalidate means busy screen hence upclock */
>> -	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
>> -		intel_dp_set_drrs_state(dev_priv->dev,
>> -				dev_priv->drrs.dp->attached_connector->panel.
>> -				fixed_mode->vrefresh);
>> -	}
>> -
>> -	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
>> -
>> -	dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
>> -	mutex_unlock(&dev_priv->drrs.mutex);
>> -}
>> -
>> -/**
>> - * intel_edp_drrs_flush - Restart Idleness DRRS
>> - * @dev: DRM device
>> - * @frontbuffer_bits: frontbuffer plane tracking bits
>> - *
>> - * This function gets called every time rendering on the given planes has
>> - * completed or flip on a crtc is completed. So DRRS should be upclocked
>> - * (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
>> - * if no other planes are dirty.
>> - *
>> - * Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
>> - */
>> -void intel_edp_drrs_flush(struct drm_device *dev,
>> -		unsigned frontbuffer_bits)
>> -{
>> -	struct drm_i915_private *dev_priv = dev->dev_private;
>> -	struct drm_crtc *crtc;
>> -	enum pipe pipe;
>> -
>> -	if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
>> -		return;
>> -
>> -	cancel_delayed_work(&dev_priv->drrs.work);
>> -
>> -	mutex_lock(&dev_priv->drrs.mutex);
>> -	if (!dev_priv->drrs.dp) {
>> -		mutex_unlock(&dev_priv->drrs.mutex);
>> -		return;
>> -	}
>> -
>> -	crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
>> -	pipe = to_intel_crtc(crtc)->pipe;
>> -	dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
>> -
>> -	/* flush means busy screen hence upclock */
>> -	if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
>> -		intel_dp_set_drrs_state(dev_priv->dev,
>> -				dev_priv->drrs.dp->attached_connector->panel.
>> -				fixed_mode->vrefresh);
>> -
>> -	/*
>> -	 * flush also means no more activity hence schedule downclock, if all
>> -	 * other fbs are quiescent too
>> -	 */
>> -	if (!dev_priv->drrs.busy_frontbuffer_bits)
>> -		schedule_delayed_work(&dev_priv->drrs.work,
>> -				msecs_to_jiffies(1000));
>> -	mutex_unlock(&dev_priv->drrs.mutex);
>> -}
>> -
>> -/**
>> - * DOC: Display Refresh Rate Switching (DRRS)
>> - *
>> - * Display Refresh Rate Switching (DRRS) is a power conservation feature
>> - * which enables swtching between low and high refresh rates,
>> - * dynamically, based on the usage scenario. This feature is applicable
>> - * for internal panels.
>> - *
>> - * Indication that the panel supports DRRS is given by the panel EDID, which
>> - * would list multiple refresh rates for one resolution.
>> - *
>> - * DRRS is of 2 types - static and seamless.
>> - * Static DRRS involves changing refresh rate (RR) by doing a full modeset
>> - * (may appear as a blink on screen) and is used in dock-undock scenario.
>> - * Seamless DRRS involves changing RR without any visual effect to the user
>> - * and can be used during normal system usage. This is done by programming
>> - * certain registers.
>> - *
>> - * Support for static/seamless DRRS may be indicated in the VBT based on
>> - * inputs from the panel spec.
>> - *
>> - * DRRS saves power by switching to low RR based on usage scenarios.
>> - *
>> - * eDP DRRS:-
>> - *        The implementation is based on frontbuffer tracking implementation.
>> - * When there is a disturbance on the screen triggered by user activity or a
>> - * periodic system activity, DRRS is disabled (RR is changed to high RR).
>> - * When there is no movement on screen, after a timeout of 1 second, a switch
>> - * to low RR is made.
>> - *        For integration with frontbuffer tracking code,
>> - * intel_edp_drrs_invalidate() and intel_edp_drrs_flush() are called.
>> - *
>> - * DRRS can be further extended to support other internal panels and also
>> - * the scenario of video playback wherein RR is set based on the rate
>> - * requested by userspace.
>> - */
>> -
>> -/**
>> - * intel_dp_drrs_init - Init basic DRRS work and mutex.
>> - * @intel_connector: eDP connector
>> - * @fixed_mode: preferred mode of panel
>> - *
>> - * This function is  called only once at driver load to initialize basic
>> - * DRRS stuff.
>> - *
>> - * Returns:
>> - * Downclock mode if panel supports it, else return NULL.
>> - * DRRS support is determined by the presence of downclock mode (apart
>> - * from VBT setting).
>> - */
>> -static struct drm_display_mode *
>> -intel_dp_drrs_init(struct intel_connector *intel_connector,
>> -		struct drm_display_mode *fixed_mode)
>> -{
>> -	struct drm_connector *connector = &intel_connector->base;
>> -	struct drm_device *dev = connector->dev;
>> -	struct drm_i915_private *dev_priv = dev->dev_private;
>> -	struct drm_display_mode *downclock_mode = NULL;
>> -
>> -	INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
>> -	mutex_init(&dev_priv->drrs.mutex);
>> -
>> -	if (INTEL_INFO(dev)->gen <= 6) {
>> -		DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
>> -		return NULL;
>> -	}
>> -
>> -	if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
>> -		DRM_DEBUG_KMS("VBT doesn't support DRRS\n");
>> -		return NULL;
>> -	}
>> -
>> -	downclock_mode = intel_find_panel_downclock
>> -					(dev, fixed_mode, connector);
>> -
>> -	if (!downclock_mode) {
>> -		DRM_DEBUG_KMS("Downclock mode is not found. DRRS not supported\n");
>> -		return NULL;
>> -	}
>> -
>> -	dev_priv->drrs.type = dev_priv->vbt.drrs_type;
>> -
>> -	dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
>> -	DRM_DEBUG_KMS("seamless DRRS supported for eDP panel.\n");
>> -	return downclock_mode;
>> -}
>> -
>>   static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>>   				     struct intel_connector *intel_connector)
>>   {
>> @@ -5696,8 +5306,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>>   	list_for_each_entry(scan, &connector->probed_modes, head) {
>>   		if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
>>   			fixed_mode = drm_mode_duplicate(dev, scan);
>> -			downclock_mode = intel_dp_drrs_init(
>> -						intel_connector, fixed_mode);
>>   			break;
>>   		}
>>   	}
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index bcafefc..e2f534a 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -1198,11 +1198,6 @@ void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
>>   void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
>>   uint32_t intel_dp_pack_aux(const uint8_t *src, int src_bytes);
>>   void intel_plane_destroy(struct drm_plane *plane);
>> -void intel_edp_drrs_enable(struct intel_dp *intel_dp);
>> -void intel_edp_drrs_disable(struct intel_dp *intel_dp);
>> -void intel_edp_drrs_invalidate(struct drm_device *dev,
>> -		unsigned frontbuffer_bits);
>> -void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
>>   
>>   /* intel_dp_mst.c */
>>   int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
>> diff --git a/drivers/gpu/drm/i915/intel_frontbuffer.c b/drivers/gpu/drm/i915/intel_frontbuffer.c
>> index 57095f5..249d0b3 100644
>> --- a/drivers/gpu/drm/i915/intel_frontbuffer.c
>> +++ b/drivers/gpu/drm/i915/intel_frontbuffer.c
>> @@ -154,7 +154,6 @@ void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
>>   	intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
>>   
>>   	intel_psr_invalidate(dev, obj->frontbuffer_bits);
>> -	intel_edp_drrs_invalidate(dev, obj->frontbuffer_bits);
>>   	intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin);
>>   }
>>   
>> @@ -181,7 +180,6 @@ void intel_frontbuffer_flush(struct drm_device *dev,
>>   
>>   	intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
>>   
>> -	intel_edp_drrs_flush(dev, frontbuffer_bits);
>>   	intel_psr_flush(dev, frontbuffer_bits);
>>   	intel_fbc_flush(dev_priv, frontbuffer_bits);
>>   }
>> -- 
>> 1.7.9.5
>>

-- 
Thanks,
--Ram

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 09/18] drm/i915: Cloned mode check
  2015-06-26 17:08   ` Daniel Vetter
  2015-06-26 17:14     ` Chris Wilson
@ 2015-06-29 11:48     ` Ramalingam C
  2015-06-29 16:16       ` Daniel Vetter
  1 sibling, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-29 11:48 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: daniel.vetter, intel-gfx, rodrigo.vivi, paulo.r.zanoni


On Friday 26 June 2015 10:38 PM, Daniel Vetter wrote:
> On Fri, Jun 26, 2015 at 07:21:53PM +0530, Ramalingam C wrote:
>> If crtc is in clone mode, DRRS will be disabled. Because if the both
>> the displays are not sharing the same vrefresh, then userspace
>> activities based on vsync will go for toss.
>>
>> Clone mode will be rechecked on every restarting Idleness DRRS events.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_drrs.c |   36 +++++++++++++++++++++++++++++++++++-
>>   1 file changed, 35 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
>> index e5d8bcd..42b420d 100644
>> --- a/drivers/gpu/drm/i915/intel_drrs.c
>> +++ b/drivers/gpu/drm/i915/intel_drrs.c
>> @@ -16,6 +16,7 @@
>>   
>>   #include <drm/i915_drm.h>
>>   #include <linux/delay.h>
>> +#include <linux/list.h>
>>   
>>   #include "i915_drv.h"
>>   #include "intel_drv.h"
>> @@ -85,6 +86,31 @@ int get_free_drrs_struct_index(struct drm_i915_private *dev_priv)
>>   	return -EBUSY;
>>   }
>>   
>> +/*
>> + * TODO: This is identifying the multiple active crtcs at a time.
>> + * Here we assume that this is clone state and disable DRRS.
>> + * But need to implement a proper method to find the real cloned mode
>> + * state. DRRS need not be disabled incase of multiple crtcs with
>> + * different content.
>> + */
> This is a pretty big hack. Why do you need it? fb tracking should keep any
> display in the high mode as long as there's activity, so as long as
> userspace flips both buffers for both pipes (which is should for cloned
> mode) they'll both be running at max.
Yup. This is not needed for Idleness as fb tracking will keep the DRRS 
at High refresh rate.
But at content based DRRS, we had some concern from android Userspace 
team that we cant
support content based DRRS for cloned modes (eDP + HDMI or DSI + HDMI).

Of course at this point in time, we can enable the DRRS for all 
scenarios and test. Based on results we can plan ahead.

>
> And for non-cloned mode (e.g. video only on external TV) things will be
> controlled independantly.
>
> Smells a lot like trying to encode policy instead of making sure that the
> resulting behaviour matches what we want. And I think it should already.
> -Daniel
>
>> +
>> +bool is_cloned_mode_active(struct drm_device *dev)
>> +{
>> +	struct drm_crtc *crtc = NULL, *tmp_crtc;
>> +
>> +	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
>> +		if (crtc && intel_crtc_active(tmp_crtc)) {
>> +			DRM_DEBUG_KMS(
>> +			"more than one crtc active. Declared as clonec mode\n");
>> +			return true;
>> +		}
>> +
>> +		if (intel_crtc_active(tmp_crtc))
>> +			crtc = tmp_crtc;
>> +	}
>> +	return false;
>> +}
>> +
>>   void intel_set_drrs_state(struct i915_drrs *drrs)
>>   {
>>   	struct drrs_info *drrs_state;
>> @@ -158,7 +184,10 @@ static void intel_idleness_drrs_work_fn(struct work_struct *__work)
>>   
>>   	panel = &drrs->connector->panel;
>>   
>> -	/* TODO: If DRRS is not supported on clone mode act here */
>> +	/* Double check if the dual-display mode is active. */
>> +	if (drrs->is_clone)
>> +		return;
>> +
>>   	mutex_lock(&drrs->drrs_mutex);
>>   	if (panel->target_mode != NULL)
>>   		DRM_ERROR("FIXME: We shouldn't be here\n");
>> @@ -192,6 +221,11 @@ static void intel_enable_idleness_drrs(struct i915_drrs *drrs)
>>   
>>   	mutex_lock(&drrs->drrs_mutex);
>>   
>> +	drrs->is_clone = is_cloned_mode_active(drrs->connector->base.dev);
>> +
>> +	if (drrs->is_clone)
>> +		return;
>> +
>>   	/* Capturing the deferred request for disable_drrs */
>>   	if (drrs->drrs_state.type == SEAMLESS_DRRS_SUPPORT_SW &&
>>   				drrs->encoder_ops->is_drrs_hr_state_pending) {
>> -- 
>> 1.7.9.5
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Thanks,
--Ram

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 10/18] drm/i915: Initializing DRRS for all connectors
  2015-06-26 17:12   ` Daniel Vetter
@ 2015-06-29 14:52     ` Ramalingam C
  0 siblings, 0 replies; 36+ messages in thread
From: Ramalingam C @ 2015-06-29 14:52 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi


On Friday 26 June 2015 10:42 PM, Daniel Vetter wrote:
> On Fri, Jun 26, 2015 at 07:21:54PM +0530, Ramalingam C wrote:
>> For all the connectors drrs init is invoked. drrs_init will
>> initialize the drrs for those connectors that support DRRS.
>>
>> Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_display.c |    5 +++++
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 3f48917..0e8467c 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -15021,6 +15021,7 @@ void intel_modeset_init(struct drm_device *dev)
>>   	int sprite, ret;
>>   	enum pipe pipe;
>>   	struct intel_crtc *crtc;
>> +	struct intel_connector *connector;
>>   
>>   	drm_mode_config_init(dev);
>>   
>> @@ -15090,6 +15091,10 @@ void intel_modeset_init(struct drm_device *dev)
>>   	i915_disable_vga(dev);
>>   	intel_setup_outputs(dev);
>>   
>> +	list_for_each_entry(connector, &dev->mode_config.connector_list,
>> +								base.head)
>> +		intel_drrs_init(dev, connector, connector->panel.fixed_mode);
> We initialize all the panel stuff in respective encoder callbacks, this is
> a layering violation. If we need to share more panel init code then that's
> ok, but the call needs to be in the edp/dsi/lvds/whatever init functions.
> -Daniel
Ok. Thought of making it generic connector property by calling the 
drrs_init for all
connector and  by validating the supported encoders at drrs_init. But I 
think we can move this call to
the corresponding encoder(dsi/eDP) init calls too. Will work on that. 
Thanks.

>
>> +
>>   	/* Just in case the BIOS is doing something questionable. */
>>   	intel_fbc_disable(dev);
>>   
>> -- 
>> 1.7.9.5
>>

-- 
Thanks,
--Ram

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions
  2015-06-26 17:11   ` Daniel Vetter
@ 2015-06-29 14:58     ` Ramalingam C
  2015-06-29 16:23       ` Daniel Vetter
  0 siblings, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-29 14:58 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: daniel.vetter, intel-gfx, rodrigo.vivi, paulo.r.zanoni


On Friday 26 June 2015 10:41 PM, Daniel Vetter wrote:
> On Fri, Jun 26, 2015 at 07:21:55PM +0530, Ramalingam C wrote:
>> During the DRRS state transitions we are modifying the clock and
>> hence the vrefresh rate.
>>
>> So we need to update the drm_crtc->mode and the adjusted
>> mode in intel_crtc. So that watermark calculations will be as per the
>> new modified clock.
>>
>> Signed-off-by: Ramalingam C<ramalingam.c@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_drrs.c     |   14 ++++++++++++++
>>   drivers/gpu/drm/i915/intel_dsi_drrs.c |   14 +++++++++++++-
>>   2 files changed, 27 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
>> index 42b420d..2901832 100644
>> --- a/drivers/gpu/drm/i915/intel_drrs.c
>> +++ b/drivers/gpu/drm/i915/intel_drrs.c
>> @@ -169,6 +169,20 @@ void intel_set_drrs_state(struct i915_drrs *drrs)
>>   		 * If it is non-DSI encoders.
>>   		 * As only DSI has SEAMLESS_DRRS_SUPPORT_SW.
>>   		 */
>> +		/*
>> +		 * TODO: Protect the access to the crtc mode with corresponding
>> +		 * mutex in case of Idleness DRRS. As media playback update
>> +		 * will happen under crtc modeset lock protection
>> +		 */
>> +		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
>> +		intel_crtc->base.mode.clock = target_mode->clock;
>> +		intel_crtc->base.mode.vrefresh = target_mode->vrefresh;
>> +		intel_crtc->config->base.adjusted_mode.clock =
>> +							target_mode->clock;
>> +		intel_crtc->config->base.adjusted_mode.vrefresh =
>> +							target_mode->vrefresh;
>> +		drm_modeset_unlock(&intel_crtc->base.mutex);
> No. For video DRRS (i.e. changing the vrefresh rate to exactly what we
> want to match media content) userspace needs to do a full modeset. Maarten
> is working on infrastructure to avoid full modeset in some special mode
> changes (to implement the fast pfit change from Jesse's original fastboot
> work). And we can extend this to DRRS too.
Daniel,

But this interface that we have developed for android is not just for 
video playback.
We are trying to provide a interface where user space can request for 
custom vrefresh,
if the rate of the display content doesn't need the vrefresh of current 
applied mode.
For example scenarios like text editor or some game where lower Frame 
per second is sufficient. And if the panel supports
the seamless drrs we don't need to do a modeset in such scenarios.

Either way Please do share/point to the details of the Maarten design. 
So that we can see if we are
working on same area and if so how far we can reuse each others work.
> For seamless&transparent DRRS we can still keep the current design with
> effectively 2 dotclocks.
You mean 2 dotclocks at drm_display_mode or drrs structure?
>
> Also with atomic you can combine the clock change with the first video
> frame which is double-awesome ;-)
> -Daniel
>
>> +
>>   		drrs_state->current_rr_type = drrs_state->target_rr_type;
>>   		DRM_INFO("Refresh Rate set to : %dHz\n", refresh_rate);
>>   	}
>> diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
>> index eb0758a..d4bb70a 100644
>> --- a/drivers/gpu/drm/i915/intel_dsi_drrs.c
>> +++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
>> @@ -46,6 +46,7 @@ static void intel_mipi_drrs_work_fn(struct work_struct *__work)
>>   	struct i915_drrs *drrs = work->drrs;
>>   	struct intel_encoder *intel_encoder = drrs->connector->encoder;
>>   	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&intel_encoder->base);
>> +	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
>>   	struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
>>   	struct dsi_mnp *dsi_mnp;
>>   	struct drm_display_mode *prev_mode = NULL;
>> @@ -69,11 +70,22 @@ retry:
>>   		/* PLL Programming is successful */
>>   		mutex_lock(&drrs->drrs_mutex);
>>   		drrs->drrs_state.current_rr_type = work->target_rr_type;
>> +
>> +		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
>> +		intel_crtc->base.mode.clock = work->target_mode->clock;
>> +		intel_crtc->base.mode.vrefresh = work->target_mode->vrefresh;
>> +		intel_crtc->config->base.adjusted_mode.clock =
>> +						work->target_mode->clock;
>> +		intel_crtc->config->base.adjusted_mode.vrefresh =
>> +						work->target_mode->vrefresh;
>> +		drm_modeset_unlock(&intel_crtc->base.mutex);
>> +
>>   		mutex_unlock(&drrs->drrs_mutex);
>> +
>>   		DRM_INFO("Refresh Rate set to : %dHz\n",
>>   						work->target_mode->vrefresh);
>>   
>> -		/* TODO: Update crtc mode and drain ladency with watermark */
>> +		/* TODO: Update drain ladency with watermark */
>>   
>>   	} else if (ret == -ETIMEDOUT && retry_cnt) {
>>   
>> -- 
>> 1.7.9.5
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Thanks,
--Ram

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 09/18] drm/i915: Cloned mode check
  2015-06-29 11:48     ` Ramalingam C
@ 2015-06-29 16:16       ` Daniel Vetter
  0 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2015-06-29 16:16 UTC (permalink / raw)
  To: Ramalingam C; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi

On Mon, Jun 29, 2015 at 05:18:21PM +0530, Ramalingam C wrote:
> 
> On Friday 26 June 2015 10:38 PM, Daniel Vetter wrote:
> >On Fri, Jun 26, 2015 at 07:21:53PM +0530, Ramalingam C wrote:
> >>If crtc is in clone mode, DRRS will be disabled. Because if the both
> >>the displays are not sharing the same vrefresh, then userspace
> >>activities based on vsync will go for toss.
> >>
> >>Clone mode will be rechecked on every restarting Idleness DRRS events.
> >>
> >>Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
> >>---
> >>  drivers/gpu/drm/i915/intel_drrs.c |   36 +++++++++++++++++++++++++++++++++++-
> >>  1 file changed, 35 insertions(+), 1 deletion(-)
> >>
> >>diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
> >>index e5d8bcd..42b420d 100644
> >>--- a/drivers/gpu/drm/i915/intel_drrs.c
> >>+++ b/drivers/gpu/drm/i915/intel_drrs.c
> >>@@ -16,6 +16,7 @@
> >>  #include <drm/i915_drm.h>
> >>  #include <linux/delay.h>
> >>+#include <linux/list.h>
> >>  #include "i915_drv.h"
> >>  #include "intel_drv.h"
> >>@@ -85,6 +86,31 @@ int get_free_drrs_struct_index(struct drm_i915_private *dev_priv)
> >>  	return -EBUSY;
> >>  }
> >>+/*
> >>+ * TODO: This is identifying the multiple active crtcs at a time.
> >>+ * Here we assume that this is clone state and disable DRRS.
> >>+ * But need to implement a proper method to find the real cloned mode
> >>+ * state. DRRS need not be disabled incase of multiple crtcs with
> >>+ * different content.
> >>+ */
> >This is a pretty big hack. Why do you need it? fb tracking should keep any
> >display in the high mode as long as there's activity, so as long as
> >userspace flips both buffers for both pipes (which is should for cloned
> >mode) they'll both be running at max.
> Yup. This is not needed for Idleness as fb tracking will keep the DRRS at
> High refresh rate.
> But at content based DRRS, we had some concern from android Userspace team
> that we cant
> support content based DRRS for cloned modes (eDP + HDMI or DSI + HDMI).
> 
> Of course at this point in time, we can enable the DRRS for all scenarios
> and test. Based on results we can plan ahead.

DRRS tracks each pipe individually and will not be confused if you use the
same framebuffer for more than one pipe (i.e. cloned use-case). The exact
same thing is how X usually is set up.

What exactly are the concerns that DRRS won't work? "concerns" is really
unspecific. We need a really clear description of what's expected, why it
doesn't work with the current DRRS and then figure out a suitable way to
address it. Adding code without a clear use-case is bad.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions
  2015-06-29 14:58     ` Ramalingam C
@ 2015-06-29 16:23       ` Daniel Vetter
  0 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2015-06-29 16:23 UTC (permalink / raw)
  To: Ramalingam C; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi

On Mon, Jun 29, 2015 at 08:28:53PM +0530, Ramalingam C wrote:
> 
> On Friday 26 June 2015 10:41 PM, Daniel Vetter wrote:
> >On Fri, Jun 26, 2015 at 07:21:55PM +0530, Ramalingam C wrote:
> >>During the DRRS state transitions we are modifying the clock and
> >>hence the vrefresh rate.
> >>
> >>So we need to update the drm_crtc->mode and the adjusted
> >>mode in intel_crtc. So that watermark calculations will be as per the
> >>new modified clock.
> >>
> >>Signed-off-by: Ramalingam C<ramalingam.c@intel.com>
> >>---
> >>  drivers/gpu/drm/i915/intel_drrs.c     |   14 ++++++++++++++
> >>  drivers/gpu/drm/i915/intel_dsi_drrs.c |   14 +++++++++++++-
> >>  2 files changed, 27 insertions(+), 1 deletion(-)
> >>
> >>diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
> >>index 42b420d..2901832 100644
> >>--- a/drivers/gpu/drm/i915/intel_drrs.c
> >>+++ b/drivers/gpu/drm/i915/intel_drrs.c
> >>@@ -169,6 +169,20 @@ void intel_set_drrs_state(struct i915_drrs *drrs)
> >>  		 * If it is non-DSI encoders.
> >>  		 * As only DSI has SEAMLESS_DRRS_SUPPORT_SW.
> >>  		 */
> >>+		/*
> >>+		 * TODO: Protect the access to the crtc mode with corresponding
> >>+		 * mutex in case of Idleness DRRS. As media playback update
> >>+		 * will happen under crtc modeset lock protection
> >>+		 */
> >>+		drm_modeset_lock(&intel_crtc->base.mutex, NULL);
> >>+		intel_crtc->base.mode.clock = target_mode->clock;
> >>+		intel_crtc->base.mode.vrefresh = target_mode->vrefresh;
> >>+		intel_crtc->config->base.adjusted_mode.clock =
> >>+							target_mode->clock;
> >>+		intel_crtc->config->base.adjusted_mode.vrefresh =
> >>+							target_mode->vrefresh;
> >>+		drm_modeset_unlock(&intel_crtc->base.mutex);
> >No. For video DRRS (i.e. changing the vrefresh rate to exactly what we
> >want to match media content) userspace needs to do a full modeset. Maarten
> >is working on infrastructure to avoid full modeset in some special mode
> >changes (to implement the fast pfit change from Jesse's original fastboot
> >work). And we can extend this to DRRS too.
> Daniel,
> 
> But this interface that we have developed for android is not just for video
> playback.
> We are trying to provide a interface where user space can request for custom
> vrefresh,
> if the rate of the display content doesn't need the vrefresh of current
> applied mode.

Well I just called it video DRRS since I thought that's the main use-case.
The interface I'm proposing here (which already exists, that's the point)
will of course work no matter what exactly you're displaying.

> For example scenarios like text editor or some game where lower Frame per
> second is sufficient. And if the panel supports
> the seamless drrs we don't need to do a modeset in such scenarios.
> 
> Either way Please do share/point to the details of the Maarten design. So
> that we can see if we are
> working on same area and if so how far we can reuse each others work.

Maarten is still debugging a pile of fallout in unrelated code, probably
best if you ping him directly on irc about the latest stuff.

> >For seamless&transparent DRRS we can still keep the current design with
> >effectively 2 dotclocks.
> You mean 2 dotclocks at drm_display_mode or drrs structure?

In intel_crtc_config we have two sets of DP m/n values, which means 2
different clocks for the sink. We also have pipe_config->port_clock. Just
need to extend that to low_port_clock for seamless DRRS (i.e. managed by
the kernel).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 00/18] Generic DRRS implementation across the encoders
  2015-06-29 11:22   ` Ramalingam C
@ 2015-06-29 16:27     ` Daniel Vetter
  2015-06-30  6:29       ` Ramalingam C
  0 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2015-06-29 16:27 UTC (permalink / raw)
  To: Ramalingam C; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi

On Mon, Jun 29, 2015 at 04:52:14PM +0530, Ramalingam C wrote:
> On Friday 26 June 2015 10:46 PM, Daniel Vetter wrote:
> >On Fri, Jun 26, 2015 at 07:21:44PM +0530, Ramalingam C wrote:
> >- Static DRRS and generalized seamless DRRS are imo separate features and
> >   we should split the patch series. seamless DRRS is already implemented
> >   using the fb tracking, maybe extended with some hints to userspace.
> >
> >   Static DRRS otoh is just a modeset with a different clock (plus a better
> >   internal implementation to avoid flicker). So from that pov two
> >   completely different features, both in the implementation and the
> >   userspace ABI.
> Yup. Static is not even in our development radar :). All the code that I
> have shared is
> concerned only with seamless DRRS and it's two usecase scenarios( Idleness
> and Content based).
> Mentioned the Static DRRS in cover letter, just to give the two different
> DRRS supports available in general.

Hm then I'm confused how the content based DRRS is supposed to work. I
thought userspace requires a precise vrefresh rate (adjusted to content,
within the limits of what the panel can do ofc) and the kernel tries to
obey. That's what I consider static DRRS, i.e. userspace makes a fixed
request, kernel executes it exactly.

Seamless DRRS for me is when the kernel tries to change vrefresh when
everything is idle behind everyone's back.

I'm doing this split since seamless doesn't require new userspace
interfaces (we just use the frontbuffer tracking system), whereas static
needs explicit action from userspace and hence the dreaded userspace ABI
problem starts to kick in.

Do you have different definitions? What exactly are those?
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 00/18] Generic DRRS implementation across the encoders
  2015-06-29 16:27     ` Daniel Vetter
@ 2015-06-30  6:29       ` Ramalingam C
  2015-06-30 10:02         ` Daniel Vetter
  0 siblings, 1 reply; 36+ messages in thread
From: Ramalingam C @ 2015-06-30  6:29 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi


On Monday 29 June 2015 09:57 PM, Daniel Vetter wrote:
> On Mon, Jun 29, 2015 at 04:52:14PM +0530, Ramalingam C wrote:
>> On Friday 26 June 2015 10:46 PM, Daniel Vetter wrote:
>>> On Fri, Jun 26, 2015 at 07:21:44PM +0530, Ramalingam C wrote:
>>> - Static DRRS and generalized seamless DRRS are imo separate features and
>>>    we should split the patch series. seamless DRRS is already implemented
>>>    using the fb tracking, maybe extended with some hints to userspace.
>>>
>>>    Static DRRS otoh is just a modeset with a different clock (plus a better
>>>    internal implementation to avoid flicker). So from that pov two
>>>    completely different features, both in the implementation and the
>>>    userspace ABI.
>> Yup. Static is not even in our development radar :). All the code that I
>> have shared is
>> concerned only with seamless DRRS and it's two usecase scenarios( Idleness
>> and Content based).
>> Mentioned the Static DRRS in cover letter, just to give the two different
>> DRRS supports available in general.
> Hm then I'm confused how the content based DRRS is supposed to work. I
> thought userspace requires a precise vrefresh rate (adjusted to content,
> within the limits of what the panel can do ofc) and the kernel tries to
> obey. That's what I consider static DRRS, i.e. userspace makes a fixed
> request, kernel executes it exactly.
If panel does support the static DRRS only and you are ok to do a 
complete modeset on a usecase then
Whatever you have explained stands true for content based DRRS. I 
believe its another complete modeset w.r.t kernel.
Which I am not addressing in this RFC.

But If the panel supports seamless DRRS and userspace want a precise 
vrefresh rate (adjusted to the
content, within the limits of what panel can do) then kernel can achieve 
the vrefresh change seamlessly
(the way its done with Idleness scenario). This is the second usecase of 
seamless DRRS support of the panel.
Infact We have implemented this and verified on android already for 
video playback.
>
> Seamless DRRS for me is when the kernel tries to change vrefresh when
> everything is idle behind everyone's back.
Seamless DRRS is a capability of the host and the panel. Usercase 
definition is upto us to do.
>
> I'm doing this split since seamless doesn't require new userspace
> interfaces (we just use the frontbuffer tracking system), whereas static
> needs explicit action from userspace and hence the dreaded userspace ABI
> problem starts to kick in.
Based on above usecase of the seamless drrs we need a fast modeset path 
which I have addressed at the RFC PATCH 16/18.
And drm connector property to expose the SEAMLESS DRRS capability to the 
userspace. implemented at RFC PATCH 18/18
>
> Do you have different definitions? What exactly are those?
-Daniel

-- 
Thanks,
--Ram

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [RFC PATCH 00/18] Generic DRRS implementation across the encoders
  2015-06-30  6:29       ` Ramalingam C
@ 2015-06-30 10:02         ` Daniel Vetter
  0 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2015-06-30 10:02 UTC (permalink / raw)
  To: Ramalingam C; +Cc: paulo.r.zanoni, daniel.vetter, intel-gfx, rodrigo.vivi

On Tue, Jun 30, 2015 at 11:59:30AM +0530, Ramalingam C wrote:
> 
> On Monday 29 June 2015 09:57 PM, Daniel Vetter wrote:
> >On Mon, Jun 29, 2015 at 04:52:14PM +0530, Ramalingam C wrote:
> >>On Friday 26 June 2015 10:46 PM, Daniel Vetter wrote:
> >>>On Fri, Jun 26, 2015 at 07:21:44PM +0530, Ramalingam C wrote:
> >>>- Static DRRS and generalized seamless DRRS are imo separate features and
> >>>   we should split the patch series. seamless DRRS is already implemented
> >>>   using the fb tracking, maybe extended with some hints to userspace.
> >>>
> >>>   Static DRRS otoh is just a modeset with a different clock (plus a better
> >>>   internal implementation to avoid flicker). So from that pov two
> >>>   completely different features, both in the implementation and the
> >>>   userspace ABI.
> >>Yup. Static is not even in our development radar :). All the code that I
> >>have shared is
> >>concerned only with seamless DRRS and it's two usecase scenarios( Idleness
> >>and Content based).
> >>Mentioned the Static DRRS in cover letter, just to give the two different
> >>DRRS supports available in general.
> >Hm then I'm confused how the content based DRRS is supposed to work. I
> >thought userspace requires a precise vrefresh rate (adjusted to content,
> >within the limits of what the panel can do ofc) and the kernel tries to
> >obey. That's what I consider static DRRS, i.e. userspace makes a fixed
> >request, kernel executes it exactly.
> If panel does support the static DRRS only and you are ok to do a complete
> modeset on a usecase then
> Whatever you have explained stands true for content based DRRS. I believe
> its another complete modeset w.r.t kernel.
> Which I am not addressing in this RFC.
> 
> But If the panel supports seamless DRRS and userspace want a precise
> vrefresh rate (adjusted to the
> content, within the limits of what panel can do) then kernel can achieve the
> vrefresh change seamlessly
> (the way its done with Idleness scenario). This is the second usecase of
> seamless DRRS support of the panel.
> Infact We have implemented this and verified on android already for video
> playback.
> >
> >Seamless DRRS for me is when the kernel tries to change vrefresh when
> >everything is idle behind everyone's back.
> Seamless DRRS is a capability of the host and the panel. Usercase definition
> is upto us to do.
> >
> >I'm doing this split since seamless doesn't require new userspace
> >interfaces (we just use the frontbuffer tracking system), whereas static
> >needs explicit action from userspace and hence the dreaded userspace ABI
> >problem starts to kick in.
> Based on above usecase of the seamless drrs we need a fast modeset path
> which I have addressed at the RFC PATCH 16/18.
> And drm connector property to expose the SEAMLESS DRRS capability to the
> userspace. implemented at RFC PATCH 18/18

Summarizing our discussion from the mtg, there's 3 different cases here:
- transparent seamless DRRS where the kernel lowers vrefresh on idle
  behind userspace's back. This is what we currently have integrated. No
  new ABI required.
- seamless DRRS but upon explicit request from userspace. This is
  essentially just a mode change, but excuted by the kernel without any
  blanking or otherwise stalling. We can reuse the modeset ioctls for
  this, just need a fast path (similar to the fast pfit update Maarten
  already has in his atomic branches). For figuring out whether seamless
  is possible we could reuse the atomic TEST_ONLY and ALLOW_MODESET flags.
  Good chances that we don't need a new ABI.
- just changing the vrefresh of the panel, with full modeset/blanking. We
  have the interface for that (we can do modesets), but currently our
  panel compute_config code hardcodes the vrefresh to the preferred mode
  of the panel. We need to change that and pick the vrefresh userspace
  asked for. I think from an implementation pov it makes sense to first
  fix up this case, and then in a 2nd step implement the seamless DRRS for
  explicit mode changes.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2015-06-30  9:59 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-26 13:51 [RFC PATCH 00/18] Generic DRRS implementation across the encoders Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 01/18] drm/i915: Removing the eDP specific DRRS implementation Ramalingam C
2015-06-26 16:50   ` Daniel Vetter
2015-06-29 11:24     ` Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 02/18] drm/i915: Generic DRRS state Machine Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 03/18] drm/i915: Addition of the drrs_min_vrefresh in VBT Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 04/18] drm/i915: Implementation of Generic DSI DRRS Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 05/18] drm/i915: Adjusting the pclk for dual link and burst mode Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 06/18] drm/i915: VLV dsi drrs support Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 07/18] drm/i915: Generic eDP DRRS implementation Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 08/18] drm/i915: VLV eDP DRRS methods Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 09/18] drm/i915: Cloned mode check Ramalingam C
2015-06-26 17:08   ` Daniel Vetter
2015-06-26 17:14     ` Chris Wilson
2015-06-26 17:38       ` Daniel Vetter
2015-06-29 11:48     ` Ramalingam C
2015-06-29 16:16       ` Daniel Vetter
2015-06-26 13:51 ` [RFC PATCH 10/18] drm/i915: Initializing DRRS for all connectors Ramalingam C
2015-06-26 17:12   ` Daniel Vetter
2015-06-29 14:52     ` Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 11/18] drm/i915: Updating the crtc modes in DRRS transitions Ramalingam C
2015-06-26 17:11   ` Daniel Vetter
2015-06-29 14:58     ` Ramalingam C
2015-06-29 16:23       ` Daniel Vetter
2015-06-26 13:51 ` [RFC PATCH 12/18] drm/i915: Redesigning dp_set_m_n to receive divider values Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 13/18] drm/i915: MEDIA_RR support in general DRRS state machine Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 14/18] drm/i915: MEDIA_RR support in eDP DRRS module Ramalingam C
2015-06-26 13:51 ` [RFC PATCH 15/18] drm/i915: MEDIA_RR support in DSI " Ramalingam C
2015-06-26 13:52 ` [RFC PATCH 16/18] drm/i915: Filtering media playback DRRS requests Ramalingam C
2015-06-26 13:52 ` [RFC PATCH 17/18] drm/i915: Addition of downclock mode to connector modelist Ramalingam C
2015-06-26 13:52 ` [RFC PATCH 18/18] drm/i915: Connector property for DRRS capability Ramalingam C
2015-06-26 17:16 ` [RFC PATCH 00/18] Generic DRRS implementation across the encoders Daniel Vetter
2015-06-29 11:22   ` Ramalingam C
2015-06-29 16:27     ` Daniel Vetter
2015-06-30  6:29       ` Ramalingam C
2015-06-30 10:02         ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.