* [PATCH 0/6] v7: Enabling DRRS in the kernel
@ 2014-03-28 4:44 Vandana Kannan
2014-03-28 4:44 ` [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature Vandana Kannan
` (5 more replies)
0 siblings, 6 replies; 40+ messages in thread
From: Vandana Kannan @ 2014-03-28 4:44 UTC (permalink / raw)
To: intel-gfx
Dynamic Refresh Rate Switching (DRRS) is a power conservation feature which
enables swtiching between low and high refresh rates based on the usage
scenario. This feature is applciable for internal eDP panel. Indication that
the panel supports DRRS is given by the panel EDID, which would list multiple
refresh rates for one resolution.
The patch series supports idleness detection in display i915 driver and
switch to low refresh rate.
Based on review comments, the functions for idleness detection have been
restructured. DRRS idleness time has been modified to be a kernel module param.
v6: Added support for VLV.
v7: Patches rebased, review comments incorporated
Pradeep Bhat (3):
drm/i915: Adding VBT fields to support eDP DRRS feature
drm/i915: Parse EDID probed modes for DRRS support
drm/i915: Add support for DRRS to switch RR
Vandana Kannan (3):
drm/i915: Idleness detection for DRRS
drm/i915/bdw: Add support for DRRS to switch RR
drm/i915: Support for RR switching on VLV
drivers/gpu/drm/i915/i915_drv.h | 24 +++++
drivers/gpu/drm/i915/i915_params.c | 8 ++
drivers/gpu/drm/i915/i915_reg.h | 2 +
drivers/gpu/drm/i915/intel_bios.c | 34 +++++-
drivers/gpu/drm/i915/intel_bios.h | 29 +++++
drivers/gpu/drm/i915/intel_display.c | 18 +++-
drivers/gpu/drm/i915/intel_dp.c | 198 +++++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 29 ++++-
drivers/gpu/drm/i915/intel_pm.c | 138 ++++++++++++++++++++++++
9 files changed, 475 insertions(+), 5 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature
2014-03-28 4:44 [PATCH 0/6] v7: Enabling DRRS in the kernel Vandana Kannan
@ 2014-03-28 4:44 ` Vandana Kannan
2014-04-01 13:04 ` Jani Nikula
2014-03-28 4:44 ` [PATCH 2/6] drm/i915: Parse EDID probed modes for DRRS support Vandana Kannan
` (4 subsequent siblings)
5 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-03-28 4:44 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch reads the DRRS support and Mode type from VBT fields.
The read information will be stored in VBT struct during BIOS
parsing. The above functionality is needed for decision making
whether DRRS feature is supported in i915 driver for eDP panels.
This information helps us decide if seamless DRRS can be done
at runtime to support certain power saving features. This patch
was tested by setting necessary bit in VBT struct and merging
the new VBT with system BIOS so that we can read the value.
v2: Incorporated review comments from Chris Wilson
Removed "intel_" as a prefix for DRRS specific declarations.
v3: Incorporated Jani's review comments
Removed function which deducts drrs mode from panel_type. Modified some
print statements. Made changes to use DRRS_NOT_SUPPORTED as 0 instead of -1.
v4: Incorporated Jani's review comments.
Modifications around setting vbt drrs_type.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++++
drivers/gpu/drm/i915/intel_bios.c | 34 +++++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_bios.h | 29 +++++++++++++++++++++++++++++
3 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9b8c1e0..cd73a33 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1284,6 +1284,12 @@ struct ddi_vbt_port_info {
uint8_t supports_dp:1;
};
+enum drrs_support_type {
+ DRRS_NOT_SUPPORTED = 0,
+ STATIC_DRRS_SUPPORT = 1,
+ SEAMLESS_DRRS_SUPPORT = 2
+};
+
struct intel_vbt_data {
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
@@ -1299,6 +1305,12 @@ struct intel_vbt_data {
int lvds_ssc_freq;
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
+ /*
+ * DRRS support type (Seamless OR Static DRRS OR not supported)
+ * These values correspond to the VBT values for drrs mode.
+ */
+ enum drrs_support_type drrs_type;
+
/* eDP */
int edp_rate;
int edp_lanes;
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 4867f4c..9b98677 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -206,7 +206,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
const struct lvds_dvo_timing *panel_dvo_timing;
const struct lvds_fp_timing *fp_timing;
struct drm_display_mode *panel_fixed_mode;
- int i, downclock;
+ int i, downclock, drrs_mode;
lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
if (!lvds_options)
@@ -218,6 +218,28 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
panel_type = lvds_options->panel_type;
+ drrs_mode = (lvds_options->dps_panel_type_bits
+ >> (panel_type * 2)) & MODE_MASK;
+ /*
+ * VBT has static DRRS = 0 and seamless DRRS = 2.
+ * The below piece of code is required to adjust vbt.drrs_type
+ * to match the enum drrs_support_type.
+ */
+ switch (drrs_mode) {
+ case 0:
+ dev_priv->vbt.drrs_type = STATIC_DRRS_SUPPORT;
+ DRM_DEBUG_KMS("DRRS supported mode is static\n");
+ break;
+ case 2:
+ dev_priv->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT;
+ DRM_DEBUG_KMS("DRRS supported mode is seamless\n");
+ break;
+ default:
+ dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
+ DRM_DEBUG_KMS("DRRS not supported (VBT input)\n");
+ break;
+ }
+
lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
if (!lvds_lfp_data)
return;
@@ -516,6 +538,16 @@ parse_driver_features(struct drm_i915_private *dev_priv,
if (driver->dual_frequency)
dev_priv->render_reclock_avail = true;
+
+ DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled);
+ /*
+ * If DRRS is not supported, drrs_type has to be set to 0.
+ * This is because, VBT is configured in such a way that
+ * static DRRS is 0 and DRRS not supported is represented by
+ * driver->drrs_enabled=false
+ */
+ if (!driver->drrs_enabled)
+ dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
}
static void
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 83b7629..d02e5f9 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -282,6 +282,9 @@ struct bdb_general_definitions {
union child_device_config devices[0];
} __packed;
+/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
+#define MODE_MASK 0x3
+
struct bdb_lvds_options {
u8 panel_type;
u8 rsvd1;
@@ -294,6 +297,18 @@ struct bdb_lvds_options {
u8 lvds_edid:1;
u8 rsvd2:1;
u8 rsvd4;
+ /* LVDS Panel channel bits stored here */
+ u32 lvds_panel_channel_bits;
+ /* LVDS SSC (Spread Spectrum Clock) bits stored here. */
+ u16 ssc_bits;
+ u16 ssc_freq;
+ u16 ssc_ddt;
+ /* Panel color depth defined here */
+ u16 panel_color_depth;
+ /* LVDS panel type bits stored here */
+ u32 dps_panel_type_bits;
+ /* LVDS backlight control type bits stored here */
+ u32 blt_control_type_bits;
} __packed;
/* LFP pointer table contains entries to the struct below */
@@ -479,6 +494,20 @@ struct bdb_driver_features {
u8 hdmi_termination;
u8 custom_vbt_version;
+ /* Driver features data block */
+ u16 rmpm_enabled:1;
+ u16 s2ddt_enabled:1;
+ u16 dpst_enabled:1;
+ u16 bltclt_enabled:1;
+ u16 adb_enabled:1;
+ u16 drrs_enabled:1;
+ u16 grs_enabled:1;
+ u16 gpmt_enabled:1;
+ u16 tbt_enabled:1;
+ u16 psr_enabled:1;
+ u16 ips_enabled:1;
+ u16 reserved3:4;
+ u16 pc_feature_valid:1;
} __packed;
#define EDP_18BPP 0
--
1.7.9.5
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-03-28 4:44 [PATCH 0/6] v7: Enabling DRRS in the kernel Vandana Kannan
2014-03-28 4:44 ` [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature Vandana Kannan
@ 2014-03-28 4:44 ` Vandana Kannan
2014-04-01 13:17 ` Jani Nikula
2014-03-28 4:44 ` [PATCH 3/6] drm/i915: Add support for DRRS to switch RR Vandana Kannan
` (3 subsequent siblings)
5 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-03-28 4:44 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch and finds out the lowest refresh rate supported for the resolution
same as the fixed_mode.
It also checks the VBT fields to see if panel supports seamless DRRS or not.
Based on above data it marks whether eDP panel supports seamless DRRS or not.
This information is needed for supporting seamless DRRS switch for certain
power saving usecases. This patch is tested by enabling the DRM logs and
user should see whether Seamless DRRS is supported or not.
v2: Daniel's review comments
Modified downclock deduction based on intel_find_panel_downclock
v3: Chris's review comments
Moved edp_downclock_avail and edp_downclock to intel_panel
v4: Jani's review comments.
Changed name of the enum edp_panel_type to drrs_support type.
Change is_drrs_supported to drrs_support of type enum drrs_support_type.
v5: Incorporated Jani's review comments
Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
and above.
v6: Incorporated Chris's review comments.
Changed initialize to init in intel_drrs_initialize
v7: Incorporated Jani's review comments.
Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 53 +++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++
2 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 59ee4dc..f2735de 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3611,6 +3611,51 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+static struct drm_display_mode *
+intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
+ struct intel_connector *intel_connector,
+ struct drm_display_mode *fixed_mode)
+{
+ struct drm_connector *connector = &intel_connector->base;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_display_mode *downclock_mode = NULL;
+
+ if (INTEL_INFO(dev)->gen <= 6) {
+ DRM_INFO("DRRS supported for Gen7 and above\n");
+ return NULL;
+ }
+
+ /**
+ * Check if PSR is supported by panel and enabled
+ * if so then DRRS is reported as not supported for Haswell.
+ */
+ if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
+ DRM_INFO("eDP panel has PSR enabled. Cannot support DRRS\n");
+ return NULL;
+ }
+
+ /* First check if DRRS is enabled from VBT struct */
+ if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
+ DRM_INFO("VBT doesn't support DRRS\n");
+ return NULL;
+ }
+
+ downclock_mode = intel_find_panel_downclock
+ (dev, fixed_mode, connector);
+
+ if (downclock_mode != NULL &&
+ dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
+ intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
+
+ intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
+ DRM_INFO("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,
struct edp_power_seq *power_seq)
@@ -3620,10 +3665,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = NULL;
+ struct drm_display_mode *downclock_mode = NULL;
bool has_dpcd;
struct drm_display_mode *scan;
struct edid *edid;
+ intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
+
if (!is_edp(intel_dp))
return true;
@@ -3665,6 +3713,9 @@ 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_dig_port,
+ intel_connector, fixed_mode);
break;
}
}
@@ -3677,7 +3728,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
}
- intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector);
return true;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fa99104..d781165 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -483,6 +483,17 @@ struct intel_hdmi {
#define DP_MAX_DOWNSTREAM_PORTS 0x10
+/**
+ * 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 edp_drrs_refresh_rate_type {
+ DRRS_HIGH_RR,
+ DRRS_LOW_RR,
+ DRRS_MAX_RR, /* RR count */
+};
+
struct intel_dp {
uint32_t output_reg;
uint32_t aux_ch_ctl_reg;
@@ -521,6 +532,11 @@ struct intel_dp {
bool has_aux_irq,
int send_bytes,
uint32_t aux_clock_divider);
+ struct {
+ enum drrs_support_type type;
+ enum edp_drrs_refresh_rate_type refresh_rate_type;
+ } drrs_state;
+
};
struct intel_digital_port {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH 3/6] drm/i915: Add support for DRRS to switch RR
2014-03-28 4:44 [PATCH 0/6] v7: Enabling DRRS in the kernel Vandana Kannan
2014-03-28 4:44 ` [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature Vandana Kannan
2014-03-28 4:44 ` [PATCH 2/6] drm/i915: Parse EDID probed modes for DRRS support Vandana Kannan
@ 2014-03-28 4:44 ` Vandana Kannan
2014-04-01 13:25 ` Jani Nikula
2014-03-28 4:45 ` [PATCH 4/6] drm/i915: Idleness detection for DRRS Vandana Kannan
` (2 subsequent siblings)
5 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-03-28 4:44 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch computes and stored 2nd M/N/TU for switching to different
refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
between alternate refresh rates programmed in 2nd M/N/TU registers.
v2: Daniel's review comments
Computing M2/N2 in compute_config and storing it in crtc_config
v3: Modified reference to edp_downclock and edp_downclock_avail based on the
changes made to move them from dev_private to intel_panel.
v4: Modified references to is_drrs_supported based on the changes made to
rename it to drrs_support.
v5: Jani's review comments
Removed superfluous return statements. Changed support for Gen 7 and above.
Corrected indentation. Re-structured the code which finds crtc and connector
from encoder. Changed some logs to be less verbose.
v6: Modifying i915_drrs to include only intel connector as intel_dp can be
derived from intel connector when required.
v7: As per internal review comments, acquiring mutex just before accessing
drrs RR. As per Chris's review comments, added documentation about the use
of locking in the function.
v8: Incorporated Jani's review comments.
Removed reference to edp_downclock.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 5 ++
drivers/gpu/drm/i915/i915_reg.h | 1 +
drivers/gpu/drm/i915/intel_dp.c | 108 ++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_drv.h | 6 ++-
4 files changed, 119 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cd73a33..1c9d5cf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -794,6 +794,10 @@ struct i915_fbc {
} no_fbc_reason;
};
+struct i915_drrs {
+ struct intel_connector *connector;
+};
+
struct i915_psr {
bool sink_support;
bool source_ok;
@@ -1497,6 +1501,7 @@ typedef struct drm_i915_private {
struct timer_list hotplug_reenable_timer;
struct i915_fbc fbc;
+ struct i915_drrs drrs;
struct intel_opregion opregion;
struct intel_vbt_data vbt;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 74f7d85..04fc64a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3255,6 +3255,7 @@ enum punit_power_well {
#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
#define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
+#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
#define PIPECONF_BPC_MASK (0x7 << 5)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f2735de..9640df1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -736,6 +736,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
}
}
+static void
+intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum transcoder transcoder = crtc->config.cpu_transcoder;
+
+ I915_WRITE(PIPE_DATA_M2(transcoder),
+ TU_SIZE(m_n->tu) | m_n->gmch_m);
+ I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
+ I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
+ I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
+}
+
bool
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
@@ -840,6 +854,15 @@ found:
pipe_config->port_clock,
&pipe_config->dp_m_n);
+ if (intel_connector->panel.downclock_mode != NULL &&
+ intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
+ intel_link_compute_m_n(bpp, lane_count,
+ intel_connector->panel.downclock_mode->clock,
+ pipe_config->port_clock,
+ &pipe_config->dp_m2_n2);
+ }
+
+
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
return true;
@@ -3611,6 +3634,87 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+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_dp *intel_dp = NULL;
+ struct intel_crtc_config *config = NULL;
+ struct intel_crtc *intel_crtc = NULL;
+ struct intel_connector *intel_connector = dev_priv->drrs.connector;
+ u32 reg, val;
+ int index = 0;
+
+ if (refresh_rate <= 0) {
+ DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n");
+ return;
+ }
+
+ if (intel_connector == NULL) {
+ DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
+ return;
+ }
+
+ encoder = intel_attached_encoder(&intel_connector->base);
+ intel_dp = enc_to_intel_dp(&encoder->base);
+ intel_crtc = encoder->new_crtc;
+
+ if (!intel_crtc) {
+ DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
+ return;
+ }
+
+ config = &intel_crtc->config;
+
+ if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
+ DRM_DEBUG_KMS("Seamless DRRS not supported.\n");
+ return;
+ }
+
+ if (intel_connector->panel.fixed_mode->vrefresh == refresh_rate)
+ index = DRRS_HIGH_RR;
+ else
+ index = DRRS_LOW_RR;
+
+ if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
+ reg = PIPECONF(intel_crtc->config.cpu_transcoder);
+ val = I915_READ(reg);
+ if (index > DRRS_HIGH_RR) {
+ val |= PIPECONF_EDP_RR_MODE_SWITCH;
+ intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
+ } else {
+ val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
+ }
+ I915_WRITE(reg, val);
+ }
+
+ /*
+ * mutex taken to ensure that there is no race between differnt
+ * drrs calls trying to update refresh rate. This scenario may occur
+ * in future when idleness detection based DRRS in kernel and
+ * possible calls from user space to set differnt RR are made.
+ */
+
+ mutex_lock(&intel_dp->drrs_state.mutex);
+
+ intel_dp->drrs_state.refresh_rate_type = index;
+
+ mutex_unlock(&intel_dp->drrs_state.mutex);
+
+ DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
+}
+
static struct drm_display_mode *
intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector,
@@ -3647,6 +3751,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
if (downclock_mode != NULL &&
dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
+ dev_priv->drrs.connector = intel_connector;
+
+ mutex_init(&intel_dp->drrs_state.mutex);
+
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d781165..46fc8b3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -305,6 +305,9 @@ struct intel_crtc_config {
int pipe_bpp;
struct intel_link_m_n dp_m_n;
+ /* m2_n2 for eDP downclock */
+ struct intel_link_m_n dp_m2_n2;
+
/*
* Frequence the dpll for the port should run at. Differs from the
* adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
@@ -535,6 +538,7 @@ struct intel_dp {
struct {
enum drrs_support_type type;
enum edp_drrs_refresh_rate_type refresh_rate_type;
+ struct mutex mutex;
} drrs_state;
};
@@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
void intel_edp_psr_enable(struct intel_dp *intel_dp);
void intel_edp_psr_disable(struct intel_dp *intel_dp);
void intel_edp_psr_update(struct drm_device *dev);
-
+void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
/* intel_dsi.c */
bool intel_dsi_init(struct drm_device *dev);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH 4/6] drm/i915: Idleness detection for DRRS
2014-03-28 4:44 [PATCH 0/6] v7: Enabling DRRS in the kernel Vandana Kannan
` (2 preceding siblings ...)
2014-03-28 4:44 ` [PATCH 3/6] drm/i915: Add support for DRRS to switch RR Vandana Kannan
@ 2014-03-28 4:45 ` Vandana Kannan
2014-04-01 13:36 ` Jani Nikula
2014-03-28 4:45 ` [PATCH 5/6] drm/i915/bdw: Add support for DRRS to switch RR Vandana Kannan
2014-03-28 4:45 ` [PATCH 6/6] drm/i915: Support for RR switching on VLV Vandana Kannan
5 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-03-28 4:45 UTC (permalink / raw)
To: intel-gfx
Adding support to detect display idleness by tracking page flip from
user space. Switch to low refresh rate is triggered after 2 seconds of
idleness. The delay is configurable. If there is a page flip or call to
update the plane, then high refresh rate is applied.
The feature is not used in dual-display mode.
v2: Chris Wilson's review comments incorporated.
Modify idleness detection implementation to make it similar to the
implementation of intel_update_fbc/intel_disable_fbc
v3: Internal review comments incorporated
Add NULL pointer check in intel_disable_drrs.
Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
v4: Jani's review comments incorporated.
Change in sequence in intel_update_drrs. Comment modified to remove details
of update param. Modified DRRS idleness interval to a module parameter.
v5: Chris's review comments incorporated.
Initialize connector in idleness detection init. Modifications made to
use only intel_connector in i915_drrs and derive intel_dp when required.
Added a function drrs_fini to cleanup DRRS work.
v6: Internal review comments. Removed check for primary enabled, which is
a redundant check, in the case of clone mode. Added a flag to track
dual-display configuration. Remove print statement for "cancel DRR work"
and print "DRRS not supported" only once.
v7: As per internal review comments, removing calls to update/disable drrs
from sprite update path. For sprite, all drrs related updates would be
taken care of with calls to crtc page flip itself. This will have to be
revisited later if flip infrastructure changes for sprite.
v8: Incorporated Jani's review comments. Added space after the periods in the
module param description. Changes around drrs-fini to remove seamless DRRS
check.
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 7 ++
drivers/gpu/drm/i915/i915_params.c | 8 ++
drivers/gpu/drm/i915/intel_display.c | 16 ++++
drivers/gpu/drm/i915/intel_dp.c | 22 +++++-
drivers/gpu/drm/i915/intel_drv.h | 5 +-
drivers/gpu/drm/i915/intel_pm.c | 138 ++++++++++++++++++++++++++++++++++
6 files changed, 193 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1c9d5cf..c4e9b37 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -796,6 +796,12 @@ struct i915_fbc {
struct i915_drrs {
struct intel_connector *connector;
+ bool is_clone;
+ struct intel_drrs_work {
+ struct delayed_work work;
+ struct drm_crtc *crtc;
+ int interval;
+ } *drrs_work;
};
struct i915_psr {
@@ -2092,6 +2098,7 @@ struct i915_params {
int enable_ips;
int invert_brightness;
int enable_cmd_parser;
+ int drrs_interval;
/* leave bools at the end to not create holes */
bool enable_hangcheck;
bool fastboot;
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d1d7980..05ca0a0 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
.invert_brightness = 0,
.disable_display = 0,
.enable_cmd_parser = 0,
+ .drrs_interval = 2000,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -152,3 +153,10 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled, 0=disabled [default])");
+
+module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
+MODULE_PARM_DESC(drrs_interval,
+ "DRRS idleness detection interval (default: 2000 ms). "
+ "If this field is set to 0, then seamless DRRS feature "
+ "based on idleness detection is disabled. "
+ "The interval is to be set in milliseconds.");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7e4ea8d..c309561 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2542,6 +2542,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
@@ -3708,6 +3709,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -3751,6 +3753,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
drm_vblank_on(dev, pipe);
@@ -3948,6 +3951,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -3995,6 +3999,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -4391,6 +4396,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4438,6 +4444,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_crtc_dpms_overlay(intel_crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4505,6 +4512,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
}
static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -8508,6 +8516,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
drm_gem_object_unreference(&work->pending_flip_obj->base);
drm_gem_object_unreference(&work->old_fb_obj->base);
+ /* disable current DRRS work scheduled and restart
+ * to push work by another x seconds
+ */
+ intel_update_drrs(dev);
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
@@ -8966,6 +8978,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup_pending;
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
intel_mark_fb_busy(obj, NULL);
mutex_unlock(&dev->struct_mutex);
@@ -11338,6 +11351,7 @@ void intel_modeset_init(struct drm_device *dev)
/* Just in case the BIOS is doing something questionable. */
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
mutex_lock(&dev->mode_config.mutex);
intel_modeset_setup_hw_state(dev, false);
@@ -11803,6 +11817,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
+
intel_disable_gt_powersave(dev);
ironlake_teardown_rc6(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9640df1..4f0281a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3351,16 +3351,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
kfree(connector);
}
+static void
+intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
+{
+ if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
+ kfree(dev_priv->drrs.drrs_work);
+ dev_priv->drrs.drrs_work = NULL;
+ dev_priv->drrs.connector = NULL;
+ }
+}
+
void intel_dp_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+
+ if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
+ intel_dp == enc_to_intel_dp(
+ &dev_priv->drrs.connector->encoder->base))
+ intel_dp_drrs_fini(dev_priv);
+
mutex_lock(&dev->mode_config.mutex);
edp_panel_vdd_off_sync(intel_dp);
mutex_unlock(&dev->mode_config.mutex);
@@ -3751,7 +3768,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
if (downclock_mode != NULL &&
dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
- dev_priv->drrs.connector = intel_connector;
+ intel_init_drrs_idleness_detection(dev, intel_connector);
mutex_init(&intel_dp->drrs_state.mutex);
@@ -3759,7 +3776,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
DRM_INFO("seamless DRRS supported for eDP panel.\n");
- }
+ } else
+ DRM_INFO("DRRS not supported\n");
return downclock_mode;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 46fc8b3..570cc47 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -930,7 +930,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
void ilk_wm_get_hw_state(struct drm_device *dev);
-
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector);
+void intel_update_drrs(struct drm_device *dev);
+void intel_disable_drrs(struct drm_device *dev);
/* intel_sdvo.c */
bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index fd68f93..6a78fca 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -621,6 +621,144 @@ out_disable:
i915_gem_stolen_cleanup_compression(dev);
}
+static void intel_drrs_work_fn(struct work_struct *__work)
+{
+ struct intel_drrs_work *work =
+ container_of(to_delayed_work(__work),
+ struct intel_drrs_work, work);
+ struct drm_device *dev = work->crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Double check if the dual-display mode is active. */
+ if (dev_priv->drrs.is_clone)
+ return;
+
+ intel_dp_set_drrs_state(work->crtc->dev,
+ dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
+}
+
+static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
+{
+ if (dev_priv->drrs.drrs_work == NULL)
+ return;
+
+ cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
+}
+
+static void intel_enable_drrs(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ intel_cancel_drrs_work(dev_priv);
+
+ if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
+ dev_priv->drrs.drrs_work->crtc = crtc;
+
+ /* Delay the actual enabling to let pageflipping cease and the
+ * display to settle before starting DRRS
+ */
+ schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
+ msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
+ }
+}
+
+void intel_disable_drrs(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ /* as part of disable DRRS, reset refresh rate to HIGH_RR */
+ if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
+ intel_cancel_drrs_work(dev_priv);
+ intel_dp_set_drrs_state(dev,
+ dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
+ }
+}
+
+/**
+ * intel_update_drrs - enable/disable DRRS as needed
+ * @dev: the drm_device
+*/
+void intel_update_drrs(struct drm_device *dev)
+{
+ struct drm_crtc *crtc = NULL, *tmp_crtc;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* if drrs.connector is NULL, then drrs_init did not get called.
+ * which means DRRS is not supported.
+ */
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
+ return;
+
+ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+ if (tmp_crtc != NULL && intel_crtc_active(tmp_crtc)) {
+ if (crtc) {
+ DRM_DEBUG_KMS(
+ "more than one pipe active, disabling DRRS\n");
+ dev_priv->drrs.is_clone = true;
+ intel_disable_drrs(dev);
+ return;
+ }
+ crtc = tmp_crtc;
+ }
+ }
+
+ if (crtc == NULL) {
+ DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
+ return;
+ }
+
+ dev_priv->drrs.is_clone = false;
+ intel_disable_drrs(dev);
+
+ /* re-enable idleness detection */
+ intel_enable_drrs(crtc);
+}
+
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector)
+{
+ struct intel_drrs_work *work;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0) {
+ DRM_INFO("DRRS disable by flag\n");
+ return;
+ }
+
+ work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
+ if (!work) {
+ DRM_ERROR("Failed to allocate DRRS work structure\n");
+ return;
+ }
+
+ dev_priv->drrs.connector = connector;
+ dev_priv->drrs.is_clone = false;
+
+ work->interval = i915.drrs_interval;
+ INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
+
+ dev_priv->drrs.drrs_work = work;
+}
+
static void i915_pineview_get_mem_freq(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH 5/6] drm/i915/bdw: Add support for DRRS to switch RR
2014-03-28 4:44 [PATCH 0/6] v7: Enabling DRRS in the kernel Vandana Kannan
` (3 preceding siblings ...)
2014-03-28 4:45 ` [PATCH 4/6] drm/i915: Idleness detection for DRRS Vandana Kannan
@ 2014-03-28 4:45 ` Vandana Kannan
2014-04-01 13:37 ` Jani Nikula
2014-03-28 4:45 ` [PATCH 6/6] drm/i915: Support for RR switching on VLV Vandana Kannan
5 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-03-28 4:45 UTC (permalink / raw)
To: intel-gfx
For Broadwell, there is one instance of Transcoder MN values per transcoder.
For dynamic switching between multiple refreshr rates, M/N values may be
reprogrammed on the fly. Link N programming triggers update of all data and
link M & N registers and the new M/N values will be used in the next frame
that is output.
v2: Incorporated Chris's review comments
Changed to check for gen >=8 or gen > 5 before setting M/N registers
v3: Incorporated Jani's review comments
Re-use cpu_transcoder_set_m_n for BDW.
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
---
drivers/gpu/drm/i915/intel_display.c | 2 +-
drivers/gpu/drm/i915/intel_dp.c | 25 +++++++++++++++++++------
drivers/gpu/drm/i915/intel_drv.h | 2 ++
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c309561..f492b51 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5120,7 +5120,7 @@ static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
I915_WRITE(PCH_TRANS_LINK_N1(pipe), m_n->link_n);
}
-static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
+void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
struct intel_link_m_n *m_n)
{
struct drm_device *dev = crtc->base.dev;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4f0281a..6cdbb38 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -743,11 +743,15 @@ intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
struct drm_i915_private *dev_priv = dev->dev_private;
enum transcoder transcoder = crtc->config.cpu_transcoder;
- I915_WRITE(PIPE_DATA_M2(transcoder),
- TU_SIZE(m_n->tu) | m_n->gmch_m);
- I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
- I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
- I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
+ if (INTEL_INFO(dev)->gen >= 8) {
+ intel_cpu_transcoder_set_m_n(crtc, m_n);
+ } else if (INTEL_INFO(dev)->gen > 6) {
+ I915_WRITE(PIPE_DATA_M2(transcoder),
+ TU_SIZE(m_n->tu) | m_n->gmch_m);
+ I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
+ I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
+ I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
+ }
}
bool
@@ -3704,7 +3708,16 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
return;
}
- if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) {
+ if (INTEL_INFO(dev)->gen >= 8) {
+ switch (index) {
+ case DRRS_HIGH_RR:
+ intel_dp_set_m2_n2(intel_crtc, &config->dp_m_n);
+ break;
+ case DRRS_LOW_RR:
+ intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
+ break;
+ };
+ } else if (INTEL_INFO(dev)->gen > 6) {
reg = PIPECONF(intel_crtc->config.cpu_transcoder);
val = I915_READ(reg);
if (index > DRRS_HIGH_RR) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 570cc47..e4b479e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -770,6 +770,8 @@ int valleyview_get_vco(struct drm_i915_private *dev_priv);
void intel_mode_from_pipe_config(struct drm_display_mode *mode,
struct intel_crtc_config *pipe_config);
int intel_format_to_fourcc(int format);
+void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
+ struct intel_link_m_n *m_n);
/* intel_dp.c */
void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH 6/6] drm/i915: Support for RR switching on VLV
2014-03-28 4:44 [PATCH 0/6] v7: Enabling DRRS in the kernel Vandana Kannan
` (4 preceding siblings ...)
2014-03-28 4:45 ` [PATCH 5/6] drm/i915/bdw: Add support for DRRS to switch RR Vandana Kannan
@ 2014-03-28 4:45 ` Vandana Kannan
2014-04-01 13:41 ` Jani Nikula
5 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-03-28 4:45 UTC (permalink / raw)
To: intel-gfx
Definition of VLV RR switch bit and corresponding toggling in
set_drrs function.
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Signed-off-by: Uma Shankar <uma.shankar@intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 1 +
drivers/gpu/drm/i915/intel_dp.c | 10 ++++++++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 04fc64a..435ed64 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3257,6 +3257,7 @@ enum punit_power_well {
#define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
+#define PIPECONF_EDP_RR_MODE_SWITCH_VLV (1 << 14)
#define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
#define PIPECONF_BPC_MASK (0x7 << 5)
#define PIPECONF_8BPC (0<<5)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6cdbb38..79d880b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3721,10 +3721,16 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
reg = PIPECONF(intel_crtc->config.cpu_transcoder);
val = I915_READ(reg);
if (index > DRRS_HIGH_RR) {
- val |= PIPECONF_EDP_RR_MODE_SWITCH;
+ if (IS_VALLEYVIEW(dev))
+ val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+ else
+ val |= PIPECONF_EDP_RR_MODE_SWITCH;
intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
} else {
- val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
+ if (IS_VALLEYVIEW(dev))
+ val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
+ else
+ val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
}
I915_WRITE(reg, val);
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature
2014-03-28 4:44 ` [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature Vandana Kannan
@ 2014-04-01 13:04 ` Jani Nikula
2014-04-01 17:26 ` Daniel Vetter
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-01 13:04 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
>
> This patch reads the DRRS support and Mode type from VBT fields.
> The read information will be stored in VBT struct during BIOS
> parsing. The above functionality is needed for decision making
> whether DRRS feature is supported in i915 driver for eDP panels.
> This information helps us decide if seamless DRRS can be done
> at runtime to support certain power saving features. This patch
> was tested by setting necessary bit in VBT struct and merging
> the new VBT with system BIOS so that we can read the value.
>
> v2: Incorporated review comments from Chris Wilson
> Removed "intel_" as a prefix for DRRS specific declarations.
>
> v3: Incorporated Jani's review comments
> Removed function which deducts drrs mode from panel_type. Modified some
> print statements. Made changes to use DRRS_NOT_SUPPORTED as 0 instead of -1.
>
> v4: Incorporated Jani's review comments.
> Modifications around setting vbt drrs_type.
>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++++
> drivers/gpu/drm/i915/intel_bios.c | 34 +++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/i915/intel_bios.h | 29 +++++++++++++++++++++++++++++
> 3 files changed, 74 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 9b8c1e0..cd73a33 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1284,6 +1284,12 @@ struct ddi_vbt_port_info {
> uint8_t supports_dp:1;
> };
>
> +enum drrs_support_type {
> + DRRS_NOT_SUPPORTED = 0,
> + STATIC_DRRS_SUPPORT = 1,
> + SEAMLESS_DRRS_SUPPORT = 2
> +};
> +
> struct intel_vbt_data {
> struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
> struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
> @@ -1299,6 +1305,12 @@ struct intel_vbt_data {
> int lvds_ssc_freq;
> unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
>
> + /*
> + * DRRS support type (Seamless OR Static DRRS OR not supported)
> + * These values correspond to the VBT values for drrs mode.
No, they don't correspond to VBT values, because we're adding that enum,
and we map the VBT values to the enum.
With that fixed,
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> + */
> + enum drrs_support_type drrs_type;
> +
> /* eDP */
> int edp_rate;
> int edp_lanes;
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 4867f4c..9b98677 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -206,7 +206,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
> const struct lvds_dvo_timing *panel_dvo_timing;
> const struct lvds_fp_timing *fp_timing;
> struct drm_display_mode *panel_fixed_mode;
> - int i, downclock;
> + int i, downclock, drrs_mode;
>
> lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
> if (!lvds_options)
> @@ -218,6 +218,28 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
>
> panel_type = lvds_options->panel_type;
>
> + drrs_mode = (lvds_options->dps_panel_type_bits
> + >> (panel_type * 2)) & MODE_MASK;
> + /*
> + * VBT has static DRRS = 0 and seamless DRRS = 2.
> + * The below piece of code is required to adjust vbt.drrs_type
> + * to match the enum drrs_support_type.
> + */
> + switch (drrs_mode) {
> + case 0:
> + dev_priv->vbt.drrs_type = STATIC_DRRS_SUPPORT;
> + DRM_DEBUG_KMS("DRRS supported mode is static\n");
> + break;
> + case 2:
> + dev_priv->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT;
> + DRM_DEBUG_KMS("DRRS supported mode is seamless\n");
> + break;
> + default:
> + dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
> + DRM_DEBUG_KMS("DRRS not supported (VBT input)\n");
> + break;
> + }
> +
> lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
> if (!lvds_lfp_data)
> return;
> @@ -516,6 +538,16 @@ parse_driver_features(struct drm_i915_private *dev_priv,
>
> if (driver->dual_frequency)
> dev_priv->render_reclock_avail = true;
> +
> + DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled);
> + /*
> + * If DRRS is not supported, drrs_type has to be set to 0.
> + * This is because, VBT is configured in such a way that
> + * static DRRS is 0 and DRRS not supported is represented by
> + * driver->drrs_enabled=false
> + */
> + if (!driver->drrs_enabled)
> + dev_priv->vbt.drrs_type = DRRS_NOT_SUPPORTED;
> }
>
> static void
> diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
> index 83b7629..d02e5f9 100644
> --- a/drivers/gpu/drm/i915/intel_bios.h
> +++ b/drivers/gpu/drm/i915/intel_bios.h
> @@ -282,6 +282,9 @@ struct bdb_general_definitions {
> union child_device_config devices[0];
> } __packed;
>
> +/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
> +#define MODE_MASK 0x3
> +
> struct bdb_lvds_options {
> u8 panel_type;
> u8 rsvd1;
> @@ -294,6 +297,18 @@ struct bdb_lvds_options {
> u8 lvds_edid:1;
> u8 rsvd2:1;
> u8 rsvd4;
> + /* LVDS Panel channel bits stored here */
> + u32 lvds_panel_channel_bits;
> + /* LVDS SSC (Spread Spectrum Clock) bits stored here. */
> + u16 ssc_bits;
> + u16 ssc_freq;
> + u16 ssc_ddt;
> + /* Panel color depth defined here */
> + u16 panel_color_depth;
> + /* LVDS panel type bits stored here */
> + u32 dps_panel_type_bits;
> + /* LVDS backlight control type bits stored here */
> + u32 blt_control_type_bits;
> } __packed;
>
> /* LFP pointer table contains entries to the struct below */
> @@ -479,6 +494,20 @@ struct bdb_driver_features {
>
> u8 hdmi_termination;
> u8 custom_vbt_version;
> + /* Driver features data block */
> + u16 rmpm_enabled:1;
> + u16 s2ddt_enabled:1;
> + u16 dpst_enabled:1;
> + u16 bltclt_enabled:1;
> + u16 adb_enabled:1;
> + u16 drrs_enabled:1;
> + u16 grs_enabled:1;
> + u16 gpmt_enabled:1;
> + u16 tbt_enabled:1;
> + u16 psr_enabled:1;
> + u16 ips_enabled:1;
> + u16 reserved3:4;
> + u16 pc_feature_valid:1;
> } __packed;
>
> #define EDP_18BPP 0
> --
> 1.7.9.5
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-03-28 4:44 ` [PATCH 2/6] drm/i915: Parse EDID probed modes for DRRS support Vandana Kannan
@ 2014-04-01 13:17 ` Jani Nikula
2014-04-03 11:10 ` [PATCH v8 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-01 13:17 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
>
> This patch and finds out the lowest refresh rate supported for the resolution
> same as the fixed_mode.
> It also checks the VBT fields to see if panel supports seamless DRRS or not.
> Based on above data it marks whether eDP panel supports seamless DRRS or not.
> This information is needed for supporting seamless DRRS switch for certain
> power saving usecases. This patch is tested by enabling the DRM logs and
> user should see whether Seamless DRRS is supported or not.
>
> v2: Daniel's review comments
> Modified downclock deduction based on intel_find_panel_downclock
>
> v3: Chris's review comments
> Moved edp_downclock_avail and edp_downclock to intel_panel
>
> v4: Jani's review comments.
> Changed name of the enum edp_panel_type to drrs_support type.
> Change is_drrs_supported to drrs_support of type enum drrs_support_type.
>
> v5: Incorporated Jani's review comments
> Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
> and above.
>
> v6: Incorporated Chris's review comments.
> Changed initialize to init in intel_drrs_initialize
>
> v7: Incorporated Jani's review comments.
> Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
> Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/intel_dp.c | 53 +++++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++
> 2 files changed, 68 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 59ee4dc..f2735de 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3611,6 +3611,51 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> I915_READ(pp_div_reg));
> }
>
> +static struct drm_display_mode *
> +intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> + struct intel_connector *intel_connector,
> + struct drm_display_mode *fixed_mode)
> +{
> + struct drm_connector *connector = &intel_connector->base;
> + struct intel_dp *intel_dp = &intel_dig_port->dp;
> + struct drm_device *dev = intel_dig_port->base.base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct drm_display_mode *downclock_mode = NULL;
> +
> + if (INTEL_INFO(dev)->gen <= 6) {
> + DRM_INFO("DRRS supported for Gen7 and above\n");
I think DRM_INFO is excessive.
> + return NULL;
> + }
> +
> + /**
It's not a kernel-doc comment, so please don't add double **. See
Documentation/kernel-doc-nano-HOWTO.txt what kernel-doc is about.
> + * Check if PSR is supported by panel and enabled
> + * if so then DRRS is reported as not supported for Haswell.
> + */
> + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
> + DRM_INFO("eDP panel has PSR enabled. Cannot support DRRS\n");
I don't think this should be a an init time decision. Rather, you need
to make sure psr and drrs are not enabled at the same time. Right?
Now, if psr just so happens to be enabled at this very specific time
during driver init (which is pretty arbitrary) you won't be able to
enable drrs later on even if you disable psr. Isn't that so?
> + return NULL;
> + }
> +
> + /* First check if DRRS is enabled from VBT struct */
Please don't add comments that are obvious from the code.
(I really wouldn't care otherwise, but it bugs me that it claims "first"
when it's the third thing you check. Such things will get stale over
time anyway as the code evolves.)
> + if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
> + DRM_INFO("VBT doesn't support DRRS\n");
> + return NULL;
> + }
> +
> + downclock_mode = intel_find_panel_downclock
> + (dev, fixed_mode, connector);
> +
> + if (downclock_mode != NULL &&
> + dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
> + intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> +
> + intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> + DRM_INFO("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,
> struct edp_power_seq *power_seq)
> @@ -3620,10 +3665,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> struct drm_device *dev = intel_dig_port->base.base.dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct drm_display_mode *fixed_mode = NULL;
> + struct drm_display_mode *downclock_mode = NULL;
> bool has_dpcd;
> struct drm_display_mode *scan;
> struct edid *edid;
>
> + intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
> +
> if (!is_edp(intel_dp))
> return true;
>
> @@ -3665,6 +3713,9 @@ 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_dig_port,
> + intel_connector, fixed_mode);
> break;
> }
> }
> @@ -3677,7 +3728,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
> }
>
> - intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> + intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> intel_panel_setup_backlight(connector);
>
> return true;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index fa99104..d781165 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -483,6 +483,17 @@ struct intel_hdmi {
>
> #define DP_MAX_DOWNSTREAM_PORTS 0x10
>
> +/**
> + * 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 edp_drrs_refresh_rate_type {
> + DRRS_HIGH_RR,
> + DRRS_LOW_RR,
> + DRRS_MAX_RR, /* RR count */
> +};
> +
> struct intel_dp {
> uint32_t output_reg;
> uint32_t aux_ch_ctl_reg;
> @@ -521,6 +532,11 @@ struct intel_dp {
> bool has_aux_irq,
> int send_bytes,
> uint32_t aux_clock_divider);
> + struct {
> + enum drrs_support_type type;
> + enum edp_drrs_refresh_rate_type refresh_rate_type;
> + } drrs_state;
> +
> };
>
> struct intel_digital_port {
> --
> 1.7.9.5
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/6] drm/i915: Add support for DRRS to switch RR
2014-03-28 4:44 ` [PATCH 3/6] drm/i915: Add support for DRRS to switch RR Vandana Kannan
@ 2014-04-01 13:25 ` Jani Nikula
2014-04-02 5:58 ` Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-01 13:25 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
>
> This patch computes and stored 2nd M/N/TU for switching to different
> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
> between alternate refresh rates programmed in 2nd M/N/TU registers.
>
> v2: Daniel's review comments
> Computing M2/N2 in compute_config and storing it in crtc_config
>
> v3: Modified reference to edp_downclock and edp_downclock_avail based on the
> changes made to move them from dev_private to intel_panel.
>
> v4: Modified references to is_drrs_supported based on the changes made to
> rename it to drrs_support.
>
> v5: Jani's review comments
> Removed superfluous return statements. Changed support for Gen 7 and above.
> Corrected indentation. Re-structured the code which finds crtc and connector
> from encoder. Changed some logs to be less verbose.
>
> v6: Modifying i915_drrs to include only intel connector as intel_dp can be
> derived from intel connector when required.
>
> v7: As per internal review comments, acquiring mutex just before accessing
> drrs RR. As per Chris's review comments, added documentation about the use
> of locking in the function.
>
> v8: Incorporated Jani's review comments.
> Removed reference to edp_downclock.
>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 5 ++
> drivers/gpu/drm/i915/i915_reg.h | 1 +
> drivers/gpu/drm/i915/intel_dp.c | 108 ++++++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_drv.h | 6 ++-
> 4 files changed, 119 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index cd73a33..1c9d5cf 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -794,6 +794,10 @@ struct i915_fbc {
> } no_fbc_reason;
> };
>
> +struct i915_drrs {
> + struct intel_connector *connector;
> +};
> +
> struct i915_psr {
> bool sink_support;
> bool source_ok;
> @@ -1497,6 +1501,7 @@ typedef struct drm_i915_private {
> struct timer_list hotplug_reenable_timer;
>
> struct i915_fbc fbc;
> + struct i915_drrs drrs;
> struct intel_opregion opregion;
> struct intel_vbt_data vbt;
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 74f7d85..04fc64a 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3255,6 +3255,7 @@ enum punit_power_well {
> #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
> #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
> #define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
> +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
> #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
> #define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
> #define PIPECONF_BPC_MASK (0x7 << 5)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index f2735de..9640df1 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -736,6 +736,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
> }
> }
>
> +static void
> +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + enum transcoder transcoder = crtc->config.cpu_transcoder;
> +
> + I915_WRITE(PIPE_DATA_M2(transcoder),
> + TU_SIZE(m_n->tu) | m_n->gmch_m);
> + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
> + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
> + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
> +}
> +
> bool
> intel_dp_compute_config(struct intel_encoder *encoder,
> struct intel_crtc_config *pipe_config)
> @@ -840,6 +854,15 @@ found:
> pipe_config->port_clock,
> &pipe_config->dp_m_n);
>
> + if (intel_connector->panel.downclock_mode != NULL &&
> + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
> + intel_link_compute_m_n(bpp, lane_count,
> + intel_connector->panel.downclock_mode->clock,
> + pipe_config->port_clock,
> + &pipe_config->dp_m2_n2);
> + }
> +
> +
> intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
>
> return true;
> @@ -3611,6 +3634,87 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> I915_READ(pp_div_reg));
> }
>
> +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_dp *intel_dp = NULL;
> + struct intel_crtc_config *config = NULL;
> + struct intel_crtc *intel_crtc = NULL;
> + struct intel_connector *intel_connector = dev_priv->drrs.connector;
> + u32 reg, val;
> + int index = 0;
enum edp_drrs_refresh_rate.
> +
> + if (refresh_rate <= 0) {
> + DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n");
> + return;
> + }
> +
> + if (intel_connector == NULL) {
> + DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
> + return;
> + }
> +
> + encoder = intel_attached_encoder(&intel_connector->base);
> + intel_dp = enc_to_intel_dp(&encoder->base);
> + intel_crtc = encoder->new_crtc;
> +
> + if (!intel_crtc) {
> + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
> + return;
> + }
> +
> + config = &intel_crtc->config;
> +
> + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
> + DRM_DEBUG_KMS("Seamless DRRS not supported.\n");
Isn't seamless the only thing that *is* supported?
> + return;
> + }
> +
> + if (intel_connector->panel.fixed_mode->vrefresh == refresh_rate)
> + index = DRRS_HIGH_RR;
> + else
> + index = DRRS_LOW_RR;
> +
> + if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
Can we end up here when drrs is not supported by the platform?
> + reg = PIPECONF(intel_crtc->config.cpu_transcoder);
> + val = I915_READ(reg);
> + if (index > DRRS_HIGH_RR) {
> + val |= PIPECONF_EDP_RR_MODE_SWITCH;
> + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
> + } else {
> + val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
> + }
> + I915_WRITE(reg, val);
> + }
> +
> + /*
> + * mutex taken to ensure that there is no race between differnt
> + * drrs calls trying to update refresh rate. This scenario may occur
> + * in future when idleness detection based DRRS in kernel and
> + * possible calls from user space to set differnt RR are made.
> + */
> +
> + mutex_lock(&intel_dp->drrs_state.mutex);
> +
> + intel_dp->drrs_state.refresh_rate_type = index;
> +
> + mutex_unlock(&intel_dp->drrs_state.mutex);
> +
> + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
> +}
> +
> static struct drm_display_mode *
> intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> struct intel_connector *intel_connector,
> @@ -3647,6 +3751,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>
> if (downclock_mode != NULL &&
> dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
> + dev_priv->drrs.connector = intel_connector;
> +
> + mutex_init(&intel_dp->drrs_state.mutex);
> +
> intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
>
> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d781165..46fc8b3 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -305,6 +305,9 @@ struct intel_crtc_config {
> int pipe_bpp;
> struct intel_link_m_n dp_m_n;
>
> + /* m2_n2 for eDP downclock */
> + struct intel_link_m_n dp_m2_n2;
> +
> /*
> * Frequence the dpll for the port should run at. Differs from the
> * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
> @@ -535,6 +538,7 @@ struct intel_dp {
> struct {
> enum drrs_support_type type;
> enum edp_drrs_refresh_rate_type refresh_rate_type;
> + struct mutex mutex;
> } drrs_state;
>
> };
> @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
> void intel_edp_psr_enable(struct intel_dp *intel_dp);
> void intel_edp_psr_disable(struct intel_dp *intel_dp);
> void intel_edp_psr_update(struct drm_device *dev);
> -
> +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
>
> /* intel_dsi.c */
> bool intel_dsi_init(struct drm_device *dev);
> --
> 1.7.9.5
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 4/6] drm/i915: Idleness detection for DRRS
2014-03-28 4:45 ` [PATCH 4/6] drm/i915: Idleness detection for DRRS Vandana Kannan
@ 2014-04-01 13:36 ` Jani Nikula
2014-04-03 11:17 ` [PATCH v9 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-01 13:36 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> Adding support to detect display idleness by tracking page flip from
> user space. Switch to low refresh rate is triggered after 2 seconds of
> idleness. The delay is configurable. If there is a page flip or call to
> update the plane, then high refresh rate is applied.
> The feature is not used in dual-display mode.
>
> v2: Chris Wilson's review comments incorporated.
> Modify idleness detection implementation to make it similar to the
> implementation of intel_update_fbc/intel_disable_fbc
>
> v3: Internal review comments incorporated
> Add NULL pointer check in intel_disable_drrs.
> Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
>
> v4: Jani's review comments incorporated.
> Change in sequence in intel_update_drrs. Comment modified to remove details
> of update param. Modified DRRS idleness interval to a module parameter.
>
> v5: Chris's review comments incorporated.
> Initialize connector in idleness detection init. Modifications made to
> use only intel_connector in i915_drrs and derive intel_dp when required.
> Added a function drrs_fini to cleanup DRRS work.
>
> v6: Internal review comments. Removed check for primary enabled, which is
> a redundant check, in the case of clone mode. Added a flag to track
> dual-display configuration. Remove print statement for "cancel DRR work"
> and print "DRRS not supported" only once.
>
> v7: As per internal review comments, removing calls to update/disable drrs
> from sprite update path. For sprite, all drrs related updates would be
> taken care of with calls to crtc page flip itself. This will have to be
> revisited later if flip infrastructure changes for sprite.
>
> v8: Incorporated Jani's review comments. Added space after the periods in the
> module param description. Changes around drrs-fini to remove seamless DRRS
> check.
>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 7 ++
> drivers/gpu/drm/i915/i915_params.c | 8 ++
> drivers/gpu/drm/i915/intel_display.c | 16 ++++
> drivers/gpu/drm/i915/intel_dp.c | 22 +++++-
> drivers/gpu/drm/i915/intel_drv.h | 5 +-
> drivers/gpu/drm/i915/intel_pm.c | 138 ++++++++++++++++++++++++++++++++++
> 6 files changed, 193 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 1c9d5cf..c4e9b37 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -796,6 +796,12 @@ struct i915_fbc {
>
> struct i915_drrs {
> struct intel_connector *connector;
> + bool is_clone;
> + struct intel_drrs_work {
> + struct delayed_work work;
> + struct drm_crtc *crtc;
> + int interval;
> + } *drrs_work;
> };
>
> struct i915_psr {
> @@ -2092,6 +2098,7 @@ struct i915_params {
> int enable_ips;
> int invert_brightness;
> int enable_cmd_parser;
> + int drrs_interval;
> /* leave bools at the end to not create holes */
> bool enable_hangcheck;
> bool fastboot;
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index d1d7980..05ca0a0 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
> .invert_brightness = 0,
> .disable_display = 0,
> .enable_cmd_parser = 0,
> + .drrs_interval = 2000,
> };
>
> module_param_named(modeset, i915.modeset, int, 0400);
> @@ -152,3 +153,10 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
> module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
> MODULE_PARM_DESC(enable_cmd_parser,
> "Enable command parsing (1=enabled, 0=disabled [default])");
> +
> +module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
> +MODULE_PARM_DESC(drrs_interval,
> + "DRRS idleness detection interval (default: 2000 ms). "
> + "If this field is set to 0, then seamless DRRS feature "
> + "based on idleness detection is disabled. "
> + "The interval is to be set in milliseconds.");
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7e4ea8d..c309561 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2542,6 +2542,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> intel_edp_psr_update(dev);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -3708,6 +3709,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> @@ -3751,6 +3753,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
>
> drm_vblank_on(dev, pipe);
> @@ -3948,6 +3951,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
> }
>
> @@ -3995,6 +3999,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
> }
>
> @@ -4391,6 +4396,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
> intel_crtc_update_cursor(crtc, true);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->enable(encoder);
> @@ -4438,6 +4444,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
> intel_crtc_dpms_overlay(intel_crtc, true);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->enable(encoder);
> @@ -4505,6 +4512,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
> intel_update_watermarks(crtc);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> }
>
> static void i9xx_crtc_off(struct drm_crtc *crtc)
> @@ -8508,6 +8516,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
> drm_gem_object_unreference(&work->pending_flip_obj->base);
> drm_gem_object_unreference(&work->old_fb_obj->base);
>
> + /* disable current DRRS work scheduled and restart
> + * to push work by another x seconds
> + */
> + intel_update_drrs(dev);
> intel_update_fbc(dev);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -8966,6 +8978,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> goto cleanup_pending;
>
> intel_disable_fbc(dev);
> + intel_disable_drrs(dev);
> intel_mark_fb_busy(obj, NULL);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -11338,6 +11351,7 @@ void intel_modeset_init(struct drm_device *dev)
>
> /* Just in case the BIOS is doing something questionable. */
> intel_disable_fbc(dev);
> + intel_disable_drrs(dev);
>
> mutex_lock(&dev->mode_config.mutex);
> intel_modeset_setup_hw_state(dev, false);
> @@ -11803,6 +11817,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
>
> intel_disable_fbc(dev);
>
> + intel_disable_drrs(dev);
> +
> intel_disable_gt_powersave(dev);
>
> ironlake_teardown_rc6(dev);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 9640df1..4f0281a 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3351,16 +3351,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
> kfree(connector);
> }
>
> +static void
> +intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
> +{
> + if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
> + kfree(dev_priv->drrs.drrs_work);
> + dev_priv->drrs.drrs_work = NULL;
> + dev_priv->drrs.connector = NULL;
> + }
> +}
> +
> void intel_dp_encoder_destroy(struct drm_encoder *encoder)
> {
> struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
> struct intel_dp *intel_dp = &intel_dig_port->dp;
> struct drm_device *dev = intel_dp_to_dev(intel_dp);
> + struct drm_i915_private *dev_priv = dev->dev_private;
>
> drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
> drm_encoder_cleanup(encoder);
> if (is_edp(intel_dp)) {
> cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +
> + if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
> + intel_dp == enc_to_intel_dp(
> + &dev_priv->drrs.connector->encoder->base))
> + intel_dp_drrs_fini(dev_priv);
> +
> mutex_lock(&dev->mode_config.mutex);
> edp_panel_vdd_off_sync(intel_dp);
> mutex_unlock(&dev->mode_config.mutex);
> @@ -3751,7 +3768,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>
> if (downclock_mode != NULL &&
> dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
> - dev_priv->drrs.connector = intel_connector;
> + intel_init_drrs_idleness_detection(dev, intel_connector);
>
> mutex_init(&intel_dp->drrs_state.mutex);
>
> @@ -3759,7 +3776,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>
> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> DRM_INFO("seamless DRRS supported for eDP panel.\n");
> - }
> + } else
> + DRM_INFO("DRRS not supported\n");
>
> return downclock_mode;
> }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 46fc8b3..570cc47 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -930,7 +930,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> void ilk_wm_get_hw_state(struct drm_device *dev);
> -
> +void intel_init_drrs_idleness_detection(struct drm_device *dev,
> + struct intel_connector *connector);
> +void intel_update_drrs(struct drm_device *dev);
> +void intel_disable_drrs(struct drm_device *dev);
>
> /* intel_sdvo.c */
> bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index fd68f93..6a78fca 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -621,6 +621,144 @@ out_disable:
> i915_gem_stolen_cleanup_compression(dev);
> }
>
> +static void intel_drrs_work_fn(struct work_struct *__work)
> +{
> + struct intel_drrs_work *work =
> + container_of(to_delayed_work(__work),
> + struct intel_drrs_work, work);
> + struct drm_device *dev = work->crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + /* Double check if the dual-display mode is active. */
> + if (dev_priv->drrs.is_clone)
> + return;
> +
> + intel_dp_set_drrs_state(work->crtc->dev,
> + dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
> +}
> +
> +static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
> +{
> + if (dev_priv->drrs.drrs_work == NULL)
> + return;
> +
> + cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
> +}
> +
> +static void intel_enable_drrs(struct drm_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_dp *intel_dp = NULL;
> +
> + intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
> +
> + if (intel_dp == NULL)
> + return;
> +
> + intel_cancel_drrs_work(dev_priv);
> +
> + if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
> + dev_priv->drrs.drrs_work->crtc = crtc;
> +
> + /* Delay the actual enabling to let pageflipping cease and the
> + * display to settle before starting DRRS
> + */
> + schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
> + msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
> + }
> +}
> +
> +void intel_disable_drrs(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_dp *intel_dp = NULL;
> +
> + if (dev_priv->drrs.connector == NULL)
> + return;
> +
> + intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
> +
> + if (intel_dp == NULL)
> + return;
> +
> + /* as part of disable DRRS, reset refresh rate to HIGH_RR */
> + if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
> + intel_cancel_drrs_work(dev_priv);
> + intel_dp_set_drrs_state(dev,
> + dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
> + }
> +}
> +
> +/**
> + * intel_update_drrs - enable/disable DRRS as needed
> + * @dev: the drm_device
> +*/
> +void intel_update_drrs(struct drm_device *dev)
> +{
> + struct drm_crtc *crtc = NULL, *tmp_crtc;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + /* if drrs.connector is NULL, then drrs_init did not get called.
> + * which means DRRS is not supported.
> + */
> + if (dev_priv->drrs.connector == NULL)
> + return;
> +
> + if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
> + return;
> +
> + list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
> + if (tmp_crtc != NULL && intel_crtc_active(tmp_crtc)) {
I don't think it's possible for tmp_crtc to be NULL here.
> + if (crtc) {
> + DRM_DEBUG_KMS(
> + "more than one pipe active, disabling DRRS\n");
> + dev_priv->drrs.is_clone = true;
> + intel_disable_drrs(dev);
> + return;
> + }
> + crtc = tmp_crtc;
> + }
> + }
> +
> + if (crtc == NULL) {
> + DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
> + return;
> + }
> +
> + dev_priv->drrs.is_clone = false;
> + intel_disable_drrs(dev);
> +
> + /* re-enable idleness detection */
> + intel_enable_drrs(crtc);
> +}
> +
> +void intel_init_drrs_idleness_detection(struct drm_device *dev,
> + struct intel_connector *connector)
> +{
> + struct intel_drrs_work *work;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (i915.drrs_interval == 0) {
> + DRM_INFO("DRRS disable by flag\n");
You've added the module parameter with 0600 permission, i.e. the user
can modify it runtime. What happens if the user boots with
i915.drrs_interval=0 but later sets it to a meaningful value?
I think it will be a useful feature to be able to have drrs disabled by
default at boot, to be enabled later.
> + return;
> + }
> +
> + work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
> + if (!work) {
> + DRM_ERROR("Failed to allocate DRRS work structure\n");
> + return;
> + }
> +
> + dev_priv->drrs.connector = connector;
> + dev_priv->drrs.is_clone = false;
> +
> + work->interval = i915.drrs_interval;
> + INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
> +
> + dev_priv->drrs.drrs_work = work;
> +}
> +
> static void i915_pineview_get_mem_freq(struct drm_device *dev)
> {
> drm_i915_private_t *dev_priv = dev->dev_private;
> --
> 1.7.9.5
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 5/6] drm/i915/bdw: Add support for DRRS to switch RR
2014-03-28 4:45 ` [PATCH 5/6] drm/i915/bdw: Add support for DRRS to switch RR Vandana Kannan
@ 2014-04-01 13:37 ` Jani Nikula
0 siblings, 0 replies; 40+ messages in thread
From: Jani Nikula @ 2014-04-01 13:37 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> For Broadwell, there is one instance of Transcoder MN values per transcoder.
> For dynamic switching between multiple refreshr rates, M/N values may be
> reprogrammed on the fly. Link N programming triggers update of all data and
> link M & N registers and the new M/N values will be used in the next frame
> that is output.
>
> v2: Incorporated Chris's review comments
> Changed to check for gen >=8 or gen > 5 before setting M/N registers
>
> v3: Incorporated Jani's review comments
> Re-use cpu_transcoder_set_m_n for BDW.
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> ---
> drivers/gpu/drm/i915/intel_display.c | 2 +-
> drivers/gpu/drm/i915/intel_dp.c | 25 +++++++++++++++++++------
> drivers/gpu/drm/i915/intel_drv.h | 2 ++
> 3 files changed, 22 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c309561..f492b51 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5120,7 +5120,7 @@ static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
> I915_WRITE(PCH_TRANS_LINK_N1(pipe), m_n->link_n);
> }
>
> -static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
> +void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
> struct intel_link_m_n *m_n)
> {
> struct drm_device *dev = crtc->base.dev;
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4f0281a..6cdbb38 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -743,11 +743,15 @@ intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
> struct drm_i915_private *dev_priv = dev->dev_private;
> enum transcoder transcoder = crtc->config.cpu_transcoder;
>
> - I915_WRITE(PIPE_DATA_M2(transcoder),
> - TU_SIZE(m_n->tu) | m_n->gmch_m);
> - I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
> - I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
> - I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
> + if (INTEL_INFO(dev)->gen >= 8) {
> + intel_cpu_transcoder_set_m_n(crtc, m_n);
> + } else if (INTEL_INFO(dev)->gen > 6) {
> + I915_WRITE(PIPE_DATA_M2(transcoder),
> + TU_SIZE(m_n->tu) | m_n->gmch_m);
> + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
> + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
> + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
> + }
> }
>
> bool
> @@ -3704,7 +3708,16 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
> return;
> }
>
> - if (INTEL_INFO(dev)->gen > 6 && INTEL_INFO(dev)->gen < 8) {
> + if (INTEL_INFO(dev)->gen >= 8) {
> + switch (index) {
> + case DRRS_HIGH_RR:
> + intel_dp_set_m2_n2(intel_crtc, &config->dp_m_n);
> + break;
> + case DRRS_LOW_RR:
> + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
> + break;
> + };
> + } else if (INTEL_INFO(dev)->gen > 6) {
> reg = PIPECONF(intel_crtc->config.cpu_transcoder);
> val = I915_READ(reg);
> if (index > DRRS_HIGH_RR) {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 570cc47..e4b479e 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -770,6 +770,8 @@ int valleyview_get_vco(struct drm_i915_private *dev_priv);
> void intel_mode_from_pipe_config(struct drm_display_mode *mode,
> struct intel_crtc_config *pipe_config);
> int intel_format_to_fourcc(int format);
> +void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
> + struct intel_link_m_n *m_n);
>
> /* intel_dp.c */
> void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
> --
> 1.7.9.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 6/6] drm/i915: Support for RR switching on VLV
2014-03-28 4:45 ` [PATCH 6/6] drm/i915: Support for RR switching on VLV Vandana Kannan
@ 2014-04-01 13:41 ` Jani Nikula
0 siblings, 0 replies; 40+ messages in thread
From: Jani Nikula @ 2014-04-01 13:41 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> Definition of VLV RR switch bit and corresponding toggling in
> set_drrs function.
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Signed-off-by: Uma Shankar <uma.shankar@intel.com>
> ---
> drivers/gpu/drm/i915/i915_reg.h | 1 +
> drivers/gpu/drm/i915/intel_dp.c | 10 ++++++++--
> 2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 04fc64a..435ed64 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3257,6 +3257,7 @@ enum punit_power_well {
> #define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
> #define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
> #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
> +#define PIPECONF_EDP_RR_MODE_SWITCH_VLV (1 << 14)
> #define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
> #define PIPECONF_BPC_MASK (0x7 << 5)
> #define PIPECONF_8BPC (0<<5)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 6cdbb38..79d880b 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3721,10 +3721,16 @@ void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate)
> reg = PIPECONF(intel_crtc->config.cpu_transcoder);
> val = I915_READ(reg);
> if (index > DRRS_HIGH_RR) {
> - val |= PIPECONF_EDP_RR_MODE_SWITCH;
> + if (IS_VALLEYVIEW(dev))
> + val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
> + else
> + val |= PIPECONF_EDP_RR_MODE_SWITCH;
> intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
> } else {
> - val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
> + if (IS_VALLEYVIEW(dev))
> + val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
> + else
> + val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
> }
> I915_WRITE(reg, val);
> }
> --
> 1.7.9.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature
2014-04-01 13:04 ` Jani Nikula
@ 2014-04-01 17:26 ` Daniel Vetter
0 siblings, 0 replies; 40+ messages in thread
From: Daniel Vetter @ 2014-04-01 17:26 UTC (permalink / raw)
To: Jani Nikula; +Cc: intel-gfx
On Tue, Apr 01, 2014 at 04:04:44PM +0300, Jani Nikula wrote:
> On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> > From: Pradeep Bhat <pradeep.bhat@intel.com>
> >
> > This patch reads the DRRS support and Mode type from VBT fields.
> > The read information will be stored in VBT struct during BIOS
> > parsing. The above functionality is needed for decision making
> > whether DRRS feature is supported in i915 driver for eDP panels.
> > This information helps us decide if seamless DRRS can be done
> > at runtime to support certain power saving features. This patch
> > was tested by setting necessary bit in VBT struct and merging
> > the new VBT with system BIOS so that we can read the value.
> >
> > v2: Incorporated review comments from Chris Wilson
> > Removed "intel_" as a prefix for DRRS specific declarations.
> >
> > v3: Incorporated Jani's review comments
> > Removed function which deducts drrs mode from panel_type. Modified some
> > print statements. Made changes to use DRRS_NOT_SUPPORTED as 0 instead of -1.
> >
> > v4: Incorporated Jani's review comments.
> > Modifications around setting vbt drrs_type.
> >
> > Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> > Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> > Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++++
> > drivers/gpu/drm/i915/intel_bios.c | 34 +++++++++++++++++++++++++++++++++-
> > drivers/gpu/drm/i915/intel_bios.h | 29 +++++++++++++++++++++++++++++
> > 3 files changed, 74 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 9b8c1e0..cd73a33 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1284,6 +1284,12 @@ struct ddi_vbt_port_info {
> > uint8_t supports_dp:1;
> > };
> >
> > +enum drrs_support_type {
> > + DRRS_NOT_SUPPORTED = 0,
> > + STATIC_DRRS_SUPPORT = 1,
> > + SEAMLESS_DRRS_SUPPORT = 2
> > +};
> > +
> > struct intel_vbt_data {
> > struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
> > struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
> > @@ -1299,6 +1305,12 @@ struct intel_vbt_data {
> > int lvds_ssc_freq;
> > unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
> >
> > + /*
> > + * DRRS support type (Seamless OR Static DRRS OR not supported)
> > + * These values correspond to the VBT values for drrs mode.
>
> No, they don't correspond to VBT values, because we're adding that enum,
> and we map the VBT values to the enum.
>
> With that fixed,
As per our irc discussion I've dropped the entire comment - the first line
is redundant with the enum definition.
>
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Queued for -next, thanks for the patch.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-01 13:25 ` Jani Nikula
@ 2014-04-02 5:58 ` Vandana Kannan
2014-04-03 11:14 ` [PATCH v9 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-02 5:58 UTC (permalink / raw)
To: Jani Nikula; +Cc: intel-gfx@lists.freedesktop.org
On Apr-01-2014 6:55 PM, Jani Nikula wrote:
> On Fri, 28 Mar 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
>> From: Pradeep Bhat <pradeep.bhat@intel.com>
>>
>> This patch computes and stored 2nd M/N/TU for switching to different
>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
>> between alternate refresh rates programmed in 2nd M/N/TU registers.
>>
>> v2: Daniel's review comments
>> Computing M2/N2 in compute_config and storing it in crtc_config
>>
>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the
>> changes made to move them from dev_private to intel_panel.
>>
>> v4: Modified references to is_drrs_supported based on the changes made to
>> rename it to drrs_support.
>>
>> v5: Jani's review comments
>> Removed superfluous return statements. Changed support for Gen 7 and above.
>> Corrected indentation. Re-structured the code which finds crtc and connector
>> from encoder. Changed some logs to be less verbose.
>>
>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be
>> derived from intel connector when required.
>>
>> v7: As per internal review comments, acquiring mutex just before accessing
>> drrs RR. As per Chris's review comments, added documentation about the use
>> of locking in the function.
>>
>> v8: Incorporated Jani's review comments.
>> Removed reference to edp_downclock.
>>
>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> ---
>> drivers/gpu/drm/i915/i915_drv.h | 5 ++
>> drivers/gpu/drm/i915/i915_reg.h | 1 +
>> drivers/gpu/drm/i915/intel_dp.c | 108 ++++++++++++++++++++++++++++++++++++++
>> drivers/gpu/drm/i915/intel_drv.h | 6 ++-
>> 4 files changed, 119 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index cd73a33..1c9d5cf 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -794,6 +794,10 @@ struct i915_fbc {
>> } no_fbc_reason;
>> };
>>
>> +struct i915_drrs {
>> + struct intel_connector *connector;
>> +};
>> +
>> struct i915_psr {
>> bool sink_support;
>> bool source_ok;
>> @@ -1497,6 +1501,7 @@ typedef struct drm_i915_private {
>> struct timer_list hotplug_reenable_timer;
>>
>> struct i915_fbc fbc;
>> + struct i915_drrs drrs;
>> struct intel_opregion opregion;
>> struct intel_vbt_data vbt;
>>
>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
>> index 74f7d85..04fc64a 100644
>> --- a/drivers/gpu/drm/i915/i915_reg.h
>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>> @@ -3255,6 +3255,7 @@ enum punit_power_well {
>> #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
>> #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
>> #define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
>> +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
>> #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
>> #define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
>> #define PIPECONF_BPC_MASK (0x7 << 5)
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index f2735de..9640df1 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -736,6 +736,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
>> }
>> }
>>
>> +static void
>> +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
>> +{
>> + struct drm_device *dev = crtc->base.dev;
>> + struct drm_i915_private *dev_priv = dev->dev_private;
>> + enum transcoder transcoder = crtc->config.cpu_transcoder;
>> +
>> + I915_WRITE(PIPE_DATA_M2(transcoder),
>> + TU_SIZE(m_n->tu) | m_n->gmch_m);
>> + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
>> + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
>> + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
>> +}
>> +
>> bool
>> intel_dp_compute_config(struct intel_encoder *encoder,
>> struct intel_crtc_config *pipe_config)
>> @@ -840,6 +854,15 @@ found:
>> pipe_config->port_clock,
>> &pipe_config->dp_m_n);
>>
>> + if (intel_connector->panel.downclock_mode != NULL &&
>> + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
>> + intel_link_compute_m_n(bpp, lane_count,
>> + intel_connector->panel.downclock_mode->clock,
>> + pipe_config->port_clock,
>> + &pipe_config->dp_m2_n2);
>> + }
>> +
>> +
>> intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
>>
>> return true;
>> @@ -3611,6 +3634,87 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>> I915_READ(pp_div_reg));
>> }
>>
>> +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_dp *intel_dp = NULL;
>> + struct intel_crtc_config *config = NULL;
>> + struct intel_crtc *intel_crtc = NULL;
>> + struct intel_connector *intel_connector = dev_priv->drrs.connector;
>> + u32 reg, val;
>> + int index = 0;
>
> enum edp_drrs_refresh_rate.
>
Will change this accordingly..
>> +
>> + if (refresh_rate <= 0) {
>> + DRM_DEBUG_KMS("Refresh rate should be positive non-zero.\n");
>> + return;
>> + }
>> +
>> + if (intel_connector == NULL) {
>> + DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
>> + return;
>> + }
>> +
>> + encoder = intel_attached_encoder(&intel_connector->base);
>> + intel_dp = enc_to_intel_dp(&encoder->base);
>> + intel_crtc = encoder->new_crtc;
>> +
>> + if (!intel_crtc) {
>> + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
>> + return;
>> + }
>> +
>> + config = &intel_crtc->config;
>> +
>> + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
>> + DRM_DEBUG_KMS("Seamless DRRS not supported.\n");
>
> Isn't seamless the only thing that *is* supported?
>
Yes, will correct this..
>> + return;
>> + }
>> +
>> + if (intel_connector->panel.fixed_mode->vrefresh == refresh_rate)
>> + index = DRRS_HIGH_RR;
>> + else
>> + index = DRRS_LOW_RR;
>> +
>> + if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
>
> Can we end up here when drrs is not supported by the platform?
>
When DRRS is not supported by the platform, drrs.connector would remain
NULL. So, the check for connector above should handle the case and avoid
coming up to this point.
For the PSR related changes (enable/disable DRRS according to status of
PSR) that would be made as part of Patch2, I think a check would be
required here to make sure any call to this function not coming through
update_drrs/disable_drrs returns without setting the registers.
>> + reg = PIPECONF(intel_crtc->config.cpu_transcoder);
>> + val = I915_READ(reg);
>> + if (index > DRRS_HIGH_RR) {
>> + val |= PIPECONF_EDP_RR_MODE_SWITCH;
>> + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
>> + } else {
>> + val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
>> + }
>> + I915_WRITE(reg, val);
>> + }
>> +
>> + /*
>> + * mutex taken to ensure that there is no race between differnt
>> + * drrs calls trying to update refresh rate. This scenario may occur
>> + * in future when idleness detection based DRRS in kernel and
>> + * possible calls from user space to set differnt RR are made.
>> + */
>> +
>> + mutex_lock(&intel_dp->drrs_state.mutex);
>> +
>> + intel_dp->drrs_state.refresh_rate_type = index;
>> +
>> + mutex_unlock(&intel_dp->drrs_state.mutex);
>> +
>> + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
>> +}
>> +
>> static struct drm_display_mode *
>> intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>> struct intel_connector *intel_connector,
>> @@ -3647,6 +3751,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>>
>> if (downclock_mode != NULL &&
>> dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
>> + dev_priv->drrs.connector = intel_connector;
>> +
>> + mutex_init(&intel_dp->drrs_state.mutex);
>> +
>> intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
>>
>> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index d781165..46fc8b3 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -305,6 +305,9 @@ struct intel_crtc_config {
>> int pipe_bpp;
>> struct intel_link_m_n dp_m_n;
>>
>> + /* m2_n2 for eDP downclock */
>> + struct intel_link_m_n dp_m2_n2;
>> +
>> /*
>> * Frequence the dpll for the port should run at. Differs from the
>> * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
>> @@ -535,6 +538,7 @@ struct intel_dp {
>> struct {
>> enum drrs_support_type type;
>> enum edp_drrs_refresh_rate_type refresh_rate_type;
>> + struct mutex mutex;
>> } drrs_state;
>>
>> };
>> @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
>> void intel_edp_psr_enable(struct intel_dp *intel_dp);
>> void intel_edp_psr_disable(struct intel_dp *intel_dp);
>> void intel_edp_psr_update(struct drm_device *dev);
>> -
>> +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
>>
>> /* intel_dsi.c */
>> bool intel_dsi_init(struct drm_device *dev);
>> --
>> 1.7.9.5
>>
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v8 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-01 13:17 ` Jani Nikula
@ 2014-04-03 11:10 ` Vandana Kannan
2014-04-03 11:46 ` Jani Nikula
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-03 11:10 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch and finds out the lowest refresh rate supported for the resolution
same as the fixed_mode.
It also checks the VBT fields to see if panel supports seamless DRRS or not.
Based on above data it marks whether eDP panel supports seamless DRRS or not.
This information is needed for supporting seamless DRRS switch for certain
power saving usecases. This patch is tested by enabling the DRM logs and
user should see whether Seamless DRRS is supported or not.
v2: Daniel's review comments
Modified downclock deduction based on intel_find_panel_downclock
v3: Chris's review comments
Moved edp_downclock_avail and edp_downclock to intel_panel
v4: Jani's review comments.
Changed name of the enum edp_panel_type to drrs_support type.
Change is_drrs_supported to drrs_support of type enum drrs_support_type.
v5: Incorporated Jani's review comments
Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
and above.
v6: Incorporated Chris's review comments.
Changed initialize to init in intel_drrs_initialize
v7: Incorporated Jani's review comments.
Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
v8: Made changes to track PSR enable/disable throughout system use (instead
of just in the init sequence) for disabling/enabling DRRS. Jani's review
comments.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 5 ++++
drivers/gpu/drm/i915/intel_dp.c | 55 +++++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cd73a33..b6ea225 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -794,6 +794,10 @@ struct i915_fbc {
} no_fbc_reason;
};
+struct i915_drrs {
+ bool is_psr_enabled;
+};
+
struct i915_psr {
bool sink_support;
bool source_ok;
@@ -1497,6 +1501,7 @@ typedef struct drm_i915_private {
struct timer_list hotplug_reenable_timer;
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_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 59ee4dc..ce588d1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1697,6 +1697,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
static void intel_edp_psr_do_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;
if (!intel_edp_psr_match_conditions(intel_dp) ||
intel_edp_is_psr_enabled(dev))
@@ -1710,6 +1711,11 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
/* Enable PSR on the host */
intel_edp_psr_enable_source(intel_dp);
+
+ if (INTEL_INFO(dev)->gen < 8) {
+ dev_priv->drrs.is_psr_enabled = true;
+ DRM_DEBUG_KMS("eDP panel PSR enabled. Can't support DRRS\n");
+ }
}
void intel_edp_psr_enable(struct intel_dp *intel_dp)
@@ -1736,6 +1742,9 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
DRM_ERROR("Timed out waiting for PSR Idle State\n");
+
+ if (INTEL_INFO(dev)->gen < 8)
+ dev_priv->drrs.is_psr_enabled = false;
}
void intel_edp_psr_update(struct drm_device *dev)
@@ -3611,6 +3620,44 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+static struct drm_display_mode *
+intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
+ struct intel_connector *intel_connector,
+ struct drm_display_mode *fixed_mode)
+{
+ struct drm_connector *connector = &intel_connector->base;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_display_mode *downclock_mode = NULL;
+
+ if (INTEL_INFO(dev)->gen <= 6) {
+ DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
+ return NULL;
+ }
+
+ if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev))
+ dev_priv->drrs.is_psr_enabled = true;
+
+ if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
+ DRM_INFO("VBT doesn't support DRRS\n");
+ return NULL;
+ }
+
+ downclock_mode = intel_find_panel_downclock
+ (dev, fixed_mode, connector);
+
+ if (downclock_mode != NULL &&
+ dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
+ intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
+
+ intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
+ DRM_INFO("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,
struct edp_power_seq *power_seq)
@@ -3620,10 +3667,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = NULL;
+ struct drm_display_mode *downclock_mode = NULL;
bool has_dpcd;
struct drm_display_mode *scan;
struct edid *edid;
+ intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
+
if (!is_edp(intel_dp))
return true;
@@ -3665,6 +3715,9 @@ 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_dig_port,
+ intel_connector, fixed_mode);
break;
}
}
@@ -3677,7 +3730,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
}
- intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector);
return true;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fa99104..d781165 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -483,6 +483,17 @@ struct intel_hdmi {
#define DP_MAX_DOWNSTREAM_PORTS 0x10
+/**
+ * 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 edp_drrs_refresh_rate_type {
+ DRRS_HIGH_RR,
+ DRRS_LOW_RR,
+ DRRS_MAX_RR, /* RR count */
+};
+
struct intel_dp {
uint32_t output_reg;
uint32_t aux_ch_ctl_reg;
@@ -521,6 +532,11 @@ struct intel_dp {
bool has_aux_irq,
int send_bytes,
uint32_t aux_clock_divider);
+ struct {
+ enum drrs_support_type type;
+ enum edp_drrs_refresh_rate_type refresh_rate_type;
+ } drrs_state;
+
};
struct intel_digital_port {
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-02 5:58 ` Vandana Kannan
@ 2014-04-03 11:14 ` Vandana Kannan
2014-04-04 4:58 ` Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-03 11:14 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch computes and stored 2nd M/N/TU for switching to different
refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
between alternate refresh rates programmed in 2nd M/N/TU registers.
v2: Daniel's review comments
Computing M2/N2 in compute_config and storing it in crtc_config
v3: Modified reference to edp_downclock and edp_downclock_avail based on the
changes made to move them from dev_private to intel_panel.
v4: Modified references to is_drrs_supported based on the changes made to
rename it to drrs_support.
v5: Jani's review comments
Removed superfluous return statements. Changed support for Gen 7 and above.
Corrected indentation. Re-structured the code which finds crtc and connector
from encoder. Changed some logs to be less verbose.
v6: Modifying i915_drrs to include only intel connector as intel_dp can be
derived from intel connector when required.
v7: As per internal review comments, acquiring mutex just before accessing
drrs RR. As per Chris's review comments, added documentation about the use
of locking in the function.
v8: Incorporated Jani's review comments.
Removed reference to edp_downclock.
v9: Jani's review comments. Modified comment in set_drrs. Changed index to
type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
registers fo DRRS.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_reg.h | 1 +
drivers/gpu/drm/i915/intel_dp.c | 111 +++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_drv.h | 6 ++-
4 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b6ea225..652da3a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -796,6 +796,7 @@ struct i915_fbc {
struct i915_drrs {
bool is_psr_enabled;
+ struct intel_connector *connector;
};
struct i915_psr {
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 74f7d85..04fc64a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3255,6 +3255,7 @@ enum punit_power_well {
#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
#define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
+#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
#define PIPECONF_BPC_MASK (0x7 << 5)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ce588d1..becc65b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -736,6 +736,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
}
}
+static void
+intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum transcoder transcoder = crtc->config.cpu_transcoder;
+
+ I915_WRITE(PIPE_DATA_M2(transcoder),
+ TU_SIZE(m_n->tu) | m_n->gmch_m);
+ I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
+ I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
+ I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
+}
+
bool
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
@@ -840,6 +854,15 @@ found:
pipe_config->port_clock,
&pipe_config->dp_m_n);
+ if (intel_connector->panel.downclock_mode != NULL &&
+ intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
+ intel_link_compute_m_n(bpp, lane_count,
+ intel_connector->panel.downclock_mode->clock,
+ pipe_config->port_clock,
+ &pipe_config->dp_m2_n2);
+ }
+
+
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
return true;
@@ -3620,6 +3643,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+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_dp *intel_dp = NULL;
+ struct intel_crtc_config *config = NULL;
+ struct intel_crtc *intel_crtc = NULL;
+ struct intel_connector *intel_connector = dev_priv->drrs.connector;
+ u32 reg, val;
+ enum edp_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_connector == NULL) {
+ DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
+ return;
+ }
+
+ if (INTEL_INFO(dev)->gen < 8 && dev_priv->drrs.is_psr_enabled) {
+ DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
+ return;
+ }
+
+ encoder = intel_attached_encoder(&intel_connector->base);
+ intel_dp = enc_to_intel_dp(&encoder->base);
+ intel_crtc = encoder->new_crtc;
+
+ if (!intel_crtc) {
+ DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
+ return;
+ }
+
+ config = &intel_crtc->config;
+
+ if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
+ DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
+ return;
+ }
+
+ if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
+ index = DRRS_LOW_RR;
+
+ if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
+ reg = PIPECONF(intel_crtc->config.cpu_transcoder);
+ val = I915_READ(reg);
+ if (index > DRRS_HIGH_RR) {
+ val |= PIPECONF_EDP_RR_MODE_SWITCH;
+ intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
+ } else {
+ val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
+ }
+ I915_WRITE(reg, val);
+ }
+
+ /*
+ * mutex taken to ensure that there is no race between differnt
+ * drrs calls trying to update refresh rate. This scenario may occur
+ * in future when idleness detection based DRRS in kernel and
+ * possible calls from user space to set differnt RR are made.
+ */
+
+ mutex_lock(&intel_dp->drrs_state.mutex);
+
+ intel_dp->drrs_state.refresh_rate_type = index;
+
+ mutex_unlock(&intel_dp->drrs_state.mutex);
+
+ DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
+}
+
static struct drm_display_mode *
intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector,
@@ -3649,6 +3756,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
if (downclock_mode != NULL &&
dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
+ dev_priv->drrs.connector = intel_connector;
+
+ mutex_init(&intel_dp->drrs_state.mutex);
+
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d781165..46fc8b3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -305,6 +305,9 @@ struct intel_crtc_config {
int pipe_bpp;
struct intel_link_m_n dp_m_n;
+ /* m2_n2 for eDP downclock */
+ struct intel_link_m_n dp_m2_n2;
+
/*
* Frequence the dpll for the port should run at. Differs from the
* adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
@@ -535,6 +538,7 @@ struct intel_dp {
struct {
enum drrs_support_type type;
enum edp_drrs_refresh_rate_type refresh_rate_type;
+ struct mutex mutex;
} drrs_state;
};
@@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
void intel_edp_psr_enable(struct intel_dp *intel_dp);
void intel_edp_psr_disable(struct intel_dp *intel_dp);
void intel_edp_psr_update(struct drm_device *dev);
-
+void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
/* intel_dsi.c */
bool intel_dsi_init(struct drm_device *dev);
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v9 4/6] drm/i915: Idleness detection for DRRS
2014-04-01 13:36 ` Jani Nikula
@ 2014-04-03 11:17 ` Vandana Kannan
2014-04-04 5:00 ` [PATCH v10 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-03 11:17 UTC (permalink / raw)
To: intel-gfx
Adding support to detect display idleness by tracking page flip from
user space. Switch to low refresh rate is triggered after 2 seconds of
idleness. The delay is configurable. If there is a page flip or call to
update the plane, then high refresh rate is applied.
The feature is not used in dual-display mode.
v2: Chris Wilson's review comments incorporated.
Modify idleness detection implementation to make it similar to the
implementation of intel_update_fbc/intel_disable_fbc
v3: Internal review comments incorporated
Add NULL pointer check in intel_disable_drrs.
Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
v4: Jani's review comments incorporated.
Change in sequence in intel_update_drrs. Comment modified to remove details
of update param. Modified DRRS idleness interval to a module parameter.
v5: Chris's review comments incorporated.
Initialize connector in idleness detection init. Modifications made to
use only intel_connector in i915_drrs and derive intel_dp when required.
Added a function drrs_fini to cleanup DRRS work.
v6: Internal review comments. Removed check for primary enabled, which is
a redundant check, in the case of clone mode. Added a flag to track
dual-display configuration. Remove print statement for "cancel DRR work"
and print "DRRS not supported" only once.
v7: As per internal review comments, removing calls to update/disable drrs
from sprite update path. For sprite, all drrs related updates would be
taken care of with calls to crtc page flip itself. This will have to be
revisited later if flip infrastructure changes for sprite.
v8: Incorporated Jani's review comments. Added space after the periods in the
module param description. Changes around drrs-fini to remove seamless DRRS
check.
v9: Added checks for PSR before updating DRRS. Added check for module
param drrs_interval before updating DRRS (this is required if the interval
is modified by the user during system use). DRRS disabled by default. Changes
based on Jani's review comments
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 7 ++
drivers/gpu/drm/i915/i915_params.c | 8 ++
drivers/gpu/drm/i915/intel_display.c | 16 ++++
drivers/gpu/drm/i915/intel_dp.c | 27 ++++++-
drivers/gpu/drm/i915/intel_drv.h | 5 +-
drivers/gpu/drm/i915/intel_pm.c | 142 +++++++++++++++++++++++++++++++++++
6 files changed, 201 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 652da3a..4a3eba6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -797,6 +797,12 @@ struct i915_fbc {
struct i915_drrs {
bool is_psr_enabled;
struct intel_connector *connector;
+ bool is_clone;
+ struct intel_drrs_work {
+ struct delayed_work work;
+ struct drm_crtc *crtc;
+ int interval;
+ } *drrs_work;
};
struct i915_psr {
@@ -2093,6 +2099,7 @@ struct i915_params {
int enable_ips;
int invert_brightness;
int enable_cmd_parser;
+ int drrs_interval;
/* leave bools at the end to not create holes */
bool enable_hangcheck;
bool fastboot;
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d1d7980..2410607 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
.invert_brightness = 0,
.disable_display = 0,
.enable_cmd_parser = 0,
+ .drrs_interval = 0,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -152,3 +153,10 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled, 0=disabled [default])");
+
+module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
+MODULE_PARM_DESC(drrs_interval,
+ "DRRS idleness detection interval (default: 0 ms). "
+ "If this field is set to 0, then seamless DRRS feature "
+ "based on idleness detection is disabled. "
+ "The interval is to be set in milliseconds.");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7e4ea8d..c309561 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2542,6 +2542,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
@@ -3708,6 +3709,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -3751,6 +3753,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
drm_vblank_on(dev, pipe);
@@ -3948,6 +3951,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -3995,6 +3999,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -4391,6 +4396,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4438,6 +4444,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_crtc_dpms_overlay(intel_crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4505,6 +4512,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
}
static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -8508,6 +8516,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
drm_gem_object_unreference(&work->pending_flip_obj->base);
drm_gem_object_unreference(&work->old_fb_obj->base);
+ /* disable current DRRS work scheduled and restart
+ * to push work by another x seconds
+ */
+ intel_update_drrs(dev);
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
@@ -8966,6 +8978,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup_pending;
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
intel_mark_fb_busy(obj, NULL);
mutex_unlock(&dev->struct_mutex);
@@ -11338,6 +11351,7 @@ void intel_modeset_init(struct drm_device *dev)
/* Just in case the BIOS is doing something questionable. */
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
mutex_lock(&dev->mode_config.mutex);
intel_modeset_setup_hw_state(dev, false);
@@ -11803,6 +11817,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
+
intel_disable_gt_powersave(dev);
ironlake_teardown_rc6(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index becc65b..0196dd1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1736,6 +1736,7 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
intel_edp_psr_enable_source(intel_dp);
if (INTEL_INFO(dev)->gen < 8) {
+ intel_disable_drrs(dev);
dev_priv->drrs.is_psr_enabled = true;
DRM_DEBUG_KMS("eDP panel PSR enabled. Can't support DRRS\n");
}
@@ -1766,8 +1767,10 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
DRM_ERROR("Timed out waiting for PSR Idle State\n");
- if (INTEL_INFO(dev)->gen < 8)
+ if (INTEL_INFO(dev)->gen < 8) {
dev_priv->drrs.is_psr_enabled = false;
+ intel_update_drrs(dev);
+ }
}
void intel_edp_psr_update(struct drm_device *dev)
@@ -3360,16 +3363,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
kfree(connector);
}
+static void
+intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
+{
+ if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
+ kfree(dev_priv->drrs.drrs_work);
+ dev_priv->drrs.drrs_work = NULL;
+ dev_priv->drrs.connector = NULL;
+ }
+}
+
void intel_dp_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+
+ if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
+ intel_dp == enc_to_intel_dp(
+ &dev_priv->drrs.connector->encoder->base))
+ intel_dp_drrs_fini(dev_priv);
+
mutex_lock(&dev->mode_config.mutex);
edp_panel_vdd_off_sync(intel_dp);
mutex_unlock(&dev->mode_config.mutex);
@@ -3756,7 +3776,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
if (downclock_mode != NULL &&
dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
- dev_priv->drrs.connector = intel_connector;
+ intel_init_drrs_idleness_detection(dev, intel_connector);
mutex_init(&intel_dp->drrs_state.mutex);
@@ -3764,7 +3784,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
DRM_INFO("seamless DRRS supported for eDP panel.\n");
- }
+ } else
+ DRM_INFO("DRRS not supported\n");
return downclock_mode;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 46fc8b3..570cc47 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -930,7 +930,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
void ilk_wm_get_hw_state(struct drm_device *dev);
-
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector);
+void intel_update_drrs(struct drm_device *dev);
+void intel_disable_drrs(struct drm_device *dev);
/* intel_sdvo.c */
bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index fd68f93..b77452f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -621,6 +621,148 @@ out_disable:
i915_gem_stolen_cleanup_compression(dev);
}
+static void intel_drrs_work_fn(struct work_struct *__work)
+{
+ struct intel_drrs_work *work =
+ container_of(to_delayed_work(__work),
+ struct intel_drrs_work, work);
+ struct drm_device *dev = work->crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Double check if the dual-display mode is active. */
+ if (dev_priv->drrs.is_clone)
+ return;
+
+ intel_dp_set_drrs_state(work->crtc->dev,
+ dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
+}
+
+static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
+{
+ if (dev_priv->drrs.drrs_work == NULL)
+ return;
+
+ cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
+}
+
+static void intel_enable_drrs(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ intel_cancel_drrs_work(dev_priv);
+
+ if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
+ dev_priv->drrs.drrs_work->crtc = crtc;
+ dev_priv->drrs.drrs_work->interval = i915.drrs_interval;
+
+ /* Delay the actual enabling to let pageflipping cease and the
+ * display to settle before starting DRRS
+ */
+ schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
+ msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
+ }
+}
+
+void intel_disable_drrs(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ /* as part of disable DRRS, reset refresh rate to HIGH_RR */
+ if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
+ intel_cancel_drrs_work(dev_priv);
+ intel_dp_set_drrs_state(dev,
+ dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
+ }
+}
+
+/**
+ * intel_update_drrs - enable/disable DRRS as needed
+ * @dev: the drm_device
+*/
+void intel_update_drrs(struct drm_device *dev)
+{
+ struct drm_crtc *crtc = NULL, *tmp_crtc;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0) {
+ intel_disable_drrs(dev);
+ return;
+ }
+
+ /* if drrs.connector is NULL, then drrs_init did not get called.
+ * which means DRRS is not supported.
+ */
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
+ return;
+
+ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+ if (tmp_crtc != NULL && intel_crtc_active(tmp_crtc)) {
+ if (crtc) {
+ DRM_DEBUG_KMS(
+ "more than one pipe active, disabling DRRS\n");
+ dev_priv->drrs.is_clone = true;
+ intel_disable_drrs(dev);
+ return;
+ }
+ crtc = tmp_crtc;
+ }
+ }
+
+ if (crtc == NULL) {
+ DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
+ return;
+ }
+
+ dev_priv->drrs.is_clone = false;
+ intel_disable_drrs(dev);
+
+ /* re-enable idleness detection */
+ intel_enable_drrs(crtc);
+}
+
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector)
+{
+ struct intel_drrs_work *work;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0)
+ DRM_INFO("DRRS disable by flag\n");
+
+ work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
+ if (!work) {
+ DRM_ERROR("Failed to allocate DRRS work structure\n");
+ return;
+ }
+
+ dev_priv->drrs.connector = connector;
+ dev_priv->drrs.is_clone = false;
+
+ work->interval = i915.drrs_interval;
+ INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
+
+ dev_priv->drrs.drrs_work = work;
+}
+
static void i915_pineview_get_mem_freq(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v8 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-03 11:10 ` [PATCH v8 " Vandana Kannan
@ 2014-04-03 11:46 ` Jani Nikula
2014-04-04 4:57 ` [PATCH v9 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-03 11:46 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Thu, 03 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
>
> This patch and finds out the lowest refresh rate supported for the resolution
> same as the fixed_mode.
> It also checks the VBT fields to see if panel supports seamless DRRS or not.
> Based on above data it marks whether eDP panel supports seamless DRRS or not.
> This information is needed for supporting seamless DRRS switch for certain
> power saving usecases. This patch is tested by enabling the DRM logs and
> user should see whether Seamless DRRS is supported or not.
>
> v2: Daniel's review comments
> Modified downclock deduction based on intel_find_panel_downclock
>
> v3: Chris's review comments
> Moved edp_downclock_avail and edp_downclock to intel_panel
>
> v4: Jani's review comments.
> Changed name of the enum edp_panel_type to drrs_support type.
> Change is_drrs_supported to drrs_support of type enum drrs_support_type.
>
> v5: Incorporated Jani's review comments
> Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
> and above.
>
> v6: Incorporated Chris's review comments.
> Changed initialize to init in intel_drrs_initialize
>
> v7: Incorporated Jani's review comments.
> Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
> Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
>
> v8: Made changes to track PSR enable/disable throughout system use (instead
> of just in the init sequence) for disabling/enabling DRRS. Jani's review
> comments.
>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 5 ++++
> drivers/gpu/drm/i915/intel_dp.c | 55 +++++++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++
> 3 files changed, 75 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index cd73a33..b6ea225 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -794,6 +794,10 @@ struct i915_fbc {
> } no_fbc_reason;
> };
>
> +struct i915_drrs {
> + bool is_psr_enabled;
> +};
> +
> struct i915_psr {
> bool sink_support;
> bool source_ok;
> @@ -1497,6 +1501,7 @@ typedef struct drm_i915_private {
> struct timer_list hotplug_reenable_timer;
>
> 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_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 59ee4dc..ce588d1 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1697,6 +1697,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
> static void intel_edp_psr_do_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;
>
> if (!intel_edp_psr_match_conditions(intel_dp) ||
> intel_edp_is_psr_enabled(dev))
> @@ -1710,6 +1711,11 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
>
> /* Enable PSR on the host */
> intel_edp_psr_enable_source(intel_dp);
> +
> + if (INTEL_INFO(dev)->gen < 8) {
> + dev_priv->drrs.is_psr_enabled = true;
> + DRM_DEBUG_KMS("eDP panel PSR enabled. Can't support DRRS\n");
> + }
I'm quite certain we have adequate tracking for whether psr is enabled
or not. Do not add more state for the same thing.
Whenever you'd need to check for dev_priv->drrs.is_psr_enabled, you can
dig it out from existing psr functions.
My whole point was you should not do this at initialization time:
if (psr enabled at this arbitrary point during init)
can't use drrs until reboot or driver reloaded
BR,
Jani.
> }
>
> void intel_edp_psr_enable(struct intel_dp *intel_dp)
> @@ -1736,6 +1742,9 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
> if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
> EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
> DRM_ERROR("Timed out waiting for PSR Idle State\n");
> +
> + if (INTEL_INFO(dev)->gen < 8)
> + dev_priv->drrs.is_psr_enabled = false;
> }
>
> void intel_edp_psr_update(struct drm_device *dev)
> @@ -3611,6 +3620,44 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> I915_READ(pp_div_reg));
> }
>
> +static struct drm_display_mode *
> +intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> + struct intel_connector *intel_connector,
> + struct drm_display_mode *fixed_mode)
> +{
> + struct drm_connector *connector = &intel_connector->base;
> + struct intel_dp *intel_dp = &intel_dig_port->dp;
> + struct drm_device *dev = intel_dig_port->base.base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct drm_display_mode *downclock_mode = NULL;
> +
> + if (INTEL_INFO(dev)->gen <= 6) {
> + DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
> + return NULL;
> + }
> +
> + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev))
> + dev_priv->drrs.is_psr_enabled = true;
> +
> + if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
> + DRM_INFO("VBT doesn't support DRRS\n");
> + return NULL;
> + }
> +
> + downclock_mode = intel_find_panel_downclock
> + (dev, fixed_mode, connector);
> +
> + if (downclock_mode != NULL &&
> + dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
> + intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> +
> + intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> + DRM_INFO("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,
> struct edp_power_seq *power_seq)
> @@ -3620,10 +3667,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> struct drm_device *dev = intel_dig_port->base.base.dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct drm_display_mode *fixed_mode = NULL;
> + struct drm_display_mode *downclock_mode = NULL;
> bool has_dpcd;
> struct drm_display_mode *scan;
> struct edid *edid;
>
> + intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
> +
> if (!is_edp(intel_dp))
> return true;
>
> @@ -3665,6 +3715,9 @@ 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_dig_port,
> + intel_connector, fixed_mode);
> break;
> }
> }
> @@ -3677,7 +3730,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
> }
>
> - intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> + intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> intel_panel_setup_backlight(connector);
>
> return true;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index fa99104..d781165 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -483,6 +483,17 @@ struct intel_hdmi {
>
> #define DP_MAX_DOWNSTREAM_PORTS 0x10
>
> +/**
> + * 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 edp_drrs_refresh_rate_type {
> + DRRS_HIGH_RR,
> + DRRS_LOW_RR,
> + DRRS_MAX_RR, /* RR count */
> +};
> +
> struct intel_dp {
> uint32_t output_reg;
> uint32_t aux_ch_ctl_reg;
> @@ -521,6 +532,11 @@ struct intel_dp {
> bool has_aux_irq,
> int send_bytes,
> uint32_t aux_clock_divider);
> + struct {
> + enum drrs_support_type type;
> + enum edp_drrs_refresh_rate_type refresh_rate_type;
> + } drrs_state;
> +
> };
>
> struct intel_digital_port {
> --
> 1.9.1
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v9 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-03 11:46 ` Jani Nikula
@ 2014-04-04 4:57 ` Vandana Kannan
2014-04-04 10:47 ` [PATCH v10 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-04 4:57 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch and finds out the lowest refresh rate supported for the resolution
same as the fixed_mode.
It also checks the VBT fields to see if panel supports seamless DRRS or not.
Based on above data it marks whether eDP panel supports seamless DRRS or not.
This information is needed for supporting seamless DRRS switch for certain
power saving usecases. This patch is tested by enabling the DRM logs and
user should see whether Seamless DRRS is supported or not.
v2: Daniel's review comments
Modified downclock deduction based on intel_find_panel_downclock
v3: Chris's review comments
Moved edp_downclock_avail and edp_downclock to intel_panel
v4: Jani's review comments.
Changed name of the enum edp_panel_type to drrs_support type.
Change is_drrs_supported to drrs_support of type enum drrs_support_type.
v5: Incorporated Jani's review comments
Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
and above.
v6: Incorporated Chris's review comments.
Changed initialize to init in intel_drrs_initialize
v7: Incorporated Jani's review comments.
Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
v8: Made changes to track PSR enable/disable throughout system use (instead
of just in the init sequence) for disabling/enabling DRRS. Jani's review
comments.
v9: PSR tracking will be done as part of idleness detection patch. Removed
PSR state tracker in i915_drrs. Jani's review comments.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 43 +++++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 16 +++++++++++++++
2 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 59ee4dc..c85ae14 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3611,6 +3611,41 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+static struct drm_display_mode *
+intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
+ struct intel_connector *intel_connector,
+ struct drm_display_mode *fixed_mode)
+{
+ struct drm_connector *connector = &intel_connector->base;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_display_mode *downclock_mode = NULL;
+
+ if (INTEL_INFO(dev)->gen <= 6) {
+ DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
+ return NULL;
+ }
+
+ if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
+ DRM_INFO("VBT doesn't support DRRS\n");
+ return NULL;
+ }
+
+ downclock_mode = intel_find_panel_downclock
+ (dev, fixed_mode, connector);
+
+ if (downclock_mode != NULL &&
+ dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
+ intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
+
+ intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
+ DRM_INFO("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,
struct edp_power_seq *power_seq)
@@ -3620,10 +3655,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = NULL;
+ struct drm_display_mode *downclock_mode = NULL;
bool has_dpcd;
struct drm_display_mode *scan;
struct edid *edid;
+ intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
+
if (!is_edp(intel_dp))
return true;
@@ -3665,6 +3703,9 @@ 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_dig_port,
+ intel_connector, fixed_mode);
break;
}
}
@@ -3677,7 +3718,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
}
- intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector);
return true;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fa99104..d781165 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -483,6 +483,17 @@ struct intel_hdmi {
#define DP_MAX_DOWNSTREAM_PORTS 0x10
+/**
+ * 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 edp_drrs_refresh_rate_type {
+ DRRS_HIGH_RR,
+ DRRS_LOW_RR,
+ DRRS_MAX_RR, /* RR count */
+};
+
struct intel_dp {
uint32_t output_reg;
uint32_t aux_ch_ctl_reg;
@@ -521,6 +532,11 @@ struct intel_dp {
bool has_aux_irq,
int send_bytes,
uint32_t aux_clock_divider);
+ struct {
+ enum drrs_support_type type;
+ enum edp_drrs_refresh_rate_type refresh_rate_type;
+ } drrs_state;
+
};
struct intel_digital_port {
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-03 11:14 ` [PATCH v9 " Vandana Kannan
@ 2014-04-04 4:58 ` Vandana Kannan
2014-04-05 6:43 ` Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-04 4:58 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch computes and stored 2nd M/N/TU for switching to different
refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
between alternate refresh rates programmed in 2nd M/N/TU registers.
v2: Daniel's review comments
Computing M2/N2 in compute_config and storing it in crtc_config
v3: Modified reference to edp_downclock and edp_downclock_avail based on the
changes made to move them from dev_private to intel_panel.
v4: Modified references to is_drrs_supported based on the changes made to
rename it to drrs_support.
v5: Jani's review comments
Removed superfluous return statements. Changed support for Gen 7 and above.
Corrected indentation. Re-structured the code which finds crtc and connector
from encoder. Changed some logs to be less verbose.
v6: Modifying i915_drrs to include only intel connector as intel_dp can be
derived from intel connector when required.
v7: As per internal review comments, acquiring mutex just before accessing
drrs RR. As per Chris's review comments, added documentation about the use
of locking in the function.
v8: Incorporated Jani's review comments.
Removed reference to edp_downclock.
v9: Jani's review comments. Modified comment in set_drrs. Changed index to
type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
registers fo DRRS.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 5 ++
drivers/gpu/drm/i915/i915_reg.h | 1 +
drivers/gpu/drm/i915/intel_dp.c | 111 +++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_drv.h | 6 ++-
4 files changed, 122 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cd73a33..1c9d5cf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -794,6 +794,10 @@ struct i915_fbc {
} no_fbc_reason;
};
+struct i915_drrs {
+ struct intel_connector *connector;
+};
+
struct i915_psr {
bool sink_support;
bool source_ok;
@@ -1497,6 +1501,7 @@ typedef struct drm_i915_private {
struct timer_list hotplug_reenable_timer;
struct i915_fbc fbc;
+ struct i915_drrs drrs;
struct intel_opregion opregion;
struct intel_vbt_data vbt;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 74f7d85..04fc64a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3255,6 +3255,7 @@ enum punit_power_well {
#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
#define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
+#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
#define PIPECONF_BPC_MASK (0x7 << 5)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c85ae14..374dcb6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -736,6 +736,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
}
}
+static void
+intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum transcoder transcoder = crtc->config.cpu_transcoder;
+
+ I915_WRITE(PIPE_DATA_M2(transcoder),
+ TU_SIZE(m_n->tu) | m_n->gmch_m);
+ I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
+ I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
+ I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
+}
+
bool
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
@@ -840,6 +854,15 @@ found:
pipe_config->port_clock,
&pipe_config->dp_m_n);
+ if (intel_connector->panel.downclock_mode != NULL &&
+ intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
+ intel_link_compute_m_n(bpp, lane_count,
+ intel_connector->panel.downclock_mode->clock,
+ pipe_config->port_clock,
+ &pipe_config->dp_m2_n2);
+ }
+
+
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
return true;
@@ -3611,6 +3634,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+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_dp *intel_dp = NULL;
+ struct intel_crtc_config *config = NULL;
+ struct intel_crtc *intel_crtc = NULL;
+ struct intel_connector *intel_connector = dev_priv->drrs.connector;
+ u32 reg, val;
+ enum edp_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_connector == NULL) {
+ DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
+ return;
+ }
+
+ if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
+ DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
+ return;
+ }
+
+ encoder = intel_attached_encoder(&intel_connector->base);
+ intel_dp = enc_to_intel_dp(&encoder->base);
+ intel_crtc = encoder->new_crtc;
+
+ if (!intel_crtc) {
+ DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
+ return;
+ }
+
+ config = &intel_crtc->config;
+
+ if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
+ DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
+ return;
+ }
+
+ if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
+ index = DRRS_LOW_RR;
+
+ if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
+ reg = PIPECONF(intel_crtc->config.cpu_transcoder);
+ val = I915_READ(reg);
+ if (index > DRRS_HIGH_RR) {
+ val |= PIPECONF_EDP_RR_MODE_SWITCH;
+ intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
+ } else {
+ val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
+ }
+ I915_WRITE(reg, val);
+ }
+
+ /*
+ * mutex taken to ensure that there is no race between differnt
+ * drrs calls trying to update refresh rate. This scenario may occur
+ * in future when idleness detection based DRRS in kernel and
+ * possible calls from user space to set differnt RR are made.
+ */
+
+ mutex_lock(&intel_dp->drrs_state.mutex);
+
+ intel_dp->drrs_state.refresh_rate_type = index;
+
+ mutex_unlock(&intel_dp->drrs_state.mutex);
+
+ DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
+}
+
static struct drm_display_mode *
intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector,
@@ -3637,6 +3744,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
if (downclock_mode != NULL &&
dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
+ dev_priv->drrs.connector = intel_connector;
+
+ mutex_init(&intel_dp->drrs_state.mutex);
+
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d781165..46fc8b3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -305,6 +305,9 @@ struct intel_crtc_config {
int pipe_bpp;
struct intel_link_m_n dp_m_n;
+ /* m2_n2 for eDP downclock */
+ struct intel_link_m_n dp_m2_n2;
+
/*
* Frequence the dpll for the port should run at. Differs from the
* adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
@@ -535,6 +538,7 @@ struct intel_dp {
struct {
enum drrs_support_type type;
enum edp_drrs_refresh_rate_type refresh_rate_type;
+ struct mutex mutex;
} drrs_state;
};
@@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
void intel_edp_psr_enable(struct intel_dp *intel_dp);
void intel_edp_psr_disable(struct intel_dp *intel_dp);
void intel_edp_psr_update(struct drm_device *dev);
-
+void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
/* intel_dsi.c */
bool intel_dsi_init(struct drm_device *dev);
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v10 4/6] drm/i915: Idleness detection for DRRS
2014-04-03 11:17 ` [PATCH v9 " Vandana Kannan
@ 2014-04-04 5:00 ` Vandana Kannan
2014-04-04 6:54 ` Jani Nikula
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-04 5:00 UTC (permalink / raw)
To: intel-gfx
Adding support to detect display idleness by tracking page flip from
user space. Switch to low refresh rate is triggered after 2 seconds of
idleness. The delay is configurable. If there is a page flip or call to
update the plane, then high refresh rate is applied.
The feature is not used in dual-display mode.
v2: Chris Wilson's review comments incorporated.
Modify idleness detection implementation to make it similar to the
implementation of intel_update_fbc/intel_disable_fbc
v3: Internal review comments incorporated
Add NULL pointer check in intel_disable_drrs.
Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
v4: Jani's review comments incorporated.
Change in sequence in intel_update_drrs. Comment modified to remove details
of update param. Modified DRRS idleness interval to a module parameter.
v5: Chris's review comments incorporated.
Initialize connector in idleness detection init. Modifications made to
use only intel_connector in i915_drrs and derive intel_dp when required.
Added a function drrs_fini to cleanup DRRS work.
v6: Internal review comments. Removed check for primary enabled, which is
a redundant check, in the case of clone mode. Added a flag to track
dual-display configuration. Remove print statement for "cancel DRR work"
and print "DRRS not supported" only once.
v7: As per internal review comments, removing calls to update/disable drrs
from sprite update path. For sprite, all drrs related updates would be
taken care of with calls to crtc page flip itself. This will have to be
revisited later if flip infrastructure changes for sprite.
v8: Incorporated Jani's review comments. Added space after the periods in the
module param description. Changes around drrs-fini to remove seamless DRRS
check.
v9: Added checks for PSR before updating DRRS. Added check for module
param drrs_interval before updating DRRS (this is required if the interval
is modified by the user during system use). DRRS disabled by default. Changes
based on Jani's review comments
v10: Disable/enable DRRS when PSR is enable/disabled.
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 7 ++
drivers/gpu/drm/i915/i915_params.c | 8 ++
drivers/gpu/drm/i915/intel_display.c | 16 ++++
drivers/gpu/drm/i915/intel_dp.c | 30 +++++++-
drivers/gpu/drm/i915/intel_drv.h | 5 +-
drivers/gpu/drm/i915/intel_pm.c | 142 +++++++++++++++++++++++++++++++++++
6 files changed, 205 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1c9d5cf..c4e9b37 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -796,6 +796,12 @@ struct i915_fbc {
struct i915_drrs {
struct intel_connector *connector;
+ bool is_clone;
+ struct intel_drrs_work {
+ struct delayed_work work;
+ struct drm_crtc *crtc;
+ int interval;
+ } *drrs_work;
};
struct i915_psr {
@@ -2092,6 +2098,7 @@ struct i915_params {
int enable_ips;
int invert_brightness;
int enable_cmd_parser;
+ int drrs_interval;
/* leave bools at the end to not create holes */
bool enable_hangcheck;
bool fastboot;
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d1d7980..2410607 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
.invert_brightness = 0,
.disable_display = 0,
.enable_cmd_parser = 0,
+ .drrs_interval = 0,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -152,3 +153,10 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled, 0=disabled [default])");
+
+module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
+MODULE_PARM_DESC(drrs_interval,
+ "DRRS idleness detection interval (default: 0 ms). "
+ "If this field is set to 0, then seamless DRRS feature "
+ "based on idleness detection is disabled. "
+ "The interval is to be set in milliseconds.");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7e4ea8d..c309561 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2542,6 +2542,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
@@ -3708,6 +3709,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -3751,6 +3753,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
drm_vblank_on(dev, pipe);
@@ -3948,6 +3951,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -3995,6 +3999,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -4391,6 +4396,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4438,6 +4444,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_crtc_dpms_overlay(intel_crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4505,6 +4512,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
}
static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -8508,6 +8516,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
drm_gem_object_unreference(&work->pending_flip_obj->base);
drm_gem_object_unreference(&work->old_fb_obj->base);
+ /* disable current DRRS work scheduled and restart
+ * to push work by another x seconds
+ */
+ intel_update_drrs(dev);
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
@@ -8966,6 +8978,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup_pending;
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
intel_mark_fb_busy(obj, NULL);
mutex_unlock(&dev->struct_mutex);
@@ -11338,6 +11351,7 @@ void intel_modeset_init(struct drm_device *dev)
/* Just in case the BIOS is doing something questionable. */
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
mutex_lock(&dev->mode_config.mutex);
intel_modeset_setup_hw_state(dev, false);
@@ -11803,6 +11817,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
+
intel_disable_gt_powersave(dev);
ironlake_teardown_rc6(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 374dcb6..dd055af 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1725,6 +1725,11 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
intel_edp_is_psr_enabled(dev))
return;
+ if (INTEL_INFO(dev)->gen < 8) {
+ DRM_DEBUG_KMS("Enabling PSR, disabling DRRS\n");
+ intel_disable_drrs(dev);
+ }
+
/* Setup PSR once */
intel_edp_psr_setup(intel_dp);
@@ -1759,6 +1764,9 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
DRM_ERROR("Timed out waiting for PSR Idle State\n");
+
+ if (INTEL_INFO(dev)->gen < 8)
+ intel_update_drrs(dev);
}
void intel_edp_psr_update(struct drm_device *dev)
@@ -3351,16 +3359,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
kfree(connector);
}
+static void
+intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
+{
+ if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
+ kfree(dev_priv->drrs.drrs_work);
+ dev_priv->drrs.drrs_work = NULL;
+ dev_priv->drrs.connector = NULL;
+ }
+}
+
void intel_dp_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+
+ if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
+ intel_dp == enc_to_intel_dp(
+ &dev_priv->drrs.connector->encoder->base))
+ intel_dp_drrs_fini(dev_priv);
+
mutex_lock(&dev->mode_config.mutex);
edp_panel_vdd_off_sync(intel_dp);
mutex_unlock(&dev->mode_config.mutex);
@@ -3744,7 +3769,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
if (downclock_mode != NULL &&
dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
- dev_priv->drrs.connector = intel_connector;
+ intel_init_drrs_idleness_detection(dev, intel_connector);
mutex_init(&intel_dp->drrs_state.mutex);
@@ -3752,7 +3777,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
DRM_INFO("seamless DRRS supported for eDP panel.\n");
- }
+ } else
+ DRM_INFO("DRRS not supported\n");
return downclock_mode;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 46fc8b3..570cc47 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -930,7 +930,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
void ilk_wm_get_hw_state(struct drm_device *dev);
-
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector);
+void intel_update_drrs(struct drm_device *dev);
+void intel_disable_drrs(struct drm_device *dev);
/* intel_sdvo.c */
bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index fd68f93..b77452f 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -621,6 +621,148 @@ out_disable:
i915_gem_stolen_cleanup_compression(dev);
}
+static void intel_drrs_work_fn(struct work_struct *__work)
+{
+ struct intel_drrs_work *work =
+ container_of(to_delayed_work(__work),
+ struct intel_drrs_work, work);
+ struct drm_device *dev = work->crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Double check if the dual-display mode is active. */
+ if (dev_priv->drrs.is_clone)
+ return;
+
+ intel_dp_set_drrs_state(work->crtc->dev,
+ dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
+}
+
+static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
+{
+ if (dev_priv->drrs.drrs_work == NULL)
+ return;
+
+ cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
+}
+
+static void intel_enable_drrs(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ intel_cancel_drrs_work(dev_priv);
+
+ if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
+ dev_priv->drrs.drrs_work->crtc = crtc;
+ dev_priv->drrs.drrs_work->interval = i915.drrs_interval;
+
+ /* Delay the actual enabling to let pageflipping cease and the
+ * display to settle before starting DRRS
+ */
+ schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
+ msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
+ }
+}
+
+void intel_disable_drrs(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ /* as part of disable DRRS, reset refresh rate to HIGH_RR */
+ if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
+ intel_cancel_drrs_work(dev_priv);
+ intel_dp_set_drrs_state(dev,
+ dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
+ }
+}
+
+/**
+ * intel_update_drrs - enable/disable DRRS as needed
+ * @dev: the drm_device
+*/
+void intel_update_drrs(struct drm_device *dev)
+{
+ struct drm_crtc *crtc = NULL, *tmp_crtc;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0) {
+ intel_disable_drrs(dev);
+ return;
+ }
+
+ /* if drrs.connector is NULL, then drrs_init did not get called.
+ * which means DRRS is not supported.
+ */
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
+ return;
+
+ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+ if (tmp_crtc != NULL && intel_crtc_active(tmp_crtc)) {
+ if (crtc) {
+ DRM_DEBUG_KMS(
+ "more than one pipe active, disabling DRRS\n");
+ dev_priv->drrs.is_clone = true;
+ intel_disable_drrs(dev);
+ return;
+ }
+ crtc = tmp_crtc;
+ }
+ }
+
+ if (crtc == NULL) {
+ DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
+ return;
+ }
+
+ dev_priv->drrs.is_clone = false;
+ intel_disable_drrs(dev);
+
+ /* re-enable idleness detection */
+ intel_enable_drrs(crtc);
+}
+
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector)
+{
+ struct intel_drrs_work *work;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0)
+ DRM_INFO("DRRS disable by flag\n");
+
+ work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
+ if (!work) {
+ DRM_ERROR("Failed to allocate DRRS work structure\n");
+ return;
+ }
+
+ dev_priv->drrs.connector = connector;
+ dev_priv->drrs.is_clone = false;
+
+ work->interval = i915.drrs_interval;
+ INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
+
+ dev_priv->drrs.drrs_work = work;
+}
+
static void i915_pineview_get_mem_freq(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v10 4/6] drm/i915: Idleness detection for DRRS
2014-04-04 5:00 ` [PATCH v10 " Vandana Kannan
@ 2014-04-04 6:54 ` Jani Nikula
2014-04-04 10:53 ` [PATCH v11 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-04 6:54 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 04 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> Adding support to detect display idleness by tracking page flip from
> user space. Switch to low refresh rate is triggered after 2 seconds of
> idleness. The delay is configurable. If there is a page flip or call to
> update the plane, then high refresh rate is applied.
> The feature is not used in dual-display mode.
>
> v2: Chris Wilson's review comments incorporated.
> Modify idleness detection implementation to make it similar to the
> implementation of intel_update_fbc/intel_disable_fbc
>
> v3: Internal review comments incorporated
> Add NULL pointer check in intel_disable_drrs.
> Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
>
> v4: Jani's review comments incorporated.
> Change in sequence in intel_update_drrs. Comment modified to remove details
> of update param. Modified DRRS idleness interval to a module parameter.
>
> v5: Chris's review comments incorporated.
> Initialize connector in idleness detection init. Modifications made to
> use only intel_connector in i915_drrs and derive intel_dp when required.
> Added a function drrs_fini to cleanup DRRS work.
>
> v6: Internal review comments. Removed check for primary enabled, which is
> a redundant check, in the case of clone mode. Added a flag to track
> dual-display configuration. Remove print statement for "cancel DRR work"
> and print "DRRS not supported" only once.
>
> v7: As per internal review comments, removing calls to update/disable drrs
> from sprite update path. For sprite, all drrs related updates would be
> taken care of with calls to crtc page flip itself. This will have to be
> revisited later if flip infrastructure changes for sprite.
>
> v8: Incorporated Jani's review comments. Added space after the periods in the
> module param description. Changes around drrs-fini to remove seamless DRRS
> check.
>
> v9: Added checks for PSR before updating DRRS. Added check for module
> param drrs_interval before updating DRRS (this is required if the interval
> is modified by the user during system use). DRRS disabled by default. Changes
> based on Jani's review comments
>
> v10: Disable/enable DRRS when PSR is enable/disabled.
>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 7 ++
> drivers/gpu/drm/i915/i915_params.c | 8 ++
> drivers/gpu/drm/i915/intel_display.c | 16 ++++
> drivers/gpu/drm/i915/intel_dp.c | 30 +++++++-
> drivers/gpu/drm/i915/intel_drv.h | 5 +-
> drivers/gpu/drm/i915/intel_pm.c | 142 +++++++++++++++++++++++++++++++++++
> 6 files changed, 205 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 1c9d5cf..c4e9b37 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -796,6 +796,12 @@ struct i915_fbc {
>
> struct i915_drrs {
> struct intel_connector *connector;
> + bool is_clone;
> + struct intel_drrs_work {
> + struct delayed_work work;
> + struct drm_crtc *crtc;
> + int interval;
> + } *drrs_work;
> };
>
> struct i915_psr {
> @@ -2092,6 +2098,7 @@ struct i915_params {
> int enable_ips;
> int invert_brightness;
> int enable_cmd_parser;
> + int drrs_interval;
> /* leave bools at the end to not create holes */
> bool enable_hangcheck;
> bool fastboot;
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index d1d7980..2410607 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
> .invert_brightness = 0,
> .disable_display = 0,
> .enable_cmd_parser = 0,
> + .drrs_interval = 0,
> };
>
> module_param_named(modeset, i915.modeset, int, 0400);
> @@ -152,3 +153,10 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
> module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
> MODULE_PARM_DESC(enable_cmd_parser,
> "Enable command parsing (1=enabled, 0=disabled [default])");
> +
> +module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
> +MODULE_PARM_DESC(drrs_interval,
> + "DRRS idleness detection interval (default: 0 ms). "
> + "If this field is set to 0, then seamless DRRS feature "
> + "based on idleness detection is disabled. "
> + "The interval is to be set in milliseconds.");
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7e4ea8d..c309561 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2542,6 +2542,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> intel_edp_psr_update(dev);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -3708,6 +3709,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> @@ -3751,6 +3753,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
>
> drm_vblank_on(dev, pipe);
> @@ -3948,6 +3951,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
> }
>
> @@ -3995,6 +3999,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
> }
>
> @@ -4391,6 +4396,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
> intel_crtc_update_cursor(crtc, true);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->enable(encoder);
> @@ -4438,6 +4444,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
> intel_crtc_dpms_overlay(intel_crtc, true);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->enable(encoder);
> @@ -4505,6 +4512,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
> intel_update_watermarks(crtc);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> }
>
> static void i9xx_crtc_off(struct drm_crtc *crtc)
> @@ -8508,6 +8516,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
> drm_gem_object_unreference(&work->pending_flip_obj->base);
> drm_gem_object_unreference(&work->old_fb_obj->base);
>
> + /* disable current DRRS work scheduled and restart
> + * to push work by another x seconds
> + */
> + intel_update_drrs(dev);
> intel_update_fbc(dev);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -8966,6 +8978,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> goto cleanup_pending;
>
> intel_disable_fbc(dev);
> + intel_disable_drrs(dev);
> intel_mark_fb_busy(obj, NULL);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -11338,6 +11351,7 @@ void intel_modeset_init(struct drm_device *dev)
>
> /* Just in case the BIOS is doing something questionable. */
> intel_disable_fbc(dev);
> + intel_disable_drrs(dev);
>
> mutex_lock(&dev->mode_config.mutex);
> intel_modeset_setup_hw_state(dev, false);
> @@ -11803,6 +11817,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
>
> intel_disable_fbc(dev);
>
> + intel_disable_drrs(dev);
> +
> intel_disable_gt_powersave(dev);
>
> ironlake_teardown_rc6(dev);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 374dcb6..dd055af 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1725,6 +1725,11 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
> intel_edp_is_psr_enabled(dev))
> return;
>
> + if (INTEL_INFO(dev)->gen < 8) {
> + DRM_DEBUG_KMS("Enabling PSR, disabling DRRS\n");
> + intel_disable_drrs(dev);
> + }
> +
> /* Setup PSR once */
> intel_edp_psr_setup(intel_dp);
>
> @@ -1759,6 +1764,9 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
> if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
> EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
> DRM_ERROR("Timed out waiting for PSR Idle State\n");
> +
> + if (INTEL_INFO(dev)->gen < 8)
> + intel_update_drrs(dev);
> }
>
> void intel_edp_psr_update(struct drm_device *dev)
> @@ -3351,16 +3359,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
> kfree(connector);
> }
>
> +static void
> +intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
> +{
> + if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
> + kfree(dev_priv->drrs.drrs_work);
> + dev_priv->drrs.drrs_work = NULL;
> + dev_priv->drrs.connector = NULL;
> + }
> +}
> +
> void intel_dp_encoder_destroy(struct drm_encoder *encoder)
> {
> struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
> struct intel_dp *intel_dp = &intel_dig_port->dp;
> struct drm_device *dev = intel_dp_to_dev(intel_dp);
> + struct drm_i915_private *dev_priv = dev->dev_private;
>
> drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
> drm_encoder_cleanup(encoder);
> if (is_edp(intel_dp)) {
> cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +
> + if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
> + intel_dp == enc_to_intel_dp(
> + &dev_priv->drrs.connector->encoder->base))
> + intel_dp_drrs_fini(dev_priv);
> +
> mutex_lock(&dev->mode_config.mutex);
> edp_panel_vdd_off_sync(intel_dp);
> mutex_unlock(&dev->mode_config.mutex);
> @@ -3744,7 +3769,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>
> if (downclock_mode != NULL &&
> dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
> - dev_priv->drrs.connector = intel_connector;
> + intel_init_drrs_idleness_detection(dev, intel_connector);
>
> mutex_init(&intel_dp->drrs_state.mutex);
>
> @@ -3752,7 +3777,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>
> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> DRM_INFO("seamless DRRS supported for eDP panel.\n");
> - }
> + } else
> + DRM_INFO("DRRS not supported\n");
I just realized this else branch really belongs to patch 2. And it also
means you'll return a non-NULL downclock_mode when DRRS is not
supported. As returned mode gets stored to the panel struct, and used
for checking whether DRRS is possible, I think you should return NULL
when DRRS is not possible.
BR,
Jani.
>
> return downclock_mode;
> }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 46fc8b3..570cc47 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -930,7 +930,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> void ilk_wm_get_hw_state(struct drm_device *dev);
> -
> +void intel_init_drrs_idleness_detection(struct drm_device *dev,
> + struct intel_connector *connector);
> +void intel_update_drrs(struct drm_device *dev);
> +void intel_disable_drrs(struct drm_device *dev);
>
> /* intel_sdvo.c */
> bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index fd68f93..b77452f 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -621,6 +621,148 @@ out_disable:
> i915_gem_stolen_cleanup_compression(dev);
> }
>
> +static void intel_drrs_work_fn(struct work_struct *__work)
> +{
> + struct intel_drrs_work *work =
> + container_of(to_delayed_work(__work),
> + struct intel_drrs_work, work);
> + struct drm_device *dev = work->crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + /* Double check if the dual-display mode is active. */
> + if (dev_priv->drrs.is_clone)
> + return;
> +
> + intel_dp_set_drrs_state(work->crtc->dev,
> + dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
> +}
> +
> +static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
> +{
> + if (dev_priv->drrs.drrs_work == NULL)
> + return;
> +
> + cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
> +}
> +
> +static void intel_enable_drrs(struct drm_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_dp *intel_dp = NULL;
> +
> + intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
> +
> + if (intel_dp == NULL)
> + return;
> +
> + intel_cancel_drrs_work(dev_priv);
> +
> + if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
> + dev_priv->drrs.drrs_work->crtc = crtc;
> + dev_priv->drrs.drrs_work->interval = i915.drrs_interval;
> +
> + /* Delay the actual enabling to let pageflipping cease and the
> + * display to settle before starting DRRS
> + */
> + schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
> + msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
> + }
> +}
> +
> +void intel_disable_drrs(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_dp *intel_dp = NULL;
> +
> + if (dev_priv->drrs.connector == NULL)
> + return;
> +
> + intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
> +
> + if (intel_dp == NULL)
> + return;
> +
> + /* as part of disable DRRS, reset refresh rate to HIGH_RR */
> + if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
> + intel_cancel_drrs_work(dev_priv);
> + intel_dp_set_drrs_state(dev,
> + dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
> + }
> +}
> +
> +/**
> + * intel_update_drrs - enable/disable DRRS as needed
> + * @dev: the drm_device
> +*/
> +void intel_update_drrs(struct drm_device *dev)
> +{
> + struct drm_crtc *crtc = NULL, *tmp_crtc;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (i915.drrs_interval == 0) {
> + intel_disable_drrs(dev);
> + return;
> + }
> +
> + /* if drrs.connector is NULL, then drrs_init did not get called.
> + * which means DRRS is not supported.
> + */
> + if (dev_priv->drrs.connector == NULL)
> + return;
> +
> + if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
> + return;
> +
> + list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
> + if (tmp_crtc != NULL && intel_crtc_active(tmp_crtc)) {
> + if (crtc) {
> + DRM_DEBUG_KMS(
> + "more than one pipe active, disabling DRRS\n");
> + dev_priv->drrs.is_clone = true;
> + intel_disable_drrs(dev);
> + return;
> + }
> + crtc = tmp_crtc;
> + }
> + }
> +
> + if (crtc == NULL) {
> + DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
> + return;
> + }
> +
> + dev_priv->drrs.is_clone = false;
> + intel_disable_drrs(dev);
> +
> + /* re-enable idleness detection */
> + intel_enable_drrs(crtc);
> +}
> +
> +void intel_init_drrs_idleness_detection(struct drm_device *dev,
> + struct intel_connector *connector)
> +{
> + struct intel_drrs_work *work;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (i915.drrs_interval == 0)
> + DRM_INFO("DRRS disable by flag\n");
> +
> + work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
> + if (!work) {
> + DRM_ERROR("Failed to allocate DRRS work structure\n");
> + return;
> + }
> +
> + dev_priv->drrs.connector = connector;
> + dev_priv->drrs.is_clone = false;
> +
> + work->interval = i915.drrs_interval;
> + INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
> +
> + dev_priv->drrs.drrs_work = work;
> +}
> +
> static void i915_pineview_get_mem_freq(struct drm_device *dev)
> {
> drm_i915_private_t *dev_priv = dev->dev_private;
> --
> 1.9.1
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v10 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-04 4:57 ` [PATCH v9 " Vandana Kannan
@ 2014-04-04 10:47 ` Vandana Kannan
2014-04-04 10:55 ` Jani Nikula
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-04 10:47 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch and finds out the lowest refresh rate supported for the resolution
same as the fixed_mode.
It also checks the VBT fields to see if panel supports seamless DRRS or not.
Based on above data it marks whether eDP panel supports seamless DRRS or not.
This information is needed for supporting seamless DRRS switch for certain
power saving usecases. This patch is tested by enabling the DRM logs and
user should see whether Seamless DRRS is supported or not.
v2: Daniel's review comments
Modified downclock deduction based on intel_find_panel_downclock
v3: Chris's review comments
Moved edp_downclock_avail and edp_downclock to intel_panel
v4: Jani's review comments.
Changed name of the enum edp_panel_type to drrs_support type.
Change is_drrs_supported to drrs_support of type enum drrs_support_type.
v5: Incorporated Jani's review comments
Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
and above.
v6: Incorporated Chris's review comments.
Changed initialize to init in intel_drrs_initialize
v7: Incorporated Jani's review comments.
Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
v8: Made changes to track PSR enable/disable throughout system use (instead
of just in the init sequence) for disabling/enabling DRRS. Jani's review
comments.
v9: PSR tracking will be done as part of idleness detection patch. Removed
PSR state tracker in i915_drrs. Jani's review comments.
v10: Added log for DRRS not supported in drrs_init
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 45 +++++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++++
2 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e48d47c..9f110bd 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3632,6 +3632,43 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+static struct drm_display_mode *
+intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
+ struct intel_connector *intel_connector,
+ struct drm_display_mode *fixed_mode)
+{
+ struct drm_connector *connector = &intel_connector->base;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_display_mode *downclock_mode = NULL;
+
+ if (INTEL_INFO(dev)->gen <= 6) {
+ DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
+ return NULL;
+ }
+
+ if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
+ DRM_INFO("VBT doesn't support DRRS\n");
+ return NULL;
+ }
+
+ downclock_mode = intel_find_panel_downclock
+ (dev, fixed_mode, connector);
+
+ if (downclock_mode != NULL &&
+ dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
+ intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
+
+ intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
+ DRM_INFO("seamless DRRS supported for eDP panel.\n");
+ return downclock_mode;
+ } else {
+ DRM_INFO("DRRS not supported\n");
+ return NULL;
+ }
+}
+
static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct intel_connector *intel_connector,
struct edp_power_seq *power_seq)
@@ -3641,10 +3678,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = NULL;
+ struct drm_display_mode *downclock_mode = NULL;
bool has_dpcd;
struct drm_display_mode *scan;
struct edid *edid;
+ intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
+
if (!is_edp(intel_dp))
return true;
@@ -3687,6 +3727,9 @@ 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_dig_port,
+ intel_connector, fixed_mode);
break;
}
}
@@ -3700,7 +3743,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
mutex_unlock(&dev->mode_config.mutex);
- intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector);
return true;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 42762b7..286d4fb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -482,6 +482,17 @@ struct intel_hdmi {
#define DP_MAX_DOWNSTREAM_PORTS 0x10
+/**
+ * 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 edp_drrs_refresh_rate_type {
+ DRRS_HIGH_RR,
+ DRRS_LOW_RR,
+ DRRS_MAX_RR, /* RR count */
+};
+
struct intel_dp {
uint32_t output_reg;
uint32_t aux_ch_ctl_reg;
@@ -520,6 +531,11 @@ struct intel_dp {
bool has_aux_irq,
int send_bytes,
uint32_t aux_clock_divider);
+ struct {
+ enum drrs_support_type type;
+ enum edp_drrs_refresh_rate_type refresh_rate_type;
+ } drrs_state;
+
};
struct intel_digital_port {
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v11 4/6] drm/i915: Idleness detection for DRRS
2014-04-04 6:54 ` Jani Nikula
@ 2014-04-04 10:53 ` Vandana Kannan
2014-04-05 6:44 ` Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-04 10:53 UTC (permalink / raw)
To: intel-gfx
Adding support to detect display idleness by tracking page flip from
user space. Switch to low refresh rate is triggered after 2 seconds of
idleness. The delay is configurable. If there is a page flip or call to
update the plane, then high refresh rate is applied.
The feature is not used in dual-display mode.
v2: Chris Wilson's review comments incorporated.
Modify idleness detection implementation to make it similar to the
implementation of intel_update_fbc/intel_disable_fbc
v3: Internal review comments incorporated
Add NULL pointer check in intel_disable_drrs.
Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
v4: Jani's review comments incorporated.
Change in sequence in intel_update_drrs. Comment modified to remove details
of update param. Modified DRRS idleness interval to a module parameter.
v5: Chris's review comments incorporated.
Initialize connector in idleness detection init. Modifications made to
use only intel_connector in i915_drrs and derive intel_dp when required.
Added a function drrs_fini to cleanup DRRS work.
v6: Internal review comments. Removed check for primary enabled, which is
a redundant check, in the case of clone mode. Added a flag to track
dual-display configuration. Remove print statement for "cancel DRR work"
and print "DRRS not supported" only once.
v7: As per internal review comments, removing calls to update/disable drrs
from sprite update path. For sprite, all drrs related updates would be
taken care of with calls to crtc page flip itself. This will have to be
revisited later if flip infrastructure changes for sprite.
v8: Incorporated Jani's review comments. Added space after the periods in the
module param description. Changes around drrs-fini to remove seamless DRRS
check.
v9: Added checks for PSR before updating DRRS. Added check for module
param drrs_interval before updating DRRS (this is required if the interval
is modified by the user during system use). DRRS disabled by default. Changes
based on Jani's review comments
v10: Disable/enable DRRS when PSR is enable/disabled.
v11: Moved DRRS not supported log to patch2.
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 7 ++
drivers/gpu/drm/i915/i915_params.c | 8 ++
drivers/gpu/drm/i915/intel_display.c | 16 ++++
drivers/gpu/drm/i915/intel_dp.c | 27 ++++++-
drivers/gpu/drm/i915/intel_drv.h | 5 +-
drivers/gpu/drm/i915/intel_pm.c | 142 +++++++++++++++++++++++++++++++++++
6 files changed, 203 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9da8d83..fb9f9f0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -635,6 +635,12 @@ struct i915_fbc {
struct i915_drrs {
struct intel_connector *connector;
+ bool is_clone;
+ struct intel_drrs_work {
+ struct delayed_work work;
+ struct drm_crtc *crtc;
+ int interval;
+ } *drrs_work;
};
struct i915_psr {
@@ -1922,6 +1928,7 @@ struct i915_params {
int enable_ips;
int invert_brightness;
int enable_cmd_parser;
+ int drrs_interval;
/* leave bools at the end to not create holes */
bool enable_hangcheck;
bool fastboot;
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d05a2af..144ab0b 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -48,6 +48,7 @@ struct i915_params i915 __read_mostly = {
.disable_display = 0,
.enable_cmd_parser = 1,
.disable_vtd_wa = 0,
+ .drrs_interval = 0,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -156,3 +157,10 @@ MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)"
module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled [default], 0=disabled)");
+
+module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
+MODULE_PARM_DESC(drrs_interval,
+ "DRRS idleness detection interval (default: 0 ms). "
+ "If this field is set to 0, then seamless DRRS feature "
+ "based on idleness detection is disabled. "
+ "The interval is to be set in milliseconds.");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3697433..363ca22 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2523,6 +2523,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
@@ -3695,6 +3696,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -3738,6 +3740,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
drm_vblank_on(dev, pipe);
@@ -3935,6 +3938,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -3982,6 +3986,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -4376,6 +4381,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4423,6 +4429,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_crtc_dpms_overlay(intel_crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4490,6 +4497,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
}
static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -8510,6 +8518,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
drm_gem_object_unreference(&work->pending_flip_obj->base);
drm_gem_object_unreference(&work->old_fb_obj->base);
+ /* disable current DRRS work scheduled and restart
+ * to push work by another x seconds
+ */
+ intel_update_drrs(dev);
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
@@ -8968,6 +8980,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup_pending;
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
intel_mark_fb_busy(obj, NULL);
mutex_unlock(&dev->struct_mutex);
@@ -11341,6 +11354,7 @@ void intel_modeset_init(struct drm_device *dev)
/* Just in case the BIOS is doing something questionable. */
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
mutex_lock(&dev->mode_config.mutex);
intel_modeset_setup_hw_state(dev, false);
@@ -11821,6 +11835,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
+
intel_disable_gt_powersave(dev);
ironlake_teardown_rc6(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 5f41c25..7a3cb28 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1740,6 +1740,11 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
intel_edp_is_psr_enabled(dev))
return;
+ if (INTEL_INFO(dev)->gen < 8) {
+ DRM_DEBUG_KMS("Enabling PSR, disabling DRRS\n");
+ intel_disable_drrs(dev);
+ }
+
/* Setup PSR once */
intel_edp_psr_setup(intel_dp);
@@ -1774,6 +1779,9 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
DRM_ERROR("Timed out waiting for PSR Idle State\n");
+
+ if (INTEL_INFO(dev)->gen < 8)
+ intel_update_drrs(dev);
}
void intel_edp_psr_update(struct drm_device *dev)
@@ -3372,16 +3380,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
kfree(connector);
}
+static void
+intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
+{
+ if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
+ kfree(dev_priv->drrs.drrs_work);
+ dev_priv->drrs.drrs_work = NULL;
+ dev_priv->drrs.connector = NULL;
+ }
+}
+
void intel_dp_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+
+ if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
+ intel_dp == enc_to_intel_dp(
+ &dev_priv->drrs.connector->encoder->base))
+ intel_dp_drrs_fini(dev_priv);
+
mutex_lock(&dev->mode_config.mutex);
edp_panel_vdd_off_sync(intel_dp);
mutex_unlock(&dev->mode_config.mutex);
@@ -3765,7 +3790,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
if (downclock_mode != NULL &&
dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
- dev_priv->drrs.connector = intel_connector;
+ intel_init_drrs_idleness_detection(dev, intel_connector);
mutex_init(&intel_dp->drrs_state.mutex);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 37d56e5..de1357b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -932,7 +932,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
void ilk_wm_get_hw_state(struct drm_device *dev);
-
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector);
+void intel_update_drrs(struct drm_device *dev);
+void intel_disable_drrs(struct drm_device *dev);
/* intel_sdvo.c */
bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 04af065..0c43329 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -621,6 +621,148 @@ out_disable:
i915_gem_stolen_cleanup_compression(dev);
}
+static void intel_drrs_work_fn(struct work_struct *__work)
+{
+ struct intel_drrs_work *work =
+ container_of(to_delayed_work(__work),
+ struct intel_drrs_work, work);
+ struct drm_device *dev = work->crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Double check if the dual-display mode is active. */
+ if (dev_priv->drrs.is_clone)
+ return;
+
+ intel_dp_set_drrs_state(work->crtc->dev,
+ dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
+}
+
+static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
+{
+ if (dev_priv->drrs.drrs_work == NULL)
+ return;
+
+ cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
+}
+
+static void intel_enable_drrs(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ intel_cancel_drrs_work(dev_priv);
+
+ if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
+ dev_priv->drrs.drrs_work->crtc = crtc;
+ dev_priv->drrs.drrs_work->interval = i915.drrs_interval;
+
+ /* Delay the actual enabling to let pageflipping cease and the
+ * display to settle before starting DRRS
+ */
+ schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
+ msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
+ }
+}
+
+void intel_disable_drrs(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ /* as part of disable DRRS, reset refresh rate to HIGH_RR */
+ if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
+ intel_cancel_drrs_work(dev_priv);
+ intel_dp_set_drrs_state(dev,
+ dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
+ }
+}
+
+/**
+ * intel_update_drrs - enable/disable DRRS as needed
+ * @dev: the drm_device
+*/
+void intel_update_drrs(struct drm_device *dev)
+{
+ struct drm_crtc *crtc = NULL, *tmp_crtc;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0) {
+ intel_disable_drrs(dev);
+ return;
+ }
+
+ /* if drrs.connector is NULL, then drrs_init did not get called.
+ * which means DRRS is not supported.
+ */
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
+ return;
+
+ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+ if (intel_crtc_active(tmp_crtc)) {
+ if (crtc) {
+ DRM_DEBUG_KMS(
+ "more than one pipe active, disabling DRRS\n");
+ dev_priv->drrs.is_clone = true;
+ intel_disable_drrs(dev);
+ return;
+ }
+ crtc = tmp_crtc;
+ }
+ }
+
+ if (crtc == NULL) {
+ DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
+ return;
+ }
+
+ dev_priv->drrs.is_clone = false;
+ intel_disable_drrs(dev);
+
+ /* re-enable idleness detection */
+ intel_enable_drrs(crtc);
+}
+
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector)
+{
+ struct intel_drrs_work *work;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0)
+ DRM_INFO("DRRS disable by flag\n");
+
+ work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
+ if (!work) {
+ DRM_ERROR("Failed to allocate DRRS work structure\n");
+ return;
+ }
+
+ dev_priv->drrs.connector = connector;
+ dev_priv->drrs.is_clone = false;
+
+ work->interval = i915.drrs_interval;
+ INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
+
+ dev_priv->drrs.drrs_work = work;
+}
+
static void i915_pineview_get_mem_freq(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v10 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-04 10:47 ` [PATCH v10 " Vandana Kannan
@ 2014-04-04 10:55 ` Jani Nikula
2014-04-04 11:13 ` Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-04 10:55 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
On Fri, 04 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
>
> This patch and finds out the lowest refresh rate supported for the resolution
> same as the fixed_mode.
> It also checks the VBT fields to see if panel supports seamless DRRS or not.
> Based on above data it marks whether eDP panel supports seamless DRRS or not.
> This information is needed for supporting seamless DRRS switch for certain
> power saving usecases. This patch is tested by enabling the DRM logs and
> user should see whether Seamless DRRS is supported or not.
>
> v2: Daniel's review comments
> Modified downclock deduction based on intel_find_panel_downclock
>
> v3: Chris's review comments
> Moved edp_downclock_avail and edp_downclock to intel_panel
>
> v4: Jani's review comments.
> Changed name of the enum edp_panel_type to drrs_support type.
> Change is_drrs_supported to drrs_support of type enum drrs_support_type.
>
> v5: Incorporated Jani's review comments
> Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
> and above.
>
> v6: Incorporated Chris's review comments.
> Changed initialize to init in intel_drrs_initialize
>
> v7: Incorporated Jani's review comments.
> Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
> Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
>
> v8: Made changes to track PSR enable/disable throughout system use (instead
> of just in the init sequence) for disabling/enabling DRRS. Jani's review
> comments.
>
> v9: PSR tracking will be done as part of idleness detection patch. Removed
> PSR state tracker in i915_drrs. Jani's review comments.
>
> v10: Added log for DRRS not supported in drrs_init
>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/intel_dp.c | 45 +++++++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++++
> 2 files changed, 60 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index e48d47c..9f110bd 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3632,6 +3632,43 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> I915_READ(pp_div_reg));
> }
>
> +static struct drm_display_mode *
> +intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> + struct intel_connector *intel_connector,
> + struct drm_display_mode *fixed_mode)
> +{
> + struct drm_connector *connector = &intel_connector->base;
> + struct intel_dp *intel_dp = &intel_dig_port->dp;
> + struct drm_device *dev = intel_dig_port->base.base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct drm_display_mode *downclock_mode = NULL;
> +
> + if (INTEL_INFO(dev)->gen <= 6) {
> + DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
> + return NULL;
> + }
> +
> + if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
> + DRM_INFO("VBT doesn't support DRRS\n");
> + return NULL;
> + }
> +
> + downclock_mode = intel_find_panel_downclock
> + (dev, fixed_mode, connector);
> +
> + if (downclock_mode != NULL &&
> + dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
> + intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> +
> + intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> + DRM_INFO("seamless DRRS supported for eDP panel.\n");
> + return downclock_mode;
> + } else {
> + DRM_INFO("DRRS not supported\n");
> + return NULL;
> + }
The above now leaks downclock_mode on the return NULL path. Please try
to be more careful.
Please let's try to bring this patchset and review into
conclusion. We'll both end up frustrated otherwise.
How about this instead?
if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
DRM_INFO("VBT doesn't support DRRS\n");
return NULL;
}
downclock_mode = intel_find_panel_downclock(dev, fixed_mode, connector);
if (!downclock_mode) {
DRM_INFO("DRRS not supported\n");
return NULL;
}
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
DRM_INFO("seamless DRRS supported for eDP panel.\n");
return downclock_mode;
BR,
Jani.
> +}
> +
> static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> struct intel_connector *intel_connector,
> struct edp_power_seq *power_seq)
> @@ -3641,10 +3678,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> struct drm_device *dev = intel_dig_port->base.base.dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct drm_display_mode *fixed_mode = NULL;
> + struct drm_display_mode *downclock_mode = NULL;
> bool has_dpcd;
> struct drm_display_mode *scan;
> struct edid *edid;
>
> + intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
> +
> if (!is_edp(intel_dp))
> return true;
>
> @@ -3687,6 +3727,9 @@ 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_dig_port,
> + intel_connector, fixed_mode);
> break;
> }
> }
> @@ -3700,7 +3743,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> }
> mutex_unlock(&dev->mode_config.mutex);
>
> - intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> + intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> intel_panel_setup_backlight(connector);
>
> return true;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 42762b7..286d4fb 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -482,6 +482,17 @@ struct intel_hdmi {
>
> #define DP_MAX_DOWNSTREAM_PORTS 0x10
>
> +/**
> + * 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 edp_drrs_refresh_rate_type {
> + DRRS_HIGH_RR,
> + DRRS_LOW_RR,
> + DRRS_MAX_RR, /* RR count */
> +};
> +
> struct intel_dp {
> uint32_t output_reg;
> uint32_t aux_ch_ctl_reg;
> @@ -520,6 +531,11 @@ struct intel_dp {
> bool has_aux_irq,
> int send_bytes,
> uint32_t aux_clock_divider);
> + struct {
> + enum drrs_support_type type;
> + enum edp_drrs_refresh_rate_type refresh_rate_type;
> + } drrs_state;
> +
> };
>
> struct intel_digital_port {
> --
> 1.9.1
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v10 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-04 10:55 ` Jani Nikula
@ 2014-04-04 11:13 ` Vandana Kannan
2014-04-05 6:42 ` [PATCH v11 " Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-04 11:13 UTC (permalink / raw)
To: Jani Nikula; +Cc: intel-gfx@lists.freedesktop.org
On Apr-04-2014 4:25 PM, Jani Nikula wrote:
> On Fri, 04 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
>> From: Pradeep Bhat <pradeep.bhat@intel.com>
>>
>> This patch and finds out the lowest refresh rate supported for the resolution
>> same as the fixed_mode.
>> It also checks the VBT fields to see if panel supports seamless DRRS or not.
>> Based on above data it marks whether eDP panel supports seamless DRRS or not.
>> This information is needed for supporting seamless DRRS switch for certain
>> power saving usecases. This patch is tested by enabling the DRM logs and
>> user should see whether Seamless DRRS is supported or not.
>>
>> v2: Daniel's review comments
>> Modified downclock deduction based on intel_find_panel_downclock
>>
>> v3: Chris's review comments
>> Moved edp_downclock_avail and edp_downclock to intel_panel
>>
>> v4: Jani's review comments.
>> Changed name of the enum edp_panel_type to drrs_support type.
>> Change is_drrs_supported to drrs_support of type enum drrs_support_type.
>>
>> v5: Incorporated Jani's review comments
>> Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
>> and above.
>>
>> v6: Incorporated Chris's review comments.
>> Changed initialize to init in intel_drrs_initialize
>>
>> v7: Incorporated Jani's review comments.
>> Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
>> Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
>>
>> v8: Made changes to track PSR enable/disable throughout system use (instead
>> of just in the init sequence) for disabling/enabling DRRS. Jani's review
>> comments.
>>
>> v9: PSR tracking will be done as part of idleness detection patch. Removed
>> PSR state tracker in i915_drrs. Jani's review comments.
>>
>> v10: Added log for DRRS not supported in drrs_init
>>
>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> ---
>> drivers/gpu/drm/i915/intel_dp.c | 45 +++++++++++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++++
>> 2 files changed, 60 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index e48d47c..9f110bd 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -3632,6 +3632,43 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>> I915_READ(pp_div_reg));
>> }
>>
>> +static struct drm_display_mode *
>> +intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>> + struct intel_connector *intel_connector,
>> + struct drm_display_mode *fixed_mode)
>> +{
>> + struct drm_connector *connector = &intel_connector->base;
>> + struct intel_dp *intel_dp = &intel_dig_port->dp;
>> + struct drm_device *dev = intel_dig_port->base.base.dev;
>> + struct drm_i915_private *dev_priv = dev->dev_private;
>> + struct drm_display_mode *downclock_mode = NULL;
>> +
>> + if (INTEL_INFO(dev)->gen <= 6) {
>> + DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
>> + return NULL;
>> + }
>> +
>> + if (dev_priv->vbt.drrs_type == DRRS_NOT_SUPPORTED) {
>> + DRM_INFO("VBT doesn't support DRRS\n");
>> + return NULL;
>> + }
>> +
>> + downclock_mode = intel_find_panel_downclock
>> + (dev, fixed_mode, connector);
>> +
>> + if (downclock_mode != NULL &&
>> + dev_priv->vbt.drrs_type == SEAMLESS_DRRS_SUPPORT) {
>> + intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
>> +
>> + intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
>> + DRM_INFO("seamless DRRS supported for eDP panel.\n");
>> + return downclock_mode;
>> + } else {
>> + DRM_INFO("DRRS not supported\n");
>> + return NULL;
>> + }
>
> The above now leaks downclock_mode on the return NULL path. Please try
> to be more careful.
>
> Please let's try to bring this patchset and review into
> conclusion. We'll both end up frustrated otherwise.
>
> How about this instead?
>
> if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
> DRM_INFO("VBT doesn't support DRRS\n");
> return NULL;
> }
>
> downclock_mode = intel_find_panel_downclock(dev, fixed_mode, connector);
> if (!downclock_mode) {
> DRM_INFO("DRRS not supported\n");
> return NULL;
> }
>
> intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> DRM_INFO("seamless DRRS supported for eDP panel.\n");
>
> return downclock_mode;
>
>
> BR,
> Jani.
>
>
Thanks.
Will make this change and resend.
-Vandana
>> +}
>> +
>> static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>> struct intel_connector *intel_connector,
>> struct edp_power_seq *power_seq)
>> @@ -3641,10 +3678,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>> struct drm_device *dev = intel_dig_port->base.base.dev;
>> struct drm_i915_private *dev_priv = dev->dev_private;
>> struct drm_display_mode *fixed_mode = NULL;
>> + struct drm_display_mode *downclock_mode = NULL;
>> bool has_dpcd;
>> struct drm_display_mode *scan;
>> struct edid *edid;
>>
>> + intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
>> +
>> if (!is_edp(intel_dp))
>> return true;
>>
>> @@ -3687,6 +3727,9 @@ 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_dig_port,
>> + intel_connector, fixed_mode);
>> break;
>> }
>> }
>> @@ -3700,7 +3743,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>> }
>> mutex_unlock(&dev->mode_config.mutex);
>>
>> - intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
>> + intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
>> intel_panel_setup_backlight(connector);
>>
>> return true;
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 42762b7..286d4fb 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -482,6 +482,17 @@ struct intel_hdmi {
>>
>> #define DP_MAX_DOWNSTREAM_PORTS 0x10
>>
>> +/**
>> + * 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 edp_drrs_refresh_rate_type {
>> + DRRS_HIGH_RR,
>> + DRRS_LOW_RR,
>> + DRRS_MAX_RR, /* RR count */
>> +};
>> +
>> struct intel_dp {
>> uint32_t output_reg;
>> uint32_t aux_ch_ctl_reg;
>> @@ -520,6 +531,11 @@ struct intel_dp {
>> bool has_aux_irq,
>> int send_bytes,
>> uint32_t aux_clock_divider);
>> + struct {
>> + enum drrs_support_type type;
>> + enum edp_drrs_refresh_rate_type refresh_rate_type;
>> + } drrs_state;
>> +
>> };
>>
>> struct intel_digital_port {
>> --
>> 1.9.1
>>
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v11 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-04 11:13 ` Vandana Kannan
@ 2014-04-05 6:42 ` Vandana Kannan
2014-04-10 8:42 ` Jani Nikula
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-05 6:42 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch and finds out the lowest refresh rate supported for the resolution
same as the fixed_mode.
It also checks the VBT fields to see if panel supports seamless DRRS or not.
Based on above data it marks whether eDP panel supports seamless DRRS or not.
This information is needed for supporting seamless DRRS switch for certain
power saving usecases. This patch is tested by enabling the DRM logs and
user should see whether Seamless DRRS is supported or not.
v2: Daniel's review comments
Modified downclock deduction based on intel_find_panel_downclock
v3: Chris's review comments
Moved edp_downclock_avail and edp_downclock to intel_panel
v4: Jani's review comments.
Changed name of the enum edp_panel_type to drrs_support type.
Change is_drrs_supported to drrs_support of type enum drrs_support_type.
v5: Incorporated Jani's review comments
Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
and above.
v6: Incorporated Chris's review comments.
Changed initialize to init in intel_drrs_initialize
v7: Incorporated Jani's review comments.
Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
v8: Made changes to track PSR enable/disable throughout system use (instead
of just in the init sequence) for disabling/enabling DRRS. Jani's review
comments.
v9: PSR tracking will be done as part of idleness detection patch. Removed
PSR state tracker in i915_drrs. Jani's review comments.
v10: Added log for DRRS not supported in drrs_init
v11: Modification in drrs_init. suggested by Jani
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 44 +++++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_drv.h | 16 +++++++++++++++
2 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e48d47c..517a8cc 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3632,6 +3632,42 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+static struct drm_display_mode *
+intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
+ struct intel_connector *intel_connector,
+ struct drm_display_mode *fixed_mode)
+{
+ struct drm_connector *connector = &intel_connector->base;
+ struct intel_dp *intel_dp = &intel_dig_port->dp;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_display_mode *downclock_mode = NULL;
+
+ 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_INFO("VBT doesn't support DRRS\n");
+ return NULL;
+ }
+
+ downclock_mode = intel_find_panel_downclock
+ (dev, fixed_mode, connector);
+
+ if (!downclock_mode) {
+ DRM_INFO("DRRS not supported\n");
+ return NULL;
+ }
+
+ intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
+
+ intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
+ DRM_INFO("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,
struct edp_power_seq *power_seq)
@@ -3641,10 +3677,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = NULL;
+ struct drm_display_mode *downclock_mode = NULL;
bool has_dpcd;
struct drm_display_mode *scan;
struct edid *edid;
+ intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
+
if (!is_edp(intel_dp))
return true;
@@ -3687,6 +3726,9 @@ 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_dig_port,
+ intel_connector, fixed_mode);
break;
}
}
@@ -3700,7 +3742,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
mutex_unlock(&dev->mode_config.mutex);
- intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector);
return true;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 42762b7..286d4fb 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -482,6 +482,17 @@ struct intel_hdmi {
#define DP_MAX_DOWNSTREAM_PORTS 0x10
+/**
+ * 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 edp_drrs_refresh_rate_type {
+ DRRS_HIGH_RR,
+ DRRS_LOW_RR,
+ DRRS_MAX_RR, /* RR count */
+};
+
struct intel_dp {
uint32_t output_reg;
uint32_t aux_ch_ctl_reg;
@@ -520,6 +531,11 @@ struct intel_dp {
bool has_aux_irq,
int send_bytes,
uint32_t aux_clock_divider);
+ struct {
+ enum drrs_support_type type;
+ enum edp_drrs_refresh_rate_type refresh_rate_type;
+ } drrs_state;
+
};
struct intel_digital_port {
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-04 4:58 ` Vandana Kannan
@ 2014-04-05 6:43 ` Vandana Kannan
2014-04-10 8:43 ` Jani Nikula
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-05 6:43 UTC (permalink / raw)
To: intel-gfx
From: Pradeep Bhat <pradeep.bhat@intel.com>
This patch computes and stored 2nd M/N/TU for switching to different
refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
between alternate refresh rates programmed in 2nd M/N/TU registers.
v2: Daniel's review comments
Computing M2/N2 in compute_config and storing it in crtc_config
v3: Modified reference to edp_downclock and edp_downclock_avail based on the
changes made to move them from dev_private to intel_panel.
v4: Modified references to is_drrs_supported based on the changes made to
rename it to drrs_support.
v5: Jani's review comments
Removed superfluous return statements. Changed support for Gen 7 and above.
Corrected indentation. Re-structured the code which finds crtc and connector
from encoder. Changed some logs to be less verbose.
v6: Modifying i915_drrs to include only intel connector as intel_dp can be
derived from intel connector when required.
v7: As per internal review comments, acquiring mutex just before accessing
drrs RR. As per Chris's review comments, added documentation about the use
of locking in the function.
v8: Incorporated Jani's review comments.
Removed reference to edp_downclock.
v9: Jani's review comments. Modified comment in set_drrs. Changed index to
type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
registers fo DRRS.
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 5 ++
drivers/gpu/drm/i915/i915_reg.h | 1 +
drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_drv.h | 6 ++-
4 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 55addaa..9da8d83 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -633,6 +633,10 @@ struct i915_fbc {
} no_fbc_reason;
};
+struct i915_drrs {
+ struct intel_connector *connector;
+};
+
struct i915_psr {
bool sink_support;
bool source_ok;
@@ -1320,6 +1324,7 @@ struct drm_i915_private {
struct timer_list hotplug_reenable_timer;
struct i915_fbc fbc;
+ struct i915_drrs drrs;
struct intel_opregion opregion;
struct intel_vbt_data vbt;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2315366..d6dddc2 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3346,6 +3346,7 @@ enum punit_power_well {
#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
#define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
+#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
#define PIPECONF_BPC_MASK (0x7 << 5)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 517a8cc..b50b170 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
}
}
+static void
+intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum transcoder transcoder = crtc->config.cpu_transcoder;
+
+ I915_WRITE(PIPE_DATA_M2(transcoder),
+ TU_SIZE(m_n->tu) | m_n->gmch_m);
+ I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
+ I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
+ I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
+}
+
bool
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
@@ -841,6 +855,14 @@ found:
pipe_config->port_clock,
&pipe_config->dp_m_n);
+ if (intel_connector->panel.downclock_mode != NULL &&
+ intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
+ intel_link_compute_m_n(bpp, lane_count,
+ intel_connector->panel.downclock_mode->clock,
+ pipe_config->port_clock,
+ &pipe_config->dp_m2_n2);
+ }
+
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
return true;
@@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
I915_READ(pp_div_reg));
}
+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_dp *intel_dp = NULL;
+ struct intel_crtc_config *config = NULL;
+ struct intel_crtc *intel_crtc = NULL;
+ struct intel_connector *intel_connector = dev_priv->drrs.connector;
+ u32 reg, val;
+ enum edp_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_connector == NULL) {
+ DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
+ return;
+ }
+
+ if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
+ DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
+ return;
+ }
+
+ encoder = intel_attached_encoder(&intel_connector->base);
+ intel_dp = enc_to_intel_dp(&encoder->base);
+ intel_crtc = encoder->new_crtc;
+
+ if (!intel_crtc) {
+ DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
+ return;
+ }
+
+ config = &intel_crtc->config;
+
+ if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
+ DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
+ return;
+ }
+
+ if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
+ index = DRRS_LOW_RR;
+
+ if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
+ reg = PIPECONF(intel_crtc->config.cpu_transcoder);
+ val = I915_READ(reg);
+ if (index > DRRS_HIGH_RR) {
+ val |= PIPECONF_EDP_RR_MODE_SWITCH;
+ intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
+ } else {
+ val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
+ }
+ I915_WRITE(reg, val);
+ }
+
+ /*
+ * mutex taken to ensure that there is no race between differnt
+ * drrs calls trying to update refresh rate. This scenario may occur
+ * in future when idleness detection based DRRS in kernel and
+ * possible calls from user space to set differnt RR are made.
+ */
+
+ mutex_lock(&intel_dp->drrs_state.mutex);
+
+ intel_dp->drrs_state.refresh_rate_type = index;
+
+ mutex_unlock(&intel_dp->drrs_state.mutex);
+
+ DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
+}
+
static struct drm_display_mode *
intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector,
@@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
return NULL;
}
+ dev_priv->drrs.connector = intel_connector;
+
+ mutex_init(&intel_dp->drrs_state.mutex);
+
intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 286d4fb..37d56e5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -305,6 +305,9 @@ struct intel_crtc_config {
int pipe_bpp;
struct intel_link_m_n dp_m_n;
+ /* m2_n2 for eDP downclock */
+ struct intel_link_m_n dp_m2_n2;
+
/*
* Frequence the dpll for the port should run at. Differs from the
* adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
@@ -534,6 +537,7 @@ struct intel_dp {
struct {
enum drrs_support_type type;
enum edp_drrs_refresh_rate_type refresh_rate_type;
+ struct mutex mutex;
} drrs_state;
};
@@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
void intel_edp_psr_enable(struct intel_dp *intel_dp);
void intel_edp_psr_disable(struct intel_dp *intel_dp);
void intel_edp_psr_update(struct drm_device *dev);
-
+void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
/* intel_dsi.c */
bool intel_dsi_init(struct drm_device *dev);
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v11 4/6] drm/i915: Idleness detection for DRRS
2014-04-04 10:53 ` [PATCH v11 " Vandana Kannan
@ 2014-04-05 6:44 ` Vandana Kannan
2014-04-10 8:52 ` Jani Nikula
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-05 6:44 UTC (permalink / raw)
To: intel-gfx
Adding support to detect display idleness by tracking page flip from
user space. Switch to low refresh rate is triggered after 2 seconds of
idleness. The delay is configurable. If there is a page flip or call to
update the plane, then high refresh rate is applied.
The feature is not used in dual-display mode.
v2: Chris Wilson's review comments incorporated.
Modify idleness detection implementation to make it similar to the
implementation of intel_update_fbc/intel_disable_fbc
v3: Internal review comments incorporated
Add NULL pointer check in intel_disable_drrs.
Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
v4: Jani's review comments incorporated.
Change in sequence in intel_update_drrs. Comment modified to remove details
of update param. Modified DRRS idleness interval to a module parameter.
v5: Chris's review comments incorporated.
Initialize connector in idleness detection init. Modifications made to
use only intel_connector in i915_drrs and derive intel_dp when required.
Added a function drrs_fini to cleanup DRRS work.
v6: Internal review comments. Removed check for primary enabled, which is
a redundant check, in the case of clone mode. Added a flag to track
dual-display configuration. Remove print statement for "cancel DRR work"
and print "DRRS not supported" only once.
v7: As per internal review comments, removing calls to update/disable drrs
from sprite update path. For sprite, all drrs related updates would be
taken care of with calls to crtc page flip itself. This will have to be
revisited later if flip infrastructure changes for sprite.
v8: Incorporated Jani's review comments. Added space after the periods in the
module param description. Changes around drrs-fini to remove seamless DRRS
check.
v9: Added checks for PSR before updating DRRS. Added check for module
param drrs_interval before updating DRRS (this is required if the interval
is modified by the user during system use). DRRS disabled by default. Changes
based on Jani's review comments
v10: Disable/enable DRRS when PSR is enable/disabled.
v11: Moved DRRS not supported log to patch2.
Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 7 ++
drivers/gpu/drm/i915/i915_params.c | 8 ++
drivers/gpu/drm/i915/intel_display.c | 16 ++++
drivers/gpu/drm/i915/intel_dp.c | 27 ++++++-
drivers/gpu/drm/i915/intel_drv.h | 5 +-
drivers/gpu/drm/i915/intel_pm.c | 142 +++++++++++++++++++++++++++++++++++
6 files changed, 203 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9da8d83..fb9f9f0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -635,6 +635,12 @@ struct i915_fbc {
struct i915_drrs {
struct intel_connector *connector;
+ bool is_clone;
+ struct intel_drrs_work {
+ struct delayed_work work;
+ struct drm_crtc *crtc;
+ int interval;
+ } *drrs_work;
};
struct i915_psr {
@@ -1922,6 +1928,7 @@ struct i915_params {
int enable_ips;
int invert_brightness;
int enable_cmd_parser;
+ int drrs_interval;
/* leave bools at the end to not create holes */
bool enable_hangcheck;
bool fastboot;
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d05a2af..144ab0b 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -48,6 +48,7 @@ struct i915_params i915 __read_mostly = {
.disable_display = 0,
.enable_cmd_parser = 1,
.disable_vtd_wa = 0,
+ .drrs_interval = 0,
};
module_param_named(modeset, i915.modeset, int, 0400);
@@ -156,3 +157,10 @@ MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)"
module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled [default], 0=disabled)");
+
+module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
+MODULE_PARM_DESC(drrs_interval,
+ "DRRS idleness detection interval (default: 0 ms). "
+ "If this field is set to 0, then seamless DRRS feature "
+ "based on idleness detection is disabled. "
+ "The interval is to be set in milliseconds.");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3697433..363ca22 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2523,6 +2523,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
intel_edp_psr_update(dev);
mutex_unlock(&dev->struct_mutex);
@@ -3695,6 +3696,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -3738,6 +3740,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
drm_vblank_on(dev, pipe);
@@ -3935,6 +3938,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -3982,6 +3986,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
mutex_unlock(&dev->struct_mutex);
}
@@ -4376,6 +4381,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_update_cursor(crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4423,6 +4429,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_crtc_dpms_overlay(intel_crtc, true);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->enable(encoder);
@@ -4490,6 +4497,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);
intel_update_fbc(dev);
+ intel_update_drrs(dev);
}
static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -8510,6 +8518,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
drm_gem_object_unreference(&work->pending_flip_obj->base);
drm_gem_object_unreference(&work->old_fb_obj->base);
+ /* disable current DRRS work scheduled and restart
+ * to push work by another x seconds
+ */
+ intel_update_drrs(dev);
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
@@ -8968,6 +8980,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup_pending;
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
intel_mark_fb_busy(obj, NULL);
mutex_unlock(&dev->struct_mutex);
@@ -11341,6 +11354,7 @@ void intel_modeset_init(struct drm_device *dev)
/* Just in case the BIOS is doing something questionable. */
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
mutex_lock(&dev->mode_config.mutex);
intel_modeset_setup_hw_state(dev, false);
@@ -11821,6 +11835,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
intel_disable_fbc(dev);
+ intel_disable_drrs(dev);
+
intel_disable_gt_powersave(dev);
ironlake_teardown_rc6(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b50b170..5fc4060 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1739,6 +1739,11 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
intel_edp_is_psr_enabled(dev))
return;
+ if (INTEL_INFO(dev)->gen < 8) {
+ DRM_DEBUG_KMS("Enabling PSR, disabling DRRS\n");
+ intel_disable_drrs(dev);
+ }
+
/* Setup PSR once */
intel_edp_psr_setup(intel_dp);
@@ -1773,6 +1778,9 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
DRM_ERROR("Timed out waiting for PSR Idle State\n");
+
+ if (INTEL_INFO(dev)->gen < 8)
+ intel_update_drrs(dev);
}
void intel_edp_psr_update(struct drm_device *dev)
@@ -3371,16 +3379,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
kfree(connector);
}
+static void
+intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
+{
+ if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
+ kfree(dev_priv->drrs.drrs_work);
+ dev_priv->drrs.drrs_work = NULL;
+ dev_priv->drrs.connector = NULL;
+ }
+}
+
void intel_dp_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ struct drm_i915_private *dev_priv = dev->dev_private;
drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+
+ if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
+ intel_dp == enc_to_intel_dp(
+ &dev_priv->drrs.connector->encoder->base))
+ intel_dp_drrs_fini(dev_priv);
+
mutex_lock(&dev->mode_config.mutex);
edp_panel_vdd_off_sync(intel_dp);
mutex_unlock(&dev->mode_config.mutex);
@@ -3767,7 +3792,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
return NULL;
}
- dev_priv->drrs.connector = intel_connector;
+ intel_init_drrs_idleness_detection(dev, intel_connector);
mutex_init(&intel_dp->drrs_state.mutex);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 37d56e5..de1357b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -932,7 +932,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
void ilk_wm_get_hw_state(struct drm_device *dev);
-
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector);
+void intel_update_drrs(struct drm_device *dev);
+void intel_disable_drrs(struct drm_device *dev);
/* intel_sdvo.c */
bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 04af065..0c43329 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -621,6 +621,148 @@ out_disable:
i915_gem_stolen_cleanup_compression(dev);
}
+static void intel_drrs_work_fn(struct work_struct *__work)
+{
+ struct intel_drrs_work *work =
+ container_of(to_delayed_work(__work),
+ struct intel_drrs_work, work);
+ struct drm_device *dev = work->crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* Double check if the dual-display mode is active. */
+ if (dev_priv->drrs.is_clone)
+ return;
+
+ intel_dp_set_drrs_state(work->crtc->dev,
+ dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
+}
+
+static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
+{
+ if (dev_priv->drrs.drrs_work == NULL)
+ return;
+
+ cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
+}
+
+static void intel_enable_drrs(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ intel_cancel_drrs_work(dev_priv);
+
+ if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
+ dev_priv->drrs.drrs_work->crtc = crtc;
+ dev_priv->drrs.drrs_work->interval = i915.drrs_interval;
+
+ /* Delay the actual enabling to let pageflipping cease and the
+ * display to settle before starting DRRS
+ */
+ schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
+ msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
+ }
+}
+
+void intel_disable_drrs(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_dp *intel_dp = NULL;
+
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
+
+ if (intel_dp == NULL)
+ return;
+
+ /* as part of disable DRRS, reset refresh rate to HIGH_RR */
+ if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
+ intel_cancel_drrs_work(dev_priv);
+ intel_dp_set_drrs_state(dev,
+ dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
+ }
+}
+
+/**
+ * intel_update_drrs - enable/disable DRRS as needed
+ * @dev: the drm_device
+*/
+void intel_update_drrs(struct drm_device *dev)
+{
+ struct drm_crtc *crtc = NULL, *tmp_crtc;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0) {
+ intel_disable_drrs(dev);
+ return;
+ }
+
+ /* if drrs.connector is NULL, then drrs_init did not get called.
+ * which means DRRS is not supported.
+ */
+ if (dev_priv->drrs.connector == NULL)
+ return;
+
+ if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
+ return;
+
+ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
+ if (intel_crtc_active(tmp_crtc)) {
+ if (crtc) {
+ DRM_DEBUG_KMS(
+ "more than one pipe active, disabling DRRS\n");
+ dev_priv->drrs.is_clone = true;
+ intel_disable_drrs(dev);
+ return;
+ }
+ crtc = tmp_crtc;
+ }
+ }
+
+ if (crtc == NULL) {
+ DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
+ return;
+ }
+
+ dev_priv->drrs.is_clone = false;
+ intel_disable_drrs(dev);
+
+ /* re-enable idleness detection */
+ intel_enable_drrs(crtc);
+}
+
+void intel_init_drrs_idleness_detection(struct drm_device *dev,
+ struct intel_connector *connector)
+{
+ struct intel_drrs_work *work;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (i915.drrs_interval == 0)
+ DRM_INFO("DRRS disable by flag\n");
+
+ work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
+ if (!work) {
+ DRM_ERROR("Failed to allocate DRRS work structure\n");
+ return;
+ }
+
+ dev_priv->drrs.connector = connector;
+ dev_priv->drrs.is_clone = false;
+
+ work->interval = i915.drrs_interval;
+ INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
+
+ dev_priv->drrs.drrs_work = work;
+}
+
static void i915_pineview_get_mem_freq(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
--
1.9.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v11 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-05 6:42 ` [PATCH v11 " Vandana Kannan
@ 2014-04-10 8:42 ` Jani Nikula
2014-04-10 8:55 ` Daniel Vetter
0 siblings, 1 reply; 40+ messages in thread
From: Jani Nikula @ 2014-04-10 8:42 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
>
> This patch and finds out the lowest refresh rate supported for the resolution
> same as the fixed_mode.
> It also checks the VBT fields to see if panel supports seamless DRRS or not.
> Based on above data it marks whether eDP panel supports seamless DRRS or not.
> This information is needed for supporting seamless DRRS switch for certain
> power saving usecases. This patch is tested by enabling the DRM logs and
> user should see whether Seamless DRRS is supported or not.
>
> v2: Daniel's review comments
> Modified downclock deduction based on intel_find_panel_downclock
>
> v3: Chris's review comments
> Moved edp_downclock_avail and edp_downclock to intel_panel
>
> v4: Jani's review comments.
> Changed name of the enum edp_panel_type to drrs_support type.
> Change is_drrs_supported to drrs_support of type enum drrs_support_type.
>
> v5: Incorporated Jani's review comments
> Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
> and above.
>
> v6: Incorporated Chris's review comments.
> Changed initialize to init in intel_drrs_initialize
>
> v7: Incorporated Jani's review comments.
> Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
> Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
>
> v8: Made changes to track PSR enable/disable throughout system use (instead
> of just in the init sequence) for disabling/enabling DRRS. Jani's review
> comments.
>
> v9: PSR tracking will be done as part of idleness detection patch. Removed
> PSR state tracker in i915_drrs. Jani's review comments.
>
> v10: Added log for DRRS not supported in drrs_init
>
> v11: Modification in drrs_init. suggested by Jani
>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/intel_dp.c | 44 +++++++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/i915/intel_drv.h | 16 +++++++++++++++
> 2 files changed, 59 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index e48d47c..517a8cc 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3632,6 +3632,42 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> I915_READ(pp_div_reg));
> }
>
> +static struct drm_display_mode *
> +intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> + struct intel_connector *intel_connector,
> + struct drm_display_mode *fixed_mode)
> +{
> + struct drm_connector *connector = &intel_connector->base;
> + struct intel_dp *intel_dp = &intel_dig_port->dp;
> + struct drm_device *dev = intel_dig_port->base.base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct drm_display_mode *downclock_mode = NULL;
> +
> + 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_INFO("VBT doesn't support DRRS\n");
> + return NULL;
> + }
> +
> + downclock_mode = intel_find_panel_downclock
> + (dev, fixed_mode, connector);
> +
> + if (!downclock_mode) {
> + DRM_INFO("DRRS not supported\n");
> + return NULL;
> + }
> +
> + intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> +
> + intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> + DRM_INFO("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,
> struct edp_power_seq *power_seq)
> @@ -3641,10 +3677,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> struct drm_device *dev = intel_dig_port->base.base.dev;
> struct drm_i915_private *dev_priv = dev->dev_private;
> struct drm_display_mode *fixed_mode = NULL;
> + struct drm_display_mode *downclock_mode = NULL;
> bool has_dpcd;
> struct drm_display_mode *scan;
> struct edid *edid;
>
> + intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
> +
> if (!is_edp(intel_dp))
> return true;
>
> @@ -3687,6 +3726,9 @@ 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_dig_port,
> + intel_connector, fixed_mode);
> break;
> }
> }
> @@ -3700,7 +3742,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> }
> mutex_unlock(&dev->mode_config.mutex);
>
> - intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> + intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> intel_panel_setup_backlight(connector);
>
> return true;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 42762b7..286d4fb 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -482,6 +482,17 @@ struct intel_hdmi {
>
> #define DP_MAX_DOWNSTREAM_PORTS 0x10
>
> +/**
> + * 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 edp_drrs_refresh_rate_type {
> + DRRS_HIGH_RR,
> + DRRS_LOW_RR,
> + DRRS_MAX_RR, /* RR count */
> +};
> +
> struct intel_dp {
> uint32_t output_reg;
> uint32_t aux_ch_ctl_reg;
> @@ -520,6 +531,11 @@ struct intel_dp {
> bool has_aux_irq,
> int send_bytes,
> uint32_t aux_clock_divider);
> + struct {
> + enum drrs_support_type type;
> + enum edp_drrs_refresh_rate_type refresh_rate_type;
> + } drrs_state;
> +
> };
>
> struct intel_digital_port {
> --
> 1.9.1
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-05 6:43 ` Vandana Kannan
@ 2014-04-10 8:43 ` Jani Nikula
2014-04-10 8:56 ` Daniel Vetter
2014-04-10 8:58 ` Daniel Vetter
0 siblings, 2 replies; 40+ messages in thread
From: Jani Nikula @ 2014-04-10 8:43 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> From: Pradeep Bhat <pradeep.bhat@intel.com>
>
> This patch computes and stored 2nd M/N/TU for switching to different
> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
> between alternate refresh rates programmed in 2nd M/N/TU registers.
>
> v2: Daniel's review comments
> Computing M2/N2 in compute_config and storing it in crtc_config
>
> v3: Modified reference to edp_downclock and edp_downclock_avail based on the
> changes made to move them from dev_private to intel_panel.
>
> v4: Modified references to is_drrs_supported based on the changes made to
> rename it to drrs_support.
>
> v5: Jani's review comments
> Removed superfluous return statements. Changed support for Gen 7 and above.
> Corrected indentation. Re-structured the code which finds crtc and connector
> from encoder. Changed some logs to be less verbose.
>
> v6: Modifying i915_drrs to include only intel connector as intel_dp can be
> derived from intel connector when required.
>
> v7: As per internal review comments, acquiring mutex just before accessing
> drrs RR. As per Chris's review comments, added documentation about the use
> of locking in the function.
>
> v8: Incorporated Jani's review comments.
> Removed reference to edp_downclock.
>
> v9: Jani's review comments. Modified comment in set_drrs. Changed index to
> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
> registers fo DRRS.
>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 5 ++
> drivers/gpu/drm/i915/i915_reg.h | 1 +
> drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/i915/intel_drv.h | 6 ++-
> 4 files changed, 121 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 55addaa..9da8d83 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -633,6 +633,10 @@ struct i915_fbc {
> } no_fbc_reason;
> };
>
> +struct i915_drrs {
> + struct intel_connector *connector;
> +};
> +
> struct i915_psr {
> bool sink_support;
> bool source_ok;
> @@ -1320,6 +1324,7 @@ struct drm_i915_private {
> struct timer_list hotplug_reenable_timer;
>
> struct i915_fbc fbc;
> + struct i915_drrs drrs;
> struct intel_opregion opregion;
> struct intel_vbt_data vbt;
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 2315366..d6dddc2 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3346,6 +3346,7 @@ enum punit_power_well {
> #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
> #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
> #define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
> +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
> #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
> #define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
> #define PIPECONF_BPC_MASK (0x7 << 5)
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 517a8cc..b50b170 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
> }
> }
>
> +static void
> +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
> +{
> + struct drm_device *dev = crtc->base.dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + enum transcoder transcoder = crtc->config.cpu_transcoder;
> +
> + I915_WRITE(PIPE_DATA_M2(transcoder),
> + TU_SIZE(m_n->tu) | m_n->gmch_m);
> + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
> + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
> + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
> +}
> +
> bool
> intel_dp_compute_config(struct intel_encoder *encoder,
> struct intel_crtc_config *pipe_config)
> @@ -841,6 +855,14 @@ found:
> pipe_config->port_clock,
> &pipe_config->dp_m_n);
>
> + if (intel_connector->panel.downclock_mode != NULL &&
> + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
> + intel_link_compute_m_n(bpp, lane_count,
> + intel_connector->panel.downclock_mode->clock,
> + pipe_config->port_clock,
> + &pipe_config->dp_m2_n2);
> + }
> +
> intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
>
> return true;
> @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> I915_READ(pp_div_reg));
> }
>
> +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_dp *intel_dp = NULL;
> + struct intel_crtc_config *config = NULL;
> + struct intel_crtc *intel_crtc = NULL;
> + struct intel_connector *intel_connector = dev_priv->drrs.connector;
> + u32 reg, val;
> + enum edp_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_connector == NULL) {
> + DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
> + return;
> + }
> +
> + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
> + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
> + return;
> + }
> +
> + encoder = intel_attached_encoder(&intel_connector->base);
> + intel_dp = enc_to_intel_dp(&encoder->base);
> + intel_crtc = encoder->new_crtc;
> +
> + if (!intel_crtc) {
> + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
> + return;
> + }
> +
> + config = &intel_crtc->config;
> +
> + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
> + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
> + return;
> + }
> +
> + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
> + index = DRRS_LOW_RR;
> +
> + if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
> + reg = PIPECONF(intel_crtc->config.cpu_transcoder);
> + val = I915_READ(reg);
> + if (index > DRRS_HIGH_RR) {
> + val |= PIPECONF_EDP_RR_MODE_SWITCH;
> + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
> + } else {
> + val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
> + }
> + I915_WRITE(reg, val);
> + }
> +
> + /*
> + * mutex taken to ensure that there is no race between differnt
> + * drrs calls trying to update refresh rate. This scenario may occur
> + * in future when idleness detection based DRRS in kernel and
> + * possible calls from user space to set differnt RR are made.
> + */
> +
> + mutex_lock(&intel_dp->drrs_state.mutex);
> +
> + intel_dp->drrs_state.refresh_rate_type = index;
> +
> + mutex_unlock(&intel_dp->drrs_state.mutex);
> +
> + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
> +}
> +
> static struct drm_display_mode *
> intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> struct intel_connector *intel_connector,
> @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> return NULL;
> }
>
> + dev_priv->drrs.connector = intel_connector;
> +
> + mutex_init(&intel_dp->drrs_state.mutex);
> +
> intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
>
> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 286d4fb..37d56e5 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -305,6 +305,9 @@ struct intel_crtc_config {
> int pipe_bpp;
> struct intel_link_m_n dp_m_n;
>
> + /* m2_n2 for eDP downclock */
> + struct intel_link_m_n dp_m2_n2;
> +
> /*
> * Frequence the dpll for the port should run at. Differs from the
> * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
> @@ -534,6 +537,7 @@ struct intel_dp {
> struct {
> enum drrs_support_type type;
> enum edp_drrs_refresh_rate_type refresh_rate_type;
> + struct mutex mutex;
> } drrs_state;
>
> };
> @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
> void intel_edp_psr_enable(struct intel_dp *intel_dp);
> void intel_edp_psr_disable(struct intel_dp *intel_dp);
> void intel_edp_psr_update(struct drm_device *dev);
> -
> +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
>
> /* intel_dsi.c */
> bool intel_dsi_init(struct drm_device *dev);
> --
> 1.9.1
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v11 4/6] drm/i915: Idleness detection for DRRS
2014-04-05 6:44 ` Vandana Kannan
@ 2014-04-10 8:52 ` Jani Nikula
0 siblings, 0 replies; 40+ messages in thread
From: Jani Nikula @ 2014-04-10 8:52 UTC (permalink / raw)
To: Vandana Kannan, intel-gfx
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> Adding support to detect display idleness by tracking page flip from
> user space. Switch to low refresh rate is triggered after 2 seconds of
> idleness. The delay is configurable. If there is a page flip or call to
> update the plane, then high refresh rate is applied.
> The feature is not used in dual-display mode.
>
> v2: Chris Wilson's review comments incorporated.
> Modify idleness detection implementation to make it similar to the
> implementation of intel_update_fbc/intel_disable_fbc
>
> v3: Internal review comments incorporated
> Add NULL pointer check in intel_disable_drrs.
> Add drrs calls in i9xx_crtc_enable/disable and valleyview_crtc_enable.
>
> v4: Jani's review comments incorporated.
> Change in sequence in intel_update_drrs. Comment modified to remove details
> of update param. Modified DRRS idleness interval to a module parameter.
>
> v5: Chris's review comments incorporated.
> Initialize connector in idleness detection init. Modifications made to
> use only intel_connector in i915_drrs and derive intel_dp when required.
> Added a function drrs_fini to cleanup DRRS work.
>
> v6: Internal review comments. Removed check for primary enabled, which is
> a redundant check, in the case of clone mode. Added a flag to track
> dual-display configuration. Remove print statement for "cancel DRR work"
> and print "DRRS not supported" only once.
>
> v7: As per internal review comments, removing calls to update/disable drrs
> from sprite update path. For sprite, all drrs related updates would be
> taken care of with calls to crtc page flip itself. This will have to be
> revisited later if flip infrastructure changes for sprite.
>
> v8: Incorporated Jani's review comments. Added space after the periods in the
> module param description. Changes around drrs-fini to remove seamless DRRS
> check.
>
> v9: Added checks for PSR before updating DRRS. Added check for module
> param drrs_interval before updating DRRS (this is required if the interval
> is modified by the user during system use). DRRS disabled by default. Changes
> based on Jani's review comments
>
> v10: Disable/enable DRRS when PSR is enable/disabled.
>
> v11: Moved DRRS not supported log to patch2.
>
> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 7 ++
> drivers/gpu/drm/i915/i915_params.c | 8 ++
> drivers/gpu/drm/i915/intel_display.c | 16 ++++
> drivers/gpu/drm/i915/intel_dp.c | 27 ++++++-
> drivers/gpu/drm/i915/intel_drv.h | 5 +-
> drivers/gpu/drm/i915/intel_pm.c | 142 +++++++++++++++++++++++++++++++++++
> 6 files changed, 203 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 9da8d83..fb9f9f0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -635,6 +635,12 @@ struct i915_fbc {
>
> struct i915_drrs {
> struct intel_connector *connector;
> + bool is_clone;
> + struct intel_drrs_work {
> + struct delayed_work work;
> + struct drm_crtc *crtc;
> + int interval;
> + } *drrs_work;
> };
>
> struct i915_psr {
> @@ -1922,6 +1928,7 @@ struct i915_params {
> int enable_ips;
> int invert_brightness;
> int enable_cmd_parser;
> + int drrs_interval;
> /* leave bools at the end to not create holes */
> bool enable_hangcheck;
> bool fastboot;
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index d05a2af..144ab0b 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -48,6 +48,7 @@ struct i915_params i915 __read_mostly = {
> .disable_display = 0,
> .enable_cmd_parser = 1,
> .disable_vtd_wa = 0,
> + .drrs_interval = 0,
> };
>
> module_param_named(modeset, i915.modeset, int, 0400);
> @@ -156,3 +157,10 @@ MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)"
> module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
> MODULE_PARM_DESC(enable_cmd_parser,
> "Enable command parsing (1=enabled [default], 0=disabled)");
> +
> +module_param_named(drrs_interval, i915.drrs_interval, int, 0600);
> +MODULE_PARM_DESC(drrs_interval,
> + "DRRS idleness detection interval (default: 0 ms). "
> + "If this field is set to 0, then seamless DRRS feature "
> + "based on idleness detection is disabled. "
> + "The interval is to be set in milliseconds.");
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3697433..363ca22 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2523,6 +2523,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> intel_edp_psr_update(dev);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -3695,6 +3696,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> @@ -3738,6 +3740,7 @@ static void haswell_crtc_enable_planes(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
>
> drm_vblank_on(dev, pipe);
> @@ -3935,6 +3938,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
> }
>
> @@ -3982,6 +3986,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> mutex_unlock(&dev->struct_mutex);
> }
>
> @@ -4376,6 +4381,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
> intel_crtc_update_cursor(crtc, true);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->enable(encoder);
> @@ -4423,6 +4429,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
> intel_crtc_dpms_overlay(intel_crtc, true);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
>
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->enable(encoder);
> @@ -4490,6 +4497,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
> intel_update_watermarks(crtc);
>
> intel_update_fbc(dev);
> + intel_update_drrs(dev);
> }
>
> static void i9xx_crtc_off(struct drm_crtc *crtc)
> @@ -8510,6 +8518,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
> drm_gem_object_unreference(&work->pending_flip_obj->base);
> drm_gem_object_unreference(&work->old_fb_obj->base);
>
> + /* disable current DRRS work scheduled and restart
> + * to push work by another x seconds
> + */
> + intel_update_drrs(dev);
> intel_update_fbc(dev);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -8968,6 +8980,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
> goto cleanup_pending;
>
> intel_disable_fbc(dev);
> + intel_disable_drrs(dev);
> intel_mark_fb_busy(obj, NULL);
> mutex_unlock(&dev->struct_mutex);
>
> @@ -11341,6 +11354,7 @@ void intel_modeset_init(struct drm_device *dev)
>
> /* Just in case the BIOS is doing something questionable. */
> intel_disable_fbc(dev);
> + intel_disable_drrs(dev);
>
> mutex_lock(&dev->mode_config.mutex);
> intel_modeset_setup_hw_state(dev, false);
> @@ -11821,6 +11835,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
>
> intel_disable_fbc(dev);
>
> + intel_disable_drrs(dev);
> +
> intel_disable_gt_powersave(dev);
>
> ironlake_teardown_rc6(dev);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index b50b170..5fc4060 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1739,6 +1739,11 @@ static void intel_edp_psr_do_enable(struct intel_dp *intel_dp)
> intel_edp_is_psr_enabled(dev))
> return;
>
> + if (INTEL_INFO(dev)->gen < 8) {
> + DRM_DEBUG_KMS("Enabling PSR, disabling DRRS\n");
> + intel_disable_drrs(dev);
> + }
> +
> /* Setup PSR once */
> intel_edp_psr_setup(intel_dp);
>
> @@ -1773,6 +1778,9 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
> if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
> EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
> DRM_ERROR("Timed out waiting for PSR Idle State\n");
> +
> + if (INTEL_INFO(dev)->gen < 8)
> + intel_update_drrs(dev);
> }
>
> void intel_edp_psr_update(struct drm_device *dev)
> @@ -3371,16 +3379,33 @@ intel_dp_connector_destroy(struct drm_connector *connector)
> kfree(connector);
> }
>
> +static void
> +intel_dp_drrs_fini(struct drm_i915_private *dev_priv)
> +{
> + if (cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work)) {
> + kfree(dev_priv->drrs.drrs_work);
> + dev_priv->drrs.drrs_work = NULL;
> + dev_priv->drrs.connector = NULL;
> + }
> +}
> +
> void intel_dp_encoder_destroy(struct drm_encoder *encoder)
> {
> struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
> struct intel_dp *intel_dp = &intel_dig_port->dp;
> struct drm_device *dev = intel_dp_to_dev(intel_dp);
> + struct drm_i915_private *dev_priv = dev->dev_private;
>
> drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
> drm_encoder_cleanup(encoder);
> if (is_edp(intel_dp)) {
> cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +
> + if (dev_priv->drrs.connector && dev_priv->drrs.drrs_work &&
> + intel_dp == enc_to_intel_dp(
> + &dev_priv->drrs.connector->encoder->base))
> + intel_dp_drrs_fini(dev_priv);
> +
> mutex_lock(&dev->mode_config.mutex);
> edp_panel_vdd_off_sync(intel_dp);
> mutex_unlock(&dev->mode_config.mutex);
> @@ -3767,7 +3792,7 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> return NULL;
> }
>
> - dev_priv->drrs.connector = intel_connector;
> + intel_init_drrs_idleness_detection(dev, intel_connector);
>
> mutex_init(&intel_dp->drrs_state.mutex);
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 37d56e5..de1357b 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -932,7 +932,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
> void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
> void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
> void ilk_wm_get_hw_state(struct drm_device *dev);
> -
> +void intel_init_drrs_idleness_detection(struct drm_device *dev,
> + struct intel_connector *connector);
> +void intel_update_drrs(struct drm_device *dev);
> +void intel_disable_drrs(struct drm_device *dev);
>
> /* intel_sdvo.c */
> bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 04af065..0c43329 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -621,6 +621,148 @@ out_disable:
> i915_gem_stolen_cleanup_compression(dev);
> }
>
> +static void intel_drrs_work_fn(struct work_struct *__work)
> +{
> + struct intel_drrs_work *work =
> + container_of(to_delayed_work(__work),
> + struct intel_drrs_work, work);
> + struct drm_device *dev = work->crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + /* Double check if the dual-display mode is active. */
> + if (dev_priv->drrs.is_clone)
> + return;
> +
> + intel_dp_set_drrs_state(work->crtc->dev,
> + dev_priv->drrs.connector->panel.downclock_mode->vrefresh);
> +}
> +
> +static void intel_cancel_drrs_work(struct drm_i915_private *dev_priv)
> +{
> + if (dev_priv->drrs.drrs_work == NULL)
> + return;
> +
> + cancel_delayed_work_sync(&dev_priv->drrs.drrs_work->work);
> +}
> +
> +static void intel_enable_drrs(struct drm_crtc *crtc)
> +{
> + struct drm_device *dev = crtc->dev;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_dp *intel_dp = NULL;
> +
> + intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
> +
> + if (intel_dp == NULL)
> + return;
> +
> + intel_cancel_drrs_work(dev_priv);
> +
> + if (intel_dp->drrs_state.refresh_rate_type != DRRS_LOW_RR) {
> + dev_priv->drrs.drrs_work->crtc = crtc;
> + dev_priv->drrs.drrs_work->interval = i915.drrs_interval;
> +
> + /* Delay the actual enabling to let pageflipping cease and the
> + * display to settle before starting DRRS
> + */
> + schedule_delayed_work(&dev_priv->drrs.drrs_work->work,
> + msecs_to_jiffies(dev_priv->drrs.drrs_work->interval));
> + }
> +}
> +
> +void intel_disable_drrs(struct drm_device *dev)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + struct intel_dp *intel_dp = NULL;
> +
> + if (dev_priv->drrs.connector == NULL)
> + return;
> +
> + intel_dp = enc_to_intel_dp(&dev_priv->drrs.connector->encoder->base);
> +
> + if (intel_dp == NULL)
> + return;
> +
> + /* as part of disable DRRS, reset refresh rate to HIGH_RR */
> + if (intel_dp->drrs_state.refresh_rate_type == DRRS_LOW_RR) {
> + intel_cancel_drrs_work(dev_priv);
> + intel_dp_set_drrs_state(dev,
> + dev_priv->drrs.connector->panel.fixed_mode->vrefresh);
> + }
> +}
> +
> +/**
> + * intel_update_drrs - enable/disable DRRS as needed
> + * @dev: the drm_device
> +*/
> +void intel_update_drrs(struct drm_device *dev)
> +{
> + struct drm_crtc *crtc = NULL, *tmp_crtc;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (i915.drrs_interval == 0) {
> + intel_disable_drrs(dev);
> + return;
> + }
> +
> + /* if drrs.connector is NULL, then drrs_init did not get called.
> + * which means DRRS is not supported.
> + */
> + if (dev_priv->drrs.connector == NULL)
> + return;
> +
> + if (dev_priv->drrs.connector->panel.downclock_mode == NULL)
> + return;
> +
> + list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
> + if (intel_crtc_active(tmp_crtc)) {
> + if (crtc) {
> + DRM_DEBUG_KMS(
> + "more than one pipe active, disabling DRRS\n");
> + dev_priv->drrs.is_clone = true;
> + intel_disable_drrs(dev);
> + return;
> + }
> + crtc = tmp_crtc;
> + }
> + }
> +
> + if (crtc == NULL) {
> + DRM_DEBUG_KMS("DRRS: crtc not initialized\n");
> + return;
> + }
> +
> + dev_priv->drrs.is_clone = false;
> + intel_disable_drrs(dev);
> +
> + /* re-enable idleness detection */
> + intel_enable_drrs(crtc);
> +}
> +
> +void intel_init_drrs_idleness_detection(struct drm_device *dev,
> + struct intel_connector *connector)
> +{
> + struct intel_drrs_work *work;
> + struct drm_i915_private *dev_priv = dev->dev_private;
> +
> + if (i915.drrs_interval == 0)
> + DRM_INFO("DRRS disable by flag\n");
> +
> + work = kzalloc(sizeof(struct intel_drrs_work), GFP_KERNEL);
> + if (!work) {
> + DRM_ERROR("Failed to allocate DRRS work structure\n");
> + return;
> + }
> +
> + dev_priv->drrs.connector = connector;
> + dev_priv->drrs.is_clone = false;
> +
> + work->interval = i915.drrs_interval;
> + INIT_DELAYED_WORK(&work->work, intel_drrs_work_fn);
> +
> + dev_priv->drrs.drrs_work = work;
> +}
> +
> static void i915_pineview_get_mem_freq(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> --
> 1.9.1
>
--
Jani Nikula, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v11 2/6] drm/i915: Parse EDID probed modes for DRRS support
2014-04-10 8:42 ` Jani Nikula
@ 2014-04-10 8:55 ` Daniel Vetter
0 siblings, 0 replies; 40+ messages in thread
From: Daniel Vetter @ 2014-04-10 8:55 UTC (permalink / raw)
To: Jani Nikula; +Cc: intel-gfx
On Thu, Apr 10, 2014 at 11:42:04AM +0300, Jani Nikula wrote:
>
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>
>
> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> > From: Pradeep Bhat <pradeep.bhat@intel.com>
> >
> > This patch and finds out the lowest refresh rate supported for the resolution
> > same as the fixed_mode.
> > It also checks the VBT fields to see if panel supports seamless DRRS or not.
> > Based on above data it marks whether eDP panel supports seamless DRRS or not.
> > This information is needed for supporting seamless DRRS switch for certain
> > power saving usecases. This patch is tested by enabling the DRM logs and
> > user should see whether Seamless DRRS is supported or not.
> >
> > v2: Daniel's review comments
> > Modified downclock deduction based on intel_find_panel_downclock
> >
> > v3: Chris's review comments
> > Moved edp_downclock_avail and edp_downclock to intel_panel
> >
> > v4: Jani's review comments.
> > Changed name of the enum edp_panel_type to drrs_support type.
> > Change is_drrs_supported to drrs_support of type enum drrs_support_type.
> >
> > v5: Incorporated Jani's review comments
> > Modify intel_dp_drrs_initialize to return downclock mode. Support for Gen7
> > and above.
> >
> > v6: Incorporated Chris's review comments.
> > Changed initialize to init in intel_drrs_initialize
> >
> > v7: Incorporated Jani's review comments.
> > Removed edp_downclock and edp_downclock_avail. Return NULL explicitly.
> > Make drrs_state and unnamed struct. Move Gen based check inside drrs_init.
> >
> > v8: Made changes to track PSR enable/disable throughout system use (instead
> > of just in the init sequence) for disabling/enabling DRRS. Jani's review
> > comments.
> >
> > v9: PSR tracking will be done as part of idleness detection patch. Removed
> > PSR state tracker in i915_drrs. Jani's review comments.
> >
> > v10: Added log for DRRS not supported in drrs_init
> >
> > v11: Modification in drrs_init. suggested by Jani
> >
> > Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> > Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
Queued for -next, thanks for the patch.
-Daniel
> > ---
> > drivers/gpu/drm/i915/intel_dp.c | 44 +++++++++++++++++++++++++++++++++++++++-
> > drivers/gpu/drm/i915/intel_drv.h | 16 +++++++++++++++
> > 2 files changed, 59 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index e48d47c..517a8cc 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -3632,6 +3632,42 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> > I915_READ(pp_div_reg));
> > }
> >
> > +static struct drm_display_mode *
> > +intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> > + struct intel_connector *intel_connector,
> > + struct drm_display_mode *fixed_mode)
> > +{
> > + struct drm_connector *connector = &intel_connector->base;
> > + struct intel_dp *intel_dp = &intel_dig_port->dp;
> > + struct drm_device *dev = intel_dig_port->base.base.dev;
> > + struct drm_i915_private *dev_priv = dev->dev_private;
> > + struct drm_display_mode *downclock_mode = NULL;
> > +
> > + 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_INFO("VBT doesn't support DRRS\n");
> > + return NULL;
> > + }
> > +
> > + downclock_mode = intel_find_panel_downclock
> > + (dev, fixed_mode, connector);
> > +
> > + if (!downclock_mode) {
> > + DRM_INFO("DRRS not supported\n");
> > + return NULL;
> > + }
> > +
> > + intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> > +
> > + intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> > + DRM_INFO("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,
> > struct edp_power_seq *power_seq)
> > @@ -3641,10 +3677,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> > struct drm_device *dev = intel_dig_port->base.base.dev;
> > struct drm_i915_private *dev_priv = dev->dev_private;
> > struct drm_display_mode *fixed_mode = NULL;
> > + struct drm_display_mode *downclock_mode = NULL;
> > bool has_dpcd;
> > struct drm_display_mode *scan;
> > struct edid *edid;
> >
> > + intel_dp->drrs_state.type = DRRS_NOT_SUPPORTED;
> > +
> > if (!is_edp(intel_dp))
> > return true;
> >
> > @@ -3687,6 +3726,9 @@ 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_dig_port,
> > + intel_connector, fixed_mode);
> > break;
> > }
> > }
> > @@ -3700,7 +3742,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> > }
> > mutex_unlock(&dev->mode_config.mutex);
> >
> > - intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> > + intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
> > intel_panel_setup_backlight(connector);
> >
> > return true;
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 42762b7..286d4fb 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -482,6 +482,17 @@ struct intel_hdmi {
> >
> > #define DP_MAX_DOWNSTREAM_PORTS 0x10
> >
> > +/**
> > + * 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 edp_drrs_refresh_rate_type {
> > + DRRS_HIGH_RR,
> > + DRRS_LOW_RR,
> > + DRRS_MAX_RR, /* RR count */
> > +};
> > +
> > struct intel_dp {
> > uint32_t output_reg;
> > uint32_t aux_ch_ctl_reg;
> > @@ -520,6 +531,11 @@ struct intel_dp {
> > bool has_aux_irq,
> > int send_bytes,
> > uint32_t aux_clock_divider);
> > + struct {
> > + enum drrs_support_type type;
> > + enum edp_drrs_refresh_rate_type refresh_rate_type;
> > + } drrs_state;
> > +
> > };
> >
> > struct intel_digital_port {
> > --
> > 1.9.1
> >
>
> --
> Jani Nikula, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-10 8:43 ` Jani Nikula
@ 2014-04-10 8:56 ` Daniel Vetter
2014-04-10 8:58 ` Daniel Vetter
1 sibling, 0 replies; 40+ messages in thread
From: Daniel Vetter @ 2014-04-10 8:56 UTC (permalink / raw)
To: Jani Nikula; +Cc: intel-gfx
On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote:
>
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>
>
> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> > From: Pradeep Bhat <pradeep.bhat@intel.com>
> >
> > This patch computes and stored 2nd M/N/TU for switching to different
> > refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
> > between alternate refresh rates programmed in 2nd M/N/TU registers.
> >
> > v2: Daniel's review comments
> > Computing M2/N2 in compute_config and storing it in crtc_config
> >
> > v3: Modified reference to edp_downclock and edp_downclock_avail based on the
> > changes made to move them from dev_private to intel_panel.
> >
> > v4: Modified references to is_drrs_supported based on the changes made to
> > rename it to drrs_support.
> >
> > v5: Jani's review comments
> > Removed superfluous return statements. Changed support for Gen 7 and above.
> > Corrected indentation. Re-structured the code which finds crtc and connector
> > from encoder. Changed some logs to be less verbose.
> >
> > v6: Modifying i915_drrs to include only intel connector as intel_dp can be
> > derived from intel connector when required.
> >
> > v7: As per internal review comments, acquiring mutex just before accessing
> > drrs RR. As per Chris's review comments, added documentation about the use
> > of locking in the function.
> >
> > v8: Incorporated Jani's review comments.
> > Removed reference to edp_downclock.
> >
> > v9: Jani's review comments. Modified comment in set_drrs. Changed index to
> > type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
> > registers fo DRRS.
> >
> > Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> > Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
Queued for -next, thanks for the patch.
-Daniel
> > ---
> > drivers/gpu/drm/i915/i915_drv.h | 5 ++
> > drivers/gpu/drm/i915/i915_reg.h | 1 +
> > drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++
> > drivers/gpu/drm/i915/intel_drv.h | 6 ++-
> > 4 files changed, 121 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 55addaa..9da8d83 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -633,6 +633,10 @@ struct i915_fbc {
> > } no_fbc_reason;
> > };
> >
> > +struct i915_drrs {
> > + struct intel_connector *connector;
> > +};
> > +
> > struct i915_psr {
> > bool sink_support;
> > bool source_ok;
> > @@ -1320,6 +1324,7 @@ struct drm_i915_private {
> > struct timer_list hotplug_reenable_timer;
> >
> > struct i915_fbc fbc;
> > + struct i915_drrs drrs;
> > struct intel_opregion opregion;
> > struct intel_vbt_data vbt;
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 2315366..d6dddc2 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -3346,6 +3346,7 @@ enum punit_power_well {
> > #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
> > #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
> > #define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
> > +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
> > #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
> > #define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
> > #define PIPECONF_BPC_MASK (0x7 << 5)
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 517a8cc..b50b170 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
> > }
> > }
> >
> > +static void
> > +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
> > +{
> > + struct drm_device *dev = crtc->base.dev;
> > + struct drm_i915_private *dev_priv = dev->dev_private;
> > + enum transcoder transcoder = crtc->config.cpu_transcoder;
> > +
> > + I915_WRITE(PIPE_DATA_M2(transcoder),
> > + TU_SIZE(m_n->tu) | m_n->gmch_m);
> > + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
> > + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
> > + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
> > +}
> > +
> > bool
> > intel_dp_compute_config(struct intel_encoder *encoder,
> > struct intel_crtc_config *pipe_config)
> > @@ -841,6 +855,14 @@ found:
> > pipe_config->port_clock,
> > &pipe_config->dp_m_n);
> >
> > + if (intel_connector->panel.downclock_mode != NULL &&
> > + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
> > + intel_link_compute_m_n(bpp, lane_count,
> > + intel_connector->panel.downclock_mode->clock,
> > + pipe_config->port_clock,
> > + &pipe_config->dp_m2_n2);
> > + }
> > +
> > intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
> >
> > return true;
> > @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> > I915_READ(pp_div_reg));
> > }
> >
> > +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_dp *intel_dp = NULL;
> > + struct intel_crtc_config *config = NULL;
> > + struct intel_crtc *intel_crtc = NULL;
> > + struct intel_connector *intel_connector = dev_priv->drrs.connector;
> > + u32 reg, val;
> > + enum edp_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_connector == NULL) {
> > + DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
> > + return;
> > + }
> > +
> > + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
> > + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
> > + return;
> > + }
> > +
> > + encoder = intel_attached_encoder(&intel_connector->base);
> > + intel_dp = enc_to_intel_dp(&encoder->base);
> > + intel_crtc = encoder->new_crtc;
> > +
> > + if (!intel_crtc) {
> > + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
> > + return;
> > + }
> > +
> > + config = &intel_crtc->config;
> > +
> > + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
> > + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
> > + return;
> > + }
> > +
> > + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
> > + index = DRRS_LOW_RR;
> > +
> > + if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
> > + reg = PIPECONF(intel_crtc->config.cpu_transcoder);
> > + val = I915_READ(reg);
> > + if (index > DRRS_HIGH_RR) {
> > + val |= PIPECONF_EDP_RR_MODE_SWITCH;
> > + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
> > + } else {
> > + val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
> > + }
> > + I915_WRITE(reg, val);
> > + }
> > +
> > + /*
> > + * mutex taken to ensure that there is no race between differnt
> > + * drrs calls trying to update refresh rate. This scenario may occur
> > + * in future when idleness detection based DRRS in kernel and
> > + * possible calls from user space to set differnt RR are made.
> > + */
> > +
> > + mutex_lock(&intel_dp->drrs_state.mutex);
> > +
> > + intel_dp->drrs_state.refresh_rate_type = index;
> > +
> > + mutex_unlock(&intel_dp->drrs_state.mutex);
> > +
> > + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
> > +}
> > +
> > static struct drm_display_mode *
> > intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> > struct intel_connector *intel_connector,
> > @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> > return NULL;
> > }
> >
> > + dev_priv->drrs.connector = intel_connector;
> > +
> > + mutex_init(&intel_dp->drrs_state.mutex);
> > +
> > intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> >
> > intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 286d4fb..37d56e5 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -305,6 +305,9 @@ struct intel_crtc_config {
> > int pipe_bpp;
> > struct intel_link_m_n dp_m_n;
> >
> > + /* m2_n2 for eDP downclock */
> > + struct intel_link_m_n dp_m2_n2;
> > +
> > /*
> > * Frequence the dpll for the port should run at. Differs from the
> > * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
> > @@ -534,6 +537,7 @@ struct intel_dp {
> > struct {
> > enum drrs_support_type type;
> > enum edp_drrs_refresh_rate_type refresh_rate_type;
> > + struct mutex mutex;
> > } drrs_state;
> >
> > };
> > @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
> > void intel_edp_psr_enable(struct intel_dp *intel_dp);
> > void intel_edp_psr_disable(struct intel_dp *intel_dp);
> > void intel_edp_psr_update(struct drm_device *dev);
> > -
> > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
> >
> > /* intel_dsi.c */
> > bool intel_dsi_init(struct drm_device *dev);
> > --
> > 1.9.1
> >
>
> --
> Jani Nikula, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-10 8:43 ` Jani Nikula
2014-04-10 8:56 ` Daniel Vetter
@ 2014-04-10 8:58 ` Daniel Vetter
2014-04-11 9:18 ` Vandana Kannan
1 sibling, 1 reply; 40+ messages in thread
From: Daniel Vetter @ 2014-04-10 8:58 UTC (permalink / raw)
To: Jani Nikula; +Cc: intel-gfx
On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote:
>
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>
>
> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> > From: Pradeep Bhat <pradeep.bhat@intel.com>
> >
> > This patch computes and stored 2nd M/N/TU for switching to different
> > refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
> > between alternate refresh rates programmed in 2nd M/N/TU registers.
> >
> > v2: Daniel's review comments
> > Computing M2/N2 in compute_config and storing it in crtc_config
> >
> > v3: Modified reference to edp_downclock and edp_downclock_avail based on the
> > changes made to move them from dev_private to intel_panel.
> >
> > v4: Modified references to is_drrs_supported based on the changes made to
> > rename it to drrs_support.
> >
> > v5: Jani's review comments
> > Removed superfluous return statements. Changed support for Gen 7 and above.
> > Corrected indentation. Re-structured the code which finds crtc and connector
> > from encoder. Changed some logs to be less verbose.
> >
> > v6: Modifying i915_drrs to include only intel connector as intel_dp can be
> > derived from intel connector when required.
> >
> > v7: As per internal review comments, acquiring mutex just before accessing
> > drrs RR. As per Chris's review comments, added documentation about the use
> > of locking in the function.
> >
> > v8: Incorporated Jani's review comments.
> > Removed reference to edp_downclock.
> >
> > v9: Jani's review comments. Modified comment in set_drrs. Changed index to
> > type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
> > registers fo DRRS.
> >
> > Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> > Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> > Cc: Jani Nikula <jani.nikula@linux.intel.com>
Queued for -next, thanks for the patch. One thing that's missing though is
the state readout and cross-check support for this new bit of crtc->config
data. We need to add that before putting this to real use.
-Daniel
> > ---
> > drivers/gpu/drm/i915/i915_drv.h | 5 ++
> > drivers/gpu/drm/i915/i915_reg.h | 1 +
> > drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++
> > drivers/gpu/drm/i915/intel_drv.h | 6 ++-
> > 4 files changed, 121 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 55addaa..9da8d83 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -633,6 +633,10 @@ struct i915_fbc {
> > } no_fbc_reason;
> > };
> >
> > +struct i915_drrs {
> > + struct intel_connector *connector;
> > +};
> > +
> > struct i915_psr {
> > bool sink_support;
> > bool source_ok;
> > @@ -1320,6 +1324,7 @@ struct drm_i915_private {
> > struct timer_list hotplug_reenable_timer;
> >
> > struct i915_fbc fbc;
> > + struct i915_drrs drrs;
> > struct intel_opregion opregion;
> > struct intel_vbt_data vbt;
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 2315366..d6dddc2 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -3346,6 +3346,7 @@ enum punit_power_well {
> > #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
> > #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
> > #define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
> > +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
> > #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
> > #define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
> > #define PIPECONF_BPC_MASK (0x7 << 5)
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 517a8cc..b50b170 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
> > }
> > }
> >
> > +static void
> > +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
> > +{
> > + struct drm_device *dev = crtc->base.dev;
> > + struct drm_i915_private *dev_priv = dev->dev_private;
> > + enum transcoder transcoder = crtc->config.cpu_transcoder;
> > +
> > + I915_WRITE(PIPE_DATA_M2(transcoder),
> > + TU_SIZE(m_n->tu) | m_n->gmch_m);
> > + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
> > + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
> > + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
> > +}
> > +
> > bool
> > intel_dp_compute_config(struct intel_encoder *encoder,
> > struct intel_crtc_config *pipe_config)
> > @@ -841,6 +855,14 @@ found:
> > pipe_config->port_clock,
> > &pipe_config->dp_m_n);
> >
> > + if (intel_connector->panel.downclock_mode != NULL &&
> > + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
> > + intel_link_compute_m_n(bpp, lane_count,
> > + intel_connector->panel.downclock_mode->clock,
> > + pipe_config->port_clock,
> > + &pipe_config->dp_m2_n2);
> > + }
> > +
> > intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
> >
> > return true;
> > @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
> > I915_READ(pp_div_reg));
> > }
> >
> > +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_dp *intel_dp = NULL;
> > + struct intel_crtc_config *config = NULL;
> > + struct intel_crtc *intel_crtc = NULL;
> > + struct intel_connector *intel_connector = dev_priv->drrs.connector;
> > + u32 reg, val;
> > + enum edp_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_connector == NULL) {
> > + DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
> > + return;
> > + }
> > +
> > + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
> > + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
> > + return;
> > + }
> > +
> > + encoder = intel_attached_encoder(&intel_connector->base);
> > + intel_dp = enc_to_intel_dp(&encoder->base);
> > + intel_crtc = encoder->new_crtc;
> > +
> > + if (!intel_crtc) {
> > + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
> > + return;
> > + }
> > +
> > + config = &intel_crtc->config;
> > +
> > + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
> > + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
> > + return;
> > + }
> > +
> > + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
> > + index = DRRS_LOW_RR;
> > +
> > + if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
> > + reg = PIPECONF(intel_crtc->config.cpu_transcoder);
> > + val = I915_READ(reg);
> > + if (index > DRRS_HIGH_RR) {
> > + val |= PIPECONF_EDP_RR_MODE_SWITCH;
> > + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
> > + } else {
> > + val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
> > + }
> > + I915_WRITE(reg, val);
> > + }
> > +
> > + /*
> > + * mutex taken to ensure that there is no race between differnt
> > + * drrs calls trying to update refresh rate. This scenario may occur
> > + * in future when idleness detection based DRRS in kernel and
> > + * possible calls from user space to set differnt RR are made.
> > + */
> > +
> > + mutex_lock(&intel_dp->drrs_state.mutex);
> > +
> > + intel_dp->drrs_state.refresh_rate_type = index;
> > +
> > + mutex_unlock(&intel_dp->drrs_state.mutex);
> > +
> > + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
> > +}
> > +
> > static struct drm_display_mode *
> > intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> > struct intel_connector *intel_connector,
> > @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
> > return NULL;
> > }
> >
> > + dev_priv->drrs.connector = intel_connector;
> > +
> > + mutex_init(&intel_dp->drrs_state.mutex);
> > +
> > intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
> >
> > intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 286d4fb..37d56e5 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -305,6 +305,9 @@ struct intel_crtc_config {
> > int pipe_bpp;
> > struct intel_link_m_n dp_m_n;
> >
> > + /* m2_n2 for eDP downclock */
> > + struct intel_link_m_n dp_m2_n2;
> > +
> > /*
> > * Frequence the dpll for the port should run at. Differs from the
> > * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
> > @@ -534,6 +537,7 @@ struct intel_dp {
> > struct {
> > enum drrs_support_type type;
> > enum edp_drrs_refresh_rate_type refresh_rate_type;
> > + struct mutex mutex;
> > } drrs_state;
> >
> > };
> > @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
> > void intel_edp_psr_enable(struct intel_dp *intel_dp);
> > void intel_edp_psr_disable(struct intel_dp *intel_dp);
> > void intel_edp_psr_update(struct drm_device *dev);
> > -
> > +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
> >
> > /* intel_dsi.c */
> > bool intel_dsi_init(struct drm_device *dev);
> > --
> > 1.9.1
> >
>
> --
> Jani Nikula, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-10 8:58 ` Daniel Vetter
@ 2014-04-11 9:18 ` Vandana Kannan
2014-04-11 9:26 ` Daniel Vetter
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-11 9:18 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx@lists.freedesktop.org
On Apr-10-2014 2:28 PM, Daniel Vetter wrote:
> On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote:
>>
>> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>>
>>
>> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
>>> From: Pradeep Bhat <pradeep.bhat@intel.com>
>>>
>>> This patch computes and stored 2nd M/N/TU for switching to different
>>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
>>> between alternate refresh rates programmed in 2nd M/N/TU registers.
>>>
>>> v2: Daniel's review comments
>>> Computing M2/N2 in compute_config and storing it in crtc_config
>>>
>>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the
>>> changes made to move them from dev_private to intel_panel.
>>>
>>> v4: Modified references to is_drrs_supported based on the changes made to
>>> rename it to drrs_support.
>>>
>>> v5: Jani's review comments
>>> Removed superfluous return statements. Changed support for Gen 7 and above.
>>> Corrected indentation. Re-structured the code which finds crtc and connector
>>> from encoder. Changed some logs to be less verbose.
>>>
>>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be
>>> derived from intel connector when required.
>>>
>>> v7: As per internal review comments, acquiring mutex just before accessing
>>> drrs RR. As per Chris's review comments, added documentation about the use
>>> of locking in the function.
>>>
>>> v8: Incorporated Jani's review comments.
>>> Removed reference to edp_downclock.
>>>
>>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to
>>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
>>> registers fo DRRS.
>>>
>>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
>>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
>>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>
> Queued for -next, thanks for the patch. One thing that's missing though is
> the state readout and cross-check support for this new bit of crtc->config
> data. We need to add that before putting this to real use.
> -Daniel
>
Hi Daniel,
Could you please elaborate on your input above - on the missing code and
cross-checking for support part?
-Vandana
>>> ---
>>> drivers/gpu/drm/i915/i915_drv.h | 5 ++
>>> drivers/gpu/drm/i915/i915_reg.h | 1 +
>>> drivers/gpu/drm/i915/intel_dp.c | 110 +++++++++++++++++++++++++++++++++++++++
>>> drivers/gpu/drm/i915/intel_drv.h | 6 ++-
>>> 4 files changed, 121 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>>> index 55addaa..9da8d83 100644
>>> --- a/drivers/gpu/drm/i915/i915_drv.h
>>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>>> @@ -633,6 +633,10 @@ struct i915_fbc {
>>> } no_fbc_reason;
>>> };
>>>
>>> +struct i915_drrs {
>>> + struct intel_connector *connector;
>>> +};
>>> +
>>> struct i915_psr {
>>> bool sink_support;
>>> bool source_ok;
>>> @@ -1320,6 +1324,7 @@ struct drm_i915_private {
>>> struct timer_list hotplug_reenable_timer;
>>>
>>> struct i915_fbc fbc;
>>> + struct i915_drrs drrs;
>>> struct intel_opregion opregion;
>>> struct intel_vbt_data vbt;
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
>>> index 2315366..d6dddc2 100644
>>> --- a/drivers/gpu/drm/i915/i915_reg.h
>>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>>> @@ -3346,6 +3346,7 @@ enum punit_power_well {
>>> #define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
>>> #define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
>>> #define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
>>> +#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
>>> #define PIPECONF_CXSR_DOWNCLOCK (1<<16)
>>> #define PIPECONF_COLOR_RANGE_SELECT (1 << 13)
>>> #define PIPECONF_BPC_MASK (0x7 << 5)
>>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>>> index 517a8cc..b50b170 100644
>>> --- a/drivers/gpu/drm/i915/intel_dp.c
>>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>>> @@ -737,6 +737,20 @@ intel_dp_set_clock(struct intel_encoder *encoder,
>>> }
>>> }
>>>
>>> +static void
>>> +intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n)
>>> +{
>>> + struct drm_device *dev = crtc->base.dev;
>>> + struct drm_i915_private *dev_priv = dev->dev_private;
>>> + enum transcoder transcoder = crtc->config.cpu_transcoder;
>>> +
>>> + I915_WRITE(PIPE_DATA_M2(transcoder),
>>> + TU_SIZE(m_n->tu) | m_n->gmch_m);
>>> + I915_WRITE(PIPE_DATA_N2(transcoder), m_n->gmch_n);
>>> + I915_WRITE(PIPE_LINK_M2(transcoder), m_n->link_m);
>>> + I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n);
>>> +}
>>> +
>>> bool
>>> intel_dp_compute_config(struct intel_encoder *encoder,
>>> struct intel_crtc_config *pipe_config)
>>> @@ -841,6 +855,14 @@ found:
>>> pipe_config->port_clock,
>>> &pipe_config->dp_m_n);
>>>
>>> + if (intel_connector->panel.downclock_mode != NULL &&
>>> + intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) {
>>> + intel_link_compute_m_n(bpp, lane_count,
>>> + intel_connector->panel.downclock_mode->clock,
>>> + pipe_config->port_clock,
>>> + &pipe_config->dp_m2_n2);
>>> + }
>>> +
>>> intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
>>>
>>> return true;
>>> @@ -3632,6 +3654,90 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>>> I915_READ(pp_div_reg));
>>> }
>>>
>>> +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_dp *intel_dp = NULL;
>>> + struct intel_crtc_config *config = NULL;
>>> + struct intel_crtc *intel_crtc = NULL;
>>> + struct intel_connector *intel_connector = dev_priv->drrs.connector;
>>> + u32 reg, val;
>>> + enum edp_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_connector == NULL) {
>>> + DRM_DEBUG_KMS("DRRS supported for eDP only.\n");
>>> + return;
>>> + }
>>> +
>>> + if (INTEL_INFO(dev)->gen < 8 && intel_edp_is_psr_enabled(dev)) {
>>> + DRM_DEBUG_KMS("DRRS is disabled as PSR is enabled\n");
>>> + return;
>>> + }
>>> +
>>> + encoder = intel_attached_encoder(&intel_connector->base);
>>> + intel_dp = enc_to_intel_dp(&encoder->base);
>>> + intel_crtc = encoder->new_crtc;
>>> +
>>> + if (!intel_crtc) {
>>> + DRM_DEBUG_KMS("DRRS: intel_crtc not initialized\n");
>>> + return;
>>> + }
>>> +
>>> + config = &intel_crtc->config;
>>> +
>>> + if (intel_dp->drrs_state.type < SEAMLESS_DRRS_SUPPORT) {
>>> + DRM_DEBUG_KMS("Only Seamless DRRS supported.\n");
>>> + return;
>>> + }
>>> +
>>> + if (intel_connector->panel.downclock_mode->vrefresh == refresh_rate)
>>> + index = DRRS_LOW_RR;
>>> +
>>> + if (index == intel_dp->drrs_state.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 > 6 && INTEL_INFO(dev)->gen < 8) {
>>> + reg = PIPECONF(intel_crtc->config.cpu_transcoder);
>>> + val = I915_READ(reg);
>>> + if (index > DRRS_HIGH_RR) {
>>> + val |= PIPECONF_EDP_RR_MODE_SWITCH;
>>> + intel_dp_set_m2_n2(intel_crtc, &config->dp_m2_n2);
>>> + } else {
>>> + val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
>>> + }
>>> + I915_WRITE(reg, val);
>>> + }
>>> +
>>> + /*
>>> + * mutex taken to ensure that there is no race between differnt
>>> + * drrs calls trying to update refresh rate. This scenario may occur
>>> + * in future when idleness detection based DRRS in kernel and
>>> + * possible calls from user space to set differnt RR are made.
>>> + */
>>> +
>>> + mutex_lock(&intel_dp->drrs_state.mutex);
>>> +
>>> + intel_dp->drrs_state.refresh_rate_type = index;
>>> +
>>> + mutex_unlock(&intel_dp->drrs_state.mutex);
>>> +
>>> + DRM_DEBUG_KMS("eDP Refresh Rate set to : %dHz\n", refresh_rate);
>>> +}
>>> +
>>> static struct drm_display_mode *
>>> intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>>> struct intel_connector *intel_connector,
>>> @@ -3661,6 +3767,10 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port,
>>> return NULL;
>>> }
>>>
>>> + dev_priv->drrs.connector = intel_connector;
>>> +
>>> + mutex_init(&intel_dp->drrs_state.mutex);
>>> +
>>> intel_dp->drrs_state.type = dev_priv->vbt.drrs_type;
>>>
>>> intel_dp->drrs_state.refresh_rate_type = DRRS_HIGH_RR;
>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>> index 286d4fb..37d56e5 100644
>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>> @@ -305,6 +305,9 @@ struct intel_crtc_config {
>>> int pipe_bpp;
>>> struct intel_link_m_n dp_m_n;
>>>
>>> + /* m2_n2 for eDP downclock */
>>> + struct intel_link_m_n dp_m2_n2;
>>> +
>>> /*
>>> * Frequence the dpll for the port should run at. Differs from the
>>> * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
>>> @@ -534,6 +537,7 @@ struct intel_dp {
>>> struct {
>>> enum drrs_support_type type;
>>> enum edp_drrs_refresh_rate_type refresh_rate_type;
>>> + struct mutex mutex;
>>> } drrs_state;
>>>
>>> };
>>> @@ -789,7 +793,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp);
>>> void intel_edp_psr_enable(struct intel_dp *intel_dp);
>>> void intel_edp_psr_disable(struct intel_dp *intel_dp);
>>> void intel_edp_psr_update(struct drm_device *dev);
>>> -
>>> +void intel_dp_set_drrs_state(struct drm_device *dev, int refresh_rate);
>>>
>>> /* intel_dsi.c */
>>> bool intel_dsi_init(struct drm_device *dev);
>>> --
>>> 1.9.1
>>>
>>
>> --
>> Jani Nikula, Intel Open Source Technology Center
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-11 9:18 ` Vandana Kannan
@ 2014-04-11 9:26 ` Daniel Vetter
2014-04-11 11:21 ` Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Daniel Vetter @ 2014-04-11 9:26 UTC (permalink / raw)
To: Vandana Kannan; +Cc: intel-gfx@lists.freedesktop.org
On Fri, Apr 11, 2014 at 02:48:53PM +0530, Vandana Kannan wrote:
> On Apr-10-2014 2:28 PM, Daniel Vetter wrote:
> > On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote:
> >>
> >> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> >>
> >>
> >> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
> >>> From: Pradeep Bhat <pradeep.bhat@intel.com>
> >>>
> >>> This patch computes and stored 2nd M/N/TU for switching to different
> >>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
> >>> between alternate refresh rates programmed in 2nd M/N/TU registers.
> >>>
> >>> v2: Daniel's review comments
> >>> Computing M2/N2 in compute_config and storing it in crtc_config
> >>>
> >>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the
> >>> changes made to move them from dev_private to intel_panel.
> >>>
> >>> v4: Modified references to is_drrs_supported based on the changes made to
> >>> rename it to drrs_support.
> >>>
> >>> v5: Jani's review comments
> >>> Removed superfluous return statements. Changed support for Gen 7 and above.
> >>> Corrected indentation. Re-structured the code which finds crtc and connector
> >>> from encoder. Changed some logs to be less verbose.
> >>>
> >>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be
> >>> derived from intel connector when required.
> >>>
> >>> v7: As per internal review comments, acquiring mutex just before accessing
> >>> drrs RR. As per Chris's review comments, added documentation about the use
> >>> of locking in the function.
> >>>
> >>> v8: Incorporated Jani's review comments.
> >>> Removed reference to edp_downclock.
> >>>
> >>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to
> >>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
> >>> registers fo DRRS.
> >>>
> >>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
> >>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
> >>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> >
> > Queued for -next, thanks for the patch. One thing that's missing though is
> > the state readout and cross-check support for this new bit of crtc->config
> > data. We need to add that before putting this to real use.
> > -Daniel
> >
> Hi Daniel,
>
> Could you please elaborate on your input above - on the missing code and
> cross-checking for support part?
If you add new state to crtc->config then you need to add the relevan
readout code for that state (see the code in check_crtc_state) and ofc
also add it to intel_pipe_config_compare.
This is a debug feature of our driver to make sure we never lose track of
things and thus far has been extremely helpful in catching issues early.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-11 9:26 ` Daniel Vetter
@ 2014-04-11 11:21 ` Vandana Kannan
2014-04-21 4:28 ` Vandana Kannan
0 siblings, 1 reply; 40+ messages in thread
From: Vandana Kannan @ 2014-04-11 11:21 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx@lists.freedesktop.org
On Apr-11-2014 2:56 PM, Daniel Vetter wrote:
> On Fri, Apr 11, 2014 at 02:48:53PM +0530, Vandana Kannan wrote:
>> On Apr-10-2014 2:28 PM, Daniel Vetter wrote:
>>> On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote:
>>>>
>>>> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>>>>
>>>>
>>>> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
>>>>> From: Pradeep Bhat <pradeep.bhat@intel.com>
>>>>>
>>>>> This patch computes and stored 2nd M/N/TU for switching to different
>>>>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
>>>>> between alternate refresh rates programmed in 2nd M/N/TU registers.
>>>>>
>>>>> v2: Daniel's review comments
>>>>> Computing M2/N2 in compute_config and storing it in crtc_config
>>>>>
>>>>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the
>>>>> changes made to move them from dev_private to intel_panel.
>>>>>
>>>>> v4: Modified references to is_drrs_supported based on the changes made to
>>>>> rename it to drrs_support.
>>>>>
>>>>> v5: Jani's review comments
>>>>> Removed superfluous return statements. Changed support for Gen 7 and above.
>>>>> Corrected indentation. Re-structured the code which finds crtc and connector
>>>>> from encoder. Changed some logs to be less verbose.
>>>>>
>>>>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be
>>>>> derived from intel connector when required.
>>>>>
>>>>> v7: As per internal review comments, acquiring mutex just before accessing
>>>>> drrs RR. As per Chris's review comments, added documentation about the use
>>>>> of locking in the function.
>>>>>
>>>>> v8: Incorporated Jani's review comments.
>>>>> Removed reference to edp_downclock.
>>>>>
>>>>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to
>>>>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
>>>>> registers fo DRRS.
>>>>>
>>>>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
>>>>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
>>>>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>>>
>>> Queued for -next, thanks for the patch. One thing that's missing though is
>>> the state readout and cross-check support for this new bit of crtc->config
>>> data. We need to add that before putting this to real use.
>>> -Daniel
>>>
>> Hi Daniel,
>>
>> Could you please elaborate on your input above - on the missing code and
>> cross-checking for support part?
>
> If you add new state to crtc->config then you need to add the relevan
> readout code for that state (see the code in check_crtc_state) and ofc
> also add it to intel_pipe_config_compare.
>
> This is a debug feature of our driver to make sure we never lose track of
> things and thus far has been extremely helpful in catching issues early.
> -Daniel
>
I have submitted a patch adding this piece of code. Please have a look..
http://lists.freedesktop.org/archives/intel-gfx/2014-April/043569.html
- Vandana
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v9 3/6] drm/i915: Add support for DRRS to switch RR
2014-04-11 11:21 ` Vandana Kannan
@ 2014-04-21 4:28 ` Vandana Kannan
0 siblings, 0 replies; 40+ messages in thread
From: Vandana Kannan @ 2014-04-21 4:28 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx@lists.freedesktop.org
On Apr-11-2014 4:51 PM, Vandana Kannan wrote:
> On Apr-11-2014 2:56 PM, Daniel Vetter wrote:
>> On Fri, Apr 11, 2014 at 02:48:53PM +0530, Vandana Kannan wrote:
>>> On Apr-10-2014 2:28 PM, Daniel Vetter wrote:
>>>> On Thu, Apr 10, 2014 at 11:43:15AM +0300, Jani Nikula wrote:
>>>>>
>>>>> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>>>>>
>>>>>
>>>>> On Sat, 05 Apr 2014, Vandana Kannan <vandana.kannan@intel.com> wrote:
>>>>>> From: Pradeep Bhat <pradeep.bhat@intel.com>
>>>>>>
>>>>>> This patch computes and stored 2nd M/N/TU for switching to different
>>>>>> refresh rate dynamically. PIPECONF_EDP_RR_MODE_SWITCH bit helps toggle
>>>>>> between alternate refresh rates programmed in 2nd M/N/TU registers.
>>>>>>
>>>>>> v2: Daniel's review comments
>>>>>> Computing M2/N2 in compute_config and storing it in crtc_config
>>>>>>
>>>>>> v3: Modified reference to edp_downclock and edp_downclock_avail based on the
>>>>>> changes made to move them from dev_private to intel_panel.
>>>>>>
>>>>>> v4: Modified references to is_drrs_supported based on the changes made to
>>>>>> rename it to drrs_support.
>>>>>>
>>>>>> v5: Jani's review comments
>>>>>> Removed superfluous return statements. Changed support for Gen 7 and above.
>>>>>> Corrected indentation. Re-structured the code which finds crtc and connector
>>>>>> from encoder. Changed some logs to be less verbose.
>>>>>>
>>>>>> v6: Modifying i915_drrs to include only intel connector as intel_dp can be
>>>>>> derived from intel connector when required.
>>>>>>
>>>>>> v7: As per internal review comments, acquiring mutex just before accessing
>>>>>> drrs RR. As per Chris's review comments, added documentation about the use
>>>>>> of locking in the function.
>>>>>>
>>>>>> v8: Incorporated Jani's review comments.
>>>>>> Removed reference to edp_downclock.
>>>>>>
>>>>>> v9: Jani's review comments. Modified comment in set_drrs. Changed index to
>>>>>> type edp_drrs_refresh_rate_type. Check if PSR is enabled before setting
>>>>>> registers fo DRRS.
>>>>>>
>>>>>> Signed-off-by: Pradeep Bhat <pradeep.bhat@intel.com>
>>>>>> Signed-off-by: Vandana Kannan <vandana.kannan@intel.com>
>>>>>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>>>>
>>>> Queued for -next, thanks for the patch. One thing that's missing though is
>>>> the state readout and cross-check support for this new bit of crtc->config
>>>> data. We need to add that before putting this to real use.
>>>> -Daniel
>>>>
>>> Hi Daniel,
>>>
>>> Could you please elaborate on your input above - on the missing code and
>>> cross-checking for support part?
>>
>> If you add new state to crtc->config then you need to add the relevan
>> readout code for that state (see the code in check_crtc_state) and ofc
>> also add it to intel_pipe_config_compare.
>>
>> This is a debug feature of our driver to make sure we never lose track of
>> things and thus far has been extremely helpful in catching issues early.
>> -Daniel
>>
> I have submitted a patch adding this piece of code. Please have a look..
> http://lists.freedesktop.org/archives/intel-gfx/2014-April/043569.html
>
> - Vandana
>
Hi Daniel,
Please help review the patch
http://lists.freedesktop.org/archives/intel-gfx/2014-April/043569.html
which is based on your review comments above.
-Vandana
_______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2014-04-21 4:28 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-28 4:44 [PATCH 0/6] v7: Enabling DRRS in the kernel Vandana Kannan
2014-03-28 4:44 ` [PATCH 1/6] drm/i915: Adding VBT fields to support eDP DRRS feature Vandana Kannan
2014-04-01 13:04 ` Jani Nikula
2014-04-01 17:26 ` Daniel Vetter
2014-03-28 4:44 ` [PATCH 2/6] drm/i915: Parse EDID probed modes for DRRS support Vandana Kannan
2014-04-01 13:17 ` Jani Nikula
2014-04-03 11:10 ` [PATCH v8 " Vandana Kannan
2014-04-03 11:46 ` Jani Nikula
2014-04-04 4:57 ` [PATCH v9 " Vandana Kannan
2014-04-04 10:47 ` [PATCH v10 " Vandana Kannan
2014-04-04 10:55 ` Jani Nikula
2014-04-04 11:13 ` Vandana Kannan
2014-04-05 6:42 ` [PATCH v11 " Vandana Kannan
2014-04-10 8:42 ` Jani Nikula
2014-04-10 8:55 ` Daniel Vetter
2014-03-28 4:44 ` [PATCH 3/6] drm/i915: Add support for DRRS to switch RR Vandana Kannan
2014-04-01 13:25 ` Jani Nikula
2014-04-02 5:58 ` Vandana Kannan
2014-04-03 11:14 ` [PATCH v9 " Vandana Kannan
2014-04-04 4:58 ` Vandana Kannan
2014-04-05 6:43 ` Vandana Kannan
2014-04-10 8:43 ` Jani Nikula
2014-04-10 8:56 ` Daniel Vetter
2014-04-10 8:58 ` Daniel Vetter
2014-04-11 9:18 ` Vandana Kannan
2014-04-11 9:26 ` Daniel Vetter
2014-04-11 11:21 ` Vandana Kannan
2014-04-21 4:28 ` Vandana Kannan
2014-03-28 4:45 ` [PATCH 4/6] drm/i915: Idleness detection for DRRS Vandana Kannan
2014-04-01 13:36 ` Jani Nikula
2014-04-03 11:17 ` [PATCH v9 " Vandana Kannan
2014-04-04 5:00 ` [PATCH v10 " Vandana Kannan
2014-04-04 6:54 ` Jani Nikula
2014-04-04 10:53 ` [PATCH v11 " Vandana Kannan
2014-04-05 6:44 ` Vandana Kannan
2014-04-10 8:52 ` Jani Nikula
2014-03-28 4:45 ` [PATCH 5/6] drm/i915/bdw: Add support for DRRS to switch RR Vandana Kannan
2014-04-01 13:37 ` Jani Nikula
2014-03-28 4:45 ` [PATCH 6/6] drm/i915: Support for RR switching on VLV Vandana Kannan
2014-04-01 13:41 ` Jani Nikula
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox