All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] drm/i915: implement IPS feature
@ 2013-05-13 19:00 Paulo Zanoni
  2013-05-13 19:00 ` [PATCH 2/3] drm/i915: add enable_ips module option Paulo Zanoni
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Paulo Zanoni @ 2013-05-13 19:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Intermediate Pixel Storage is a feature that should reduce the number
of times the display engine wakes up memory to read pixels, so it
should allow deeper PC states. IPS can only be enabled on ULT port A
with 8:8:8 pipe pixel formats.

With eDP 1920x1080 and correct watermarks but without FBC this moves
my PC7 residency from 2.5% to around 38%.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |   11 +++++
 drivers/gpu/drm/i915/intel_display.c |   80 +++++++++++++++++++++++++++++++++-
 2 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 32eb97c..65339a7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -977,6 +977,8 @@
 /* Framebuffer compression for Ivybridge */
 #define IVB_FBC_RT_BASE			0x7020
 
+#define IPS_CTL		0x43408
+#define   IPS_ENABLE	(1 << 31)
 
 #define _HSW_PIPE_SLICE_CHICKEN_1_A	0x420B0
 #define _HSW_PIPE_SLICE_CHICKEN_1_B	0x420B4
@@ -3621,6 +3623,15 @@
 #define _LGC_PALETTE_B           0x4a800
 #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
 
+#define _GAMMA_MODE_A		0x4a480
+#define _GAMMA_MODE_B		0x4ac80
+#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
+#define GAMMA_MODE_MODE_MASK	(3 << 0)
+#define GAMMA_MODE_MODE_8bit	(0 << 0)
+#define GAMMA_MODE_MODE_10bit	(1 << 0)
+#define GAMMA_MODE_MODE_12bit	(2 << 0)
+#define GAMMA_MODE_MODE_SPLIT	(3 << 0)
+
 /* interrupts */
 #define DE_MASTER_IRQ_CONTROL   (1 << 31)
 #define DE_SPRITEB_FLIP_DONE    (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 48166fe..61e4671 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3340,6 +3340,62 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+static bool hsw_crtc_supports_ips(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
+	bool is_port_a_edp = false;
+
+	if (!IS_ULT(dev))
+		return false;
+
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->type == INTEL_OUTPUT_EDP)
+			if (enc_to_dig_port(&encoder->base)->port == PORT_A)
+				is_port_a_edp = true;
+	if (!is_port_a_edp)
+		return false;
+
+	if (intel_crtc->config.pipe_bpp != 24)
+		return false;
+
+	return true;
+}
+
+static void hsw_enable_ips(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+
+	if (!hsw_crtc_supports_ips(crtc))
+		return;
+
+	DRM_DEBUG_KMS("Enabling IPS\n");
+
+	/* We can only enable IPS after we enable a plane and wait for a vblank.
+	 * We guarantee that the plane is enabled by calling intel_enable_ips
+	 * only after intel_enable_plane. And intel_enable_plane already waits
+	 * for a vblank, so all we need to do here is to enable the IPS bit. */
+	I915_WRITE(IPS_CTL, IPS_ENABLE);
+}
+
+static void hsw_disable_ips(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	if (!hsw_crtc_supports_ips(crtc))
+		return;
+
+	DRM_DEBUG_KMS("Disabling IPS\n");
+
+	I915_WRITE(IPS_CTL, 0);
+
+	/* We need to wait for a vblank before we can disable the plane. */
+	intel_wait_for_vblank(dev, intel_crtc->pipe);
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3387,6 +3443,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
 
+	hsw_enable_ips(crtc);
+
 	if (intel_crtc->config.has_pch_encoder)
 		lpt_pch_enable(crtc);
 
@@ -3516,6 +3574,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	if (dev_priv->cfb_plane == plane)
 		intel_disable_fbc(dev);
 
+	hsw_disable_ips(crtc);
+
 	intel_disable_plane(dev_priv, plane, pipe);
 
 	if (intel_crtc->config.has_pch_encoder)
@@ -6291,8 +6351,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int palreg = PALETTE(intel_crtc->pipe);
+	enum pipe pipe = intel_crtc->pipe;
+	int palreg = PALETTE(pipe);
 	int i;
+	bool reenable_ips = false;
 
 	/* The clocks have to be on to load the palette. */
 	if (!crtc->enabled || !intel_crtc->active)
@@ -6300,7 +6362,18 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 
 	/* use legacy palette for Ironlake */
 	if (HAS_PCH_SPLIT(dev))
-		palreg = LGC_PALETTE(intel_crtc->pipe);
+		palreg = LGC_PALETTE(pipe);
+
+	/* Workaround : Do not read or write the pipe palette/gamma data while
+	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+	 */
+	if (hsw_crtc_supports_ips(crtc) &&
+	    (I915_READ(IPS_CTL) & IPS_ENABLE) &&
+	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
+	     GAMMA_MODE_MODE_SPLIT)) {
+		hsw_disable_ips(crtc);
+		reenable_ips = true;
+	}
 
 	for (i = 0; i < 256; i++) {
 		I915_WRITE(palreg + 4 * i,
@@ -6308,6 +6381,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 			   (intel_crtc->lut_g[i] << 8) |
 			   intel_crtc->lut_b[i]);
 	}
+
+	if (reenable_ips)
+		hsw_enable_ips(crtc);
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
-- 
1.7.10.4

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

* [PATCH 2/3] drm/i915: add enable_ips module option
  2013-05-13 19:00 [PATCH 1/3] drm/i915: implement IPS feature Paulo Zanoni
@ 2013-05-13 19:00 ` Paulo Zanoni
  2013-05-16 19:56   ` Paulo Zanoni
  2013-05-13 19:00 ` [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry Paulo Zanoni
  2013-05-15  7:54 ` [PATCH 1/3] drm/i915: implement IPS feature Chris Wilson
  2 siblings, 1 reply; 16+ messages in thread
From: Paulo Zanoni @ 2013-05-13 19:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

IPS is still enabled by default. Feature requested by the power
management team.

This should also help testing the feature on some early pre-production
hardware where there were relationship problems between IPS and PSR.

Requested-by: Kristen Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c      |    4 ++++
 drivers/gpu/drm/i915/i915_drv.h      |    1 +
 drivers/gpu/drm/i915/intel_display.c |    3 +++
 3 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a1a936f..f356304 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -128,6 +128,10 @@ module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
 MODULE_PARM_DESC(disable_power_well,
 		 "Disable the power well when possible (default: false)");
 
+int i915_enable_ips __read_mostly = 1;
+module_param_named(enable_ips, i915_enable_ips, int, 0600);
+MODULE_PARM_DESC(enable_ips, "Enables IPS (default: true)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 639ec0b..a25669f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1460,6 +1460,7 @@ extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
 extern int i915_disable_power_well __read_mostly;
+extern int i915_enable_ips __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 61e4671..e9129b9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3350,6 +3350,9 @@ static bool hsw_crtc_supports_ips(struct drm_crtc *crtc)
 	if (!IS_ULT(dev))
 		return false;
 
+	if (!i915_enable_ips)
+		return false;
+
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->type == INTEL_OUTPUT_EDP)
 			if (enc_to_dig_port(&encoder->base)->port == PORT_A)
-- 
1.7.10.4

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

* [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry
  2013-05-13 19:00 [PATCH 1/3] drm/i915: implement IPS feature Paulo Zanoni
  2013-05-13 19:00 ` [PATCH 2/3] drm/i915: add enable_ips module option Paulo Zanoni
@ 2013-05-13 19:00 ` Paulo Zanoni
  2013-05-14 17:59   ` Rodrigo Vivi
  2013-05-31 16:08   ` Rodrigo Vivi
  2013-05-15  7:54 ` [PATCH 1/3] drm/i915: implement IPS feature Chris Wilson
  2 siblings, 2 replies; 16+ messages in thread
From: Paulo Zanoni @ 2013-05-13 19:00 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

It just prints whether it's supported/enabled/disabled. Feature
requested by the power management team.

Requested-by: Kristen Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a55630a..382ba64 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1311,6 +1311,25 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static int i915_ips_status(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!IS_ULT(dev)) {
+		seq_printf(m, "not supported\n");
+		return 0;
+	}
+
+	if (I915_READ(IPS_CTL) & IPS_ENABLE)
+		seq_printf(m, "enabled\n");
+	else
+		seq_printf(m, "disabled\n");
+
+	return 0;
+}
+
 static int i915_sr_status(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -2108,6 +2127,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_ring_freq_table", i915_ring_freq_table, 0},
 	{"i915_gfxec", i915_gfxec, 0},
 	{"i915_fbc_status", i915_fbc_status, 0},
+	{"i915_ips_status", i915_ips_status, 0},
 	{"i915_sr_status", i915_sr_status, 0},
 	{"i915_opregion", i915_opregion, 0},
 	{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
-- 
1.7.10.4

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

* Re: [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry
  2013-05-13 19:00 ` [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry Paulo Zanoni
@ 2013-05-14 17:59   ` Rodrigo Vivi
  2013-05-14 17:59     ` Rodrigo Vivi
  2013-05-31 16:08   ` Rodrigo Vivi
  1 sibling, 1 reply; 16+ messages in thread
From: Rodrigo Vivi @ 2013-05-14 17:59 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Feel free to use: Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Mon, May 13, 2013 at 4:00 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> It just prints whether it's supported/enabled/disabled. Feature
> requested by the power management team.
>
> Requested-by: Kristen Accardi <kristen.c.accardi@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |   20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index a55630a..382ba64 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1311,6 +1311,25 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
>         return 0;
>  }
>
> +static int i915_ips_status(struct seq_file *m, void *unused)
> +{
> +       struct drm_info_node *node = (struct drm_info_node *) m->private;
> +       struct drm_device *dev = node->minor->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       if (!IS_ULT(dev)) {
> +               seq_printf(m, "not supported\n");
> +               return 0;
> +       }
> +
> +       if (I915_READ(IPS_CTL) & IPS_ENABLE)
> +               seq_printf(m, "enabled\n");
> +       else
> +               seq_printf(m, "disabled\n");
> +
> +       return 0;
> +}
> +
>  static int i915_sr_status(struct seq_file *m, void *unused)
>  {
>         struct drm_info_node *node = (struct drm_info_node *) m->private;
> @@ -2108,6 +2127,7 @@ static struct drm_info_list i915_debugfs_list[] = {
>         {"i915_ring_freq_table", i915_ring_freq_table, 0},
>         {"i915_gfxec", i915_gfxec, 0},
>         {"i915_fbc_status", i915_fbc_status, 0},
> +       {"i915_ips_status", i915_ips_status, 0},
>         {"i915_sr_status", i915_sr_status, 0},
>         {"i915_opregion", i915_opregion, 0},
>         {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
> --
> 1.7.10.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry
  2013-05-14 17:59   ` Rodrigo Vivi
@ 2013-05-14 17:59     ` Rodrigo Vivi
  0 siblings, 0 replies; 16+ messages in thread
From: Rodrigo Vivi @ 2013-05-14 17:59 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> for the entire series


On Tue, May 14, 2013 at 2:59 PM, Rodrigo Vivi <rodrigo.vivi@gmail.com> wrote:
> Feel free to use: Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
>
> On Mon, May 13, 2013 at 4:00 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
>> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>>
>> It just prints whether it's supported/enabled/disabled. Feature
>> requested by the power management team.
>>
>> Requested-by: Kristen Accardi <kristen.c.accardi@intel.com>
>> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_debugfs.c |   20 ++++++++++++++++++++
>>  1 file changed, 20 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>> index a55630a..382ba64 100644
>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>> @@ -1311,6 +1311,25 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
>>         return 0;
>>  }
>>
>> +static int i915_ips_status(struct seq_file *m, void *unused)
>> +{
>> +       struct drm_info_node *node = (struct drm_info_node *) m->private;
>> +       struct drm_device *dev = node->minor->dev;
>> +       struct drm_i915_private *dev_priv = dev->dev_private;
>> +
>> +       if (!IS_ULT(dev)) {
>> +               seq_printf(m, "not supported\n");
>> +               return 0;
>> +       }
>> +
>> +       if (I915_READ(IPS_CTL) & IPS_ENABLE)
>> +               seq_printf(m, "enabled\n");
>> +       else
>> +               seq_printf(m, "disabled\n");
>> +
>> +       return 0;
>> +}
>> +
>>  static int i915_sr_status(struct seq_file *m, void *unused)
>>  {
>>         struct drm_info_node *node = (struct drm_info_node *) m->private;
>> @@ -2108,6 +2127,7 @@ static struct drm_info_list i915_debugfs_list[] = {
>>         {"i915_ring_freq_table", i915_ring_freq_table, 0},
>>         {"i915_gfxec", i915_gfxec, 0},
>>         {"i915_fbc_status", i915_fbc_status, 0},
>> +       {"i915_ips_status", i915_ips_status, 0},
>>         {"i915_sr_status", i915_sr_status, 0},
>>         {"i915_opregion", i915_opregion, 0},
>>         {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
>> --
>> 1.7.10.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
>
> --
> Rodrigo Vivi
> Blog: http://blog.vivi.eng.br



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH 1/3] drm/i915: implement IPS feature
  2013-05-13 19:00 [PATCH 1/3] drm/i915: implement IPS feature Paulo Zanoni
  2013-05-13 19:00 ` [PATCH 2/3] drm/i915: add enable_ips module option Paulo Zanoni
  2013-05-13 19:00 ` [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry Paulo Zanoni
@ 2013-05-15  7:54 ` Chris Wilson
  2013-05-16 19:54   ` Paulo Zanoni
  2 siblings, 1 reply; 16+ messages in thread
From: Chris Wilson @ 2013-05-15  7:54 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Mon, May 13, 2013 at 04:00:08PM -0300, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Intermediate Pixel Storage is a feature that should reduce the number
> of times the display engine wakes up memory to read pixels, so it
> should allow deeper PC states. IPS can only be enabled on ULT port A
> with 8:8:8 pipe pixel formats.
> 
> With eDP 1920x1080 and correct watermarks but without FBC this moves
> my PC7 residency from 2.5% to around 38%.

You need to read initial IPS state and add that to pipe-config so that
takeover from the BIOS is correct and to make the code less fiddly.

[snip]

> +static bool hsw_crtc_supports_ips(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct intel_encoder *encoder;
> +	bool is_port_a_edp = false;
> +
> +	if (!IS_ULT(dev))
> +		return false;
> +
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		if (encoder->type == INTEL_OUTPUT_EDP)
> +			if (enc_to_dig_port(&encoder->base)->port == PORT_A)
> +				is_port_a_edp = true;
> +	if (!is_port_a_edp)
> +		return false;
> +
> +	if (intel_crtc->config.pipe_bpp != 24)
> +		return false;
> +

Try:
 {
  if (!IS_ULT(dev)) return false;
  if (intel_crtc->config.pipe_bpp != 24) return false;
  for_each_encoder_on_crtc() if (encoder->type == INTEL_OUTPUT_EDP && enc_to_dig_port(encoder) == PORT_A) return true;
  return false;
 }

> +	return true;
> +}
> +
> +static void hsw_enable_ips(struct drm_crtc *crtc)
> +{
> +	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
> +
> +	if (!hsw_crtc_supports_ips(crtc))
> +		return;
> +
> +	DRM_DEBUG_KMS("Enabling IPS\n");
> +
> +	/* We can only enable IPS after we enable a plane and wait for a vblank.
> +	 * We guarantee that the plane is enabled by calling intel_enable_ips
> +	 * only after intel_enable_plane. And intel_enable_plane already waits
> +	 * for a vblank, so all we need to do here is to enable the IPS bit. */

Throw in an assert_pipe_enabled() for good measure.

> +	I915_WRITE(IPS_CTL, IPS_ENABLE);
> +}
> +
> +static void hsw_disable_ips(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +
> +	if (!hsw_crtc_supports_ips(crtc))
> +		return;

For disabling, it would be better to check if the IPS feature was
enabled on this pipe. As written, one can change the module parameter to
trick the system into running with IPS always enabled - presumably that
is bad.

> +
> +	DRM_DEBUG_KMS("Disabling IPS\n");
> +
> +	I915_WRITE(IPS_CTL, 0);
> +
> +	/* We need to wait for a vblank before we can disable the plane. */
> +	intel_wait_for_vblank(dev, intel_crtc->pipe);
> +}
> +
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> @@ -3387,6 +3443,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  			  intel_crtc->config.has_pch_encoder);
>  	intel_enable_plane(dev_priv, plane, pipe);
>  
> +	hsw_enable_ips(crtc);
> +
>  	if (intel_crtc->config.has_pch_encoder)
>  		lpt_pch_enable(crtc);
>  
> @@ -3516,6 +3574,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>  	if (dev_priv->cfb_plane == plane)
>  		intel_disable_fbc(dev);
>  
> +	hsw_disable_ips(crtc);
> +
>  	intel_disable_plane(dev_priv, plane, pipe);
>  
>  	if (intel_crtc->config.has_pch_encoder)
> @@ -6291,8 +6351,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	int palreg = PALETTE(intel_crtc->pipe);
> +	enum pipe pipe = intel_crtc->pipe;
> +	int palreg = PALETTE(pipe);
>  	int i;
> +	bool reenable_ips = false;
>  
>  	/* The clocks have to be on to load the palette. */
>  	if (!crtc->enabled || !intel_crtc->active)
> @@ -6300,7 +6362,18 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  
>  	/* use legacy palette for Ironlake */
>  	if (HAS_PCH_SPLIT(dev))
> -		palreg = LGC_PALETTE(intel_crtc->pipe);
> +		palreg = LGC_PALETTE(pipe);
> +
> +	/* Workaround : Do not read or write the pipe palette/gamma data while
> +	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
> +	 */
> +	if (hsw_crtc_supports_ips(crtc) &&

Bring on pipe_config IPS state - as this can provoked into a user
triggerable hang (or something)...

> +	    (I915_READ(IPS_CTL) & IPS_ENABLE) &&
> +	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
> +	     GAMMA_MODE_MODE_SPLIT)) {
> +		hsw_disable_ips(crtc);
> +		reenable_ips = true;
> +	}
>  
>  	for (i = 0; i < 256; i++) {
>  		I915_WRITE(palreg + 4 * i,
> @@ -6308,6 +6381,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  			   (intel_crtc->lut_g[i] << 8) |
>  			   intel_crtc->lut_b[i]);
>  	}
> +
> +	if (reenable_ips)
> +		hsw_enable_ips(crtc);

See above.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* [PATCH 1/3] drm/i915: implement IPS feature
  2013-05-15  7:54 ` [PATCH 1/3] drm/i915: implement IPS feature Chris Wilson
@ 2013-05-16 19:54   ` Paulo Zanoni
  2013-05-18  3:18     ` Rodrigo Vivi
  2013-05-21  8:41     ` Daniel Vetter
  0 siblings, 2 replies; 16+ messages in thread
From: Paulo Zanoni @ 2013-05-16 19:54 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Intermediate Pixel Storage is a feature that should reduce the number
of times the display engine wakes up memory to read pixels, so it
should allow deeper PC states. IPS can only be enabled on ULT pipe A
with 8:8:8 pipe pixel formats.

With eDP 1920x1080 and correct watermarks but without FBC this moves
my PC7 residency from 2.5% to around 38%.

v2: - It's tied to pipe A, not port A
    - Add pipe_config support (Chris)
    - Add some assertions (Chris)
    - Rebase against latest dinq

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      | 11 +++++
 drivers/gpu/drm/i915/intel_display.c | 79 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h     |  2 +
 3 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 32eb97c..65339a7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -977,6 +977,8 @@
 /* Framebuffer compression for Ivybridge */
 #define IVB_FBC_RT_BASE			0x7020
 
+#define IPS_CTL		0x43408
+#define   IPS_ENABLE	(1 << 31)
 
 #define _HSW_PIPE_SLICE_CHICKEN_1_A	0x420B0
 #define _HSW_PIPE_SLICE_CHICKEN_1_B	0x420B4
@@ -3621,6 +3623,15 @@
 #define _LGC_PALETTE_B           0x4a800
 #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
 
+#define _GAMMA_MODE_A		0x4a480
+#define _GAMMA_MODE_B		0x4ac80
+#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
+#define GAMMA_MODE_MODE_MASK	(3 << 0)
+#define GAMMA_MODE_MODE_8bit	(0 << 0)
+#define GAMMA_MODE_MODE_10bit	(1 << 0)
+#define GAMMA_MODE_MODE_12bit	(2 << 0)
+#define GAMMA_MODE_MODE_SPLIT	(3 << 0)
+
 /* interrupts */
 #define DE_MASTER_IRQ_CONTROL   (1 << 31)
 #define DE_SPRITEB_FLIP_DONE    (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d588ff6..5b41cf3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3340,6 +3340,53 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+/* IPS only exists on ULT machines and is tied to pipe A. */
+static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
+{
+	return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
+}
+
+static void hsw_enable_ips(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (!hsw_crtc_supports_ips(crtc))
+		return;
+
+	if (crtc->config.pipe_bpp != 24)
+		return;
+
+	DRM_DEBUG_KMS("Enabling IPS\n");
+
+	crtc->config.ips_enabled = true;
+
+	/* We can only enable IPS after we enable a plane and wait for a vblank.
+	 * We guarantee that the plane is enabled by calling intel_enable_ips
+	 * only after intel_enable_plane. And intel_enable_plane already waits
+	 * for a vblank, so all we need to do here is to enable the IPS bit. */
+	assert_plane_enabled(dev_priv, crtc->plane);
+	I915_WRITE(IPS_CTL, IPS_ENABLE);
+}
+
+static void hsw_disable_ips(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!hsw_crtc_supports_ips(crtc))
+		return;
+
+	DRM_DEBUG_KMS("Disabling IPS\n");
+
+	crtc->config.ips_enabled = false;
+
+	assert_plane_enabled(dev_priv, crtc->plane);
+	I915_WRITE(IPS_CTL, 0);
+
+	/* We need to wait for a vblank before we can disable the plane. */
+	intel_wait_for_vblank(dev, crtc->pipe);
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3387,6 +3434,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
 
+	hsw_enable_ips(intel_crtc);
+
 	if (intel_crtc->config.has_pch_encoder)
 		lpt_pch_enable(crtc);
 
@@ -3529,6 +3578,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	if (dev_priv->cfb_plane == plane)
 		intel_disable_fbc(dev);
 
+	hsw_disable_ips(intel_crtc);
+
 	intel_disable_plane(dev_priv, plane, pipe);
 
 	if (intel_crtc->config.has_pch_encoder)
@@ -5021,6 +5072,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 
 	i9xx_get_pfit_config(crtc, pipe_config);
 
+	pipe_config->ips_enabled = false;
+
 	return true;
 }
 
@@ -5890,6 +5943,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 
 	ironlake_get_pfit_config(crtc, pipe_config);
 
+	pipe_config->ips_enabled = false;
+
 	return true;
 }
 
@@ -6041,6 +6096,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 	if (intel_display_power_enabled(dev, pfit_domain))
 		ironlake_get_pfit_config(crtc, pipe_config);
 
+	pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
+				   (I915_READ(IPS_CTL) & IPS_ENABLE);
+
 	return true;
 }
 
@@ -6345,8 +6403,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int palreg = PALETTE(intel_crtc->pipe);
+	enum pipe pipe = intel_crtc->pipe;
+	int palreg = PALETTE(pipe);
 	int i;
+	bool reenable_ips = false;
 
 	/* The clocks have to be on to load the palette. */
 	if (!crtc->enabled || !intel_crtc->active)
@@ -6354,7 +6414,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 
 	/* use legacy palette for Ironlake */
 	if (HAS_PCH_SPLIT(dev))
-		palreg = LGC_PALETTE(intel_crtc->pipe);
+		palreg = LGC_PALETTE(pipe);
+
+	/* Workaround : Do not read or write the pipe palette/gamma data while
+	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+	 */
+	if (intel_crtc->config.ips_enabled &&
+	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
+	     GAMMA_MODE_MODE_SPLIT)) {
+		hsw_disable_ips(intel_crtc);
+		reenable_ips = true;
+	}
 
 	for (i = 0; i < 256; i++) {
 		I915_WRITE(palreg + 4 * i,
@@ -6362,6 +6432,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 			   (intel_crtc->lut_g[i] << 8) |
 			   intel_crtc->lut_b[i]);
 	}
+
+	if (reenable_ips)
+		hsw_enable_ips(intel_crtc);
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
@@ -8064,6 +8137,8 @@ intel_pipe_config_compare(struct drm_device *dev,
 	PIPE_CONF_CHECK_I(pch_pfit.pos);
 	PIPE_CONF_CHECK_I(pch_pfit.size);
 
+	PIPE_CONF_CHECK_I(ips_enabled);
+
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_FLAGS
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ba05cc7..5e4844a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -264,6 +264,8 @@ struct intel_crtc_config {
 	/* FDI configuration, only valid if has_pch_encoder is set. */
 	int fdi_lanes;
 	struct intel_link_m_n fdi_m_n;
+
+	bool ips_enabled;
 };
 
 struct intel_crtc {
-- 
1.8.1.2

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

* [PATCH 2/3] drm/i915: add enable_ips module option
  2013-05-13 19:00 ` [PATCH 2/3] drm/i915: add enable_ips module option Paulo Zanoni
@ 2013-05-16 19:56   ` Paulo Zanoni
  2013-05-31 16:04     ` Rodrigo Vivi
  0 siblings, 1 reply; 16+ messages in thread
From: Paulo Zanoni @ 2013-05-16 19:56 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

IPS is still enabled by default. Feature requested by the power
management team.

This should also help testing the feature on some early pre-production
hardware where there were relationship problems between IPS and PSR.

v2: Rebase on top of the newest IPS implementation.

Requested-by: Kristen Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c      | 4 ++++
 drivers/gpu/drm/i915/i915_drv.h      | 1 +
 drivers/gpu/drm/i915/intel_display.c | 3 ++-
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a1a936f..0289f24 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -128,6 +128,10 @@ module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
 MODULE_PARM_DESC(disable_power_well,
 		 "Disable the power well when possible (default: false)");
 
+int i915_enable_ips __read_mostly = 1;
+module_param_named(enable_ips, i915_enable_ips, int, 0600);
+MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 639ec0b..a25669f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1460,6 +1460,7 @@ extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
 extern int i915_disable_power_well __read_mostly;
+extern int i915_enable_ips __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5b41cf3..afde99e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3343,7 +3343,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 /* IPS only exists on ULT machines and is tied to pipe A. */
 static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
 {
-	return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
+	return (i915_enable_ips && IS_ULT(crtc->base.dev) &&
+		crtc->pipe == PIPE_A);
 }
 
 static void hsw_enable_ips(struct intel_crtc *crtc)
-- 
1.8.1.2

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

* Re: [PATCH 1/3] drm/i915: implement IPS feature
  2013-05-16 19:54   ` Paulo Zanoni
@ 2013-05-18  3:18     ` Rodrigo Vivi
  2013-05-21  8:41     ` Daniel Vetter
  1 sibling, 0 replies; 16+ messages in thread
From: Rodrigo Vivi @ 2013-05-18  3:18 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Thu, May 16, 2013 at 4:54 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Intermediate Pixel Storage is a feature that should reduce the number
> of times the display engine wakes up memory to read pixels, so it
> should allow deeper PC states. IPS can only be enabled on ULT pipe A
> with 8:8:8 pipe pixel formats.
>
> With eDP 1920x1080 and correct watermarks but without FBC this moves
> my PC7 residency from 2.5% to around 38%.
>
> v2: - It's tied to pipe A, not port A
>     - Add pipe_config support (Chris)
>     - Add some assertions (Chris)
>     - Rebase against latest dinq
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h      | 11 +++++
>  drivers/gpu/drm/i915/intel_display.c | 79 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h     |  2 +
>  3 files changed, 90 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 32eb97c..65339a7 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -977,6 +977,8 @@
>  /* Framebuffer compression for Ivybridge */
>  #define IVB_FBC_RT_BASE                        0x7020
>
> +#define IPS_CTL                0x43408
> +#define   IPS_ENABLE   (1 << 31)
>
>  #define _HSW_PIPE_SLICE_CHICKEN_1_A    0x420B0
>  #define _HSW_PIPE_SLICE_CHICKEN_1_B    0x420B4
> @@ -3621,6 +3623,15 @@
>  #define _LGC_PALETTE_B           0x4a800
>  #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
>
> +#define _GAMMA_MODE_A          0x4a480
> +#define _GAMMA_MODE_B          0x4ac80
> +#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
> +#define GAMMA_MODE_MODE_MASK   (3 << 0)
> +#define GAMMA_MODE_MODE_8bit   (0 << 0)
> +#define GAMMA_MODE_MODE_10bit  (1 << 0)
> +#define GAMMA_MODE_MODE_12bit  (2 << 0)
> +#define GAMMA_MODE_MODE_SPLIT  (3 << 0)
> +
>  /* interrupts */
>  #define DE_MASTER_IRQ_CONTROL   (1 << 31)
>  #define DE_SPRITEB_FLIP_DONE    (1 << 29)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index d588ff6..5b41cf3 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3340,6 +3340,53 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>         intel_wait_for_vblank(dev, intel_crtc->pipe);
>  }
>
> +/* IPS only exists on ULT machines and is tied to pipe A. */
> +static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
> +{
> +       return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
> +}
> +
> +static void hsw_enable_ips(struct intel_crtc *crtc)
> +{
> +       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> +
> +       if (!hsw_crtc_supports_ips(crtc))
> +               return;
> +
> +       if (crtc->config.pipe_bpp != 24)
> +               return;
> +
> +       DRM_DEBUG_KMS("Enabling IPS\n");
> +
> +       crtc->config.ips_enabled = true;
> +
> +       /* We can only enable IPS after we enable a plane and wait for a vblank.
> +        * We guarantee that the plane is enabled by calling intel_enable_ips
> +        * only after intel_enable_plane. And intel_enable_plane already waits
> +        * for a vblank, so all we need to do here is to enable the IPS bit. */
> +       assert_plane_enabled(dev_priv, crtc->plane);
> +       I915_WRITE(IPS_CTL, IPS_ENABLE);
> +}
> +
> +static void hsw_disable_ips(struct intel_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       if (!hsw_crtc_supports_ips(crtc))
> +               return;
> +
> +       DRM_DEBUG_KMS("Disabling IPS\n");
> +
> +       crtc->config.ips_enabled = false;
> +
> +       assert_plane_enabled(dev_priv, crtc->plane);
> +       I915_WRITE(IPS_CTL, 0);
> +
> +       /* We need to wait for a vblank before we can disable the plane. */
> +       intel_wait_for_vblank(dev, crtc->pipe);
> +}
> +
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
> @@ -3387,6 +3434,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>                           intel_crtc->config.has_pch_encoder);
>         intel_enable_plane(dev_priv, plane, pipe);
>
> +       hsw_enable_ips(intel_crtc);
> +
>         if (intel_crtc->config.has_pch_encoder)
>                 lpt_pch_enable(crtc);
>
> @@ -3529,6 +3578,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>         if (dev_priv->cfb_plane == plane)
>                 intel_disable_fbc(dev);
>
> +       hsw_disable_ips(intel_crtc);
> +
>         intel_disable_plane(dev_priv, plane, pipe);
>
>         if (intel_crtc->config.has_pch_encoder)
> @@ -5021,6 +5072,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
>
>         i9xx_get_pfit_config(crtc, pipe_config);
>
> +       pipe_config->ips_enabled = false;
> +
>         return true;
>  }
>
> @@ -5890,6 +5943,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
>
>         ironlake_get_pfit_config(crtc, pipe_config);
>
> +       pipe_config->ips_enabled = false;
> +
>         return true;
>  }
>
> @@ -6041,6 +6096,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>         if (intel_display_power_enabled(dev, pfit_domain))
>                 ironlake_get_pfit_config(crtc, pipe_config);
>
> +       pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
> +                                  (I915_READ(IPS_CTL) & IPS_ENABLE);
> +
>         return true;
>  }
>
> @@ -6345,8 +6403,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>         struct drm_device *dev = crtc->dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -       int palreg = PALETTE(intel_crtc->pipe);
> +       enum pipe pipe = intel_crtc->pipe;
> +       int palreg = PALETTE(pipe);
>         int i;
> +       bool reenable_ips = false;
>
>         /* The clocks have to be on to load the palette. */
>         if (!crtc->enabled || !intel_crtc->active)
> @@ -6354,7 +6414,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>
>         /* use legacy palette for Ironlake */
>         if (HAS_PCH_SPLIT(dev))
> -               palreg = LGC_PALETTE(intel_crtc->pipe);
> +               palreg = LGC_PALETTE(pipe);
> +
> +       /* Workaround : Do not read or write the pipe palette/gamma data while
> +        * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
> +        */
> +       if (intel_crtc->config.ips_enabled &&
> +           ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
> +            GAMMA_MODE_MODE_SPLIT)) {
> +               hsw_disable_ips(intel_crtc);
> +               reenable_ips = true;
> +       }
>
>         for (i = 0; i < 256; i++) {
>                 I915_WRITE(palreg + 4 * i,
> @@ -6362,6 +6432,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>                            (intel_crtc->lut_g[i] << 8) |
>                            intel_crtc->lut_b[i]);
>         }
> +
> +       if (reenable_ips)
> +               hsw_enable_ips(intel_crtc);
>  }
>
>  static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
> @@ -8064,6 +8137,8 @@ intel_pipe_config_compare(struct drm_device *dev,
>         PIPE_CONF_CHECK_I(pch_pfit.pos);
>         PIPE_CONF_CHECK_I(pch_pfit.size);
>
> +       PIPE_CONF_CHECK_I(ips_enabled);
> +
>  #undef PIPE_CONF_CHECK_I
>  #undef PIPE_CONF_CHECK_FLAGS
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index ba05cc7..5e4844a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -264,6 +264,8 @@ struct intel_crtc_config {
>         /* FDI configuration, only valid if has_pch_encoder is set. */
>         int fdi_lanes;
>         struct intel_link_m_n fdi_m_n;
> +
> +       bool ips_enabled;
>  };
>
>  struct intel_crtc {
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH 1/3] drm/i915: implement IPS feature
  2013-05-16 19:54   ` Paulo Zanoni
  2013-05-18  3:18     ` Rodrigo Vivi
@ 2013-05-21  8:41     ` Daniel Vetter
  2013-05-23 21:26       ` Paulo Zanoni
  1 sibling, 1 reply; 16+ messages in thread
From: Daniel Vetter @ 2013-05-21  8:41 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, May 16, 2013 at 04:54:04PM -0300, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Intermediate Pixel Storage is a feature that should reduce the number
> of times the display engine wakes up memory to read pixels, so it
> should allow deeper PC states. IPS can only be enabled on ULT pipe A
> with 8:8:8 pipe pixel formats.
> 
> With eDP 1920x1080 and correct watermarks but without FBC this moves
> my PC7 residency from 2.5% to around 38%.
> 
> v2: - It's tied to pipe A, not port A
>     - Add pipe_config support (Chris)
>     - Add some assertions (Chris)
>     - Rebase against latest dinq
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

Three small comments below.

> ---
>  drivers/gpu/drm/i915/i915_reg.h      | 11 +++++
>  drivers/gpu/drm/i915/intel_display.c | 79 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h     |  2 +
>  3 files changed, 90 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 32eb97c..65339a7 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -977,6 +977,8 @@
>  /* Framebuffer compression for Ivybridge */
>  #define IVB_FBC_RT_BASE			0x7020
>  
> +#define IPS_CTL		0x43408
> +#define   IPS_ENABLE	(1 << 31)
>  
>  #define _HSW_PIPE_SLICE_CHICKEN_1_A	0x420B0
>  #define _HSW_PIPE_SLICE_CHICKEN_1_B	0x420B4
> @@ -3621,6 +3623,15 @@
>  #define _LGC_PALETTE_B           0x4a800
>  #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
>  
> +#define _GAMMA_MODE_A		0x4a480
> +#define _GAMMA_MODE_B		0x4ac80
> +#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
> +#define GAMMA_MODE_MODE_MASK	(3 << 0)
> +#define GAMMA_MODE_MODE_8bit	(0 << 0)
> +#define GAMMA_MODE_MODE_10bit	(1 << 0)
> +#define GAMMA_MODE_MODE_12bit	(2 << 0)
> +#define GAMMA_MODE_MODE_SPLIT	(3 << 0)
> +
>  /* interrupts */
>  #define DE_MASTER_IRQ_CONTROL   (1 << 31)
>  #define DE_SPRITEB_FLIP_DONE    (1 << 29)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index d588ff6..5b41cf3 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3340,6 +3340,53 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  	intel_wait_for_vblank(dev, intel_crtc->pipe);
>  }
>  
> +/* IPS only exists on ULT machines and is tied to pipe A. */
> +static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
> +{
> +	return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
> +}
> +
> +static void hsw_enable_ips(struct intel_crtc *crtc)
> +{
> +	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> +
> +	if (!hsw_crtc_supports_ips(crtc))
> +		return;
> +
> +	if (crtc->config.pipe_bpp != 24)
> +		return;
> +
> +	DRM_DEBUG_KMS("Enabling IPS\n");
> +
> +	crtc->config.ips_enabled = true;
> +
> +	/* We can only enable IPS after we enable a plane and wait for a vblank.
> +	 * We guarantee that the plane is enabled by calling intel_enable_ips
> +	 * only after intel_enable_plane. And intel_enable_plane already waits
> +	 * for a vblank, so all we need to do here is to enable the IPS bit. */
> +	assert_plane_enabled(dev_priv, crtc->plane);
> +	I915_WRITE(IPS_CTL, IPS_ENABLE);
> +}
> +
> +static void hsw_disable_ips(struct intel_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (!hsw_crtc_supports_ips(crtc))
> +		return;

Like Chris suggested I think it's better to use the pipe_config state here
to decide whether to disable ips or not. Otherwise we could leak out an
enabled IPS config if the BIOS sets it up, but the module param is not
set.

> +
> +	DRM_DEBUG_KMS("Disabling IPS\n");
> +
> +	crtc->config.ips_enabled = false;
> +
> +	assert_plane_enabled(dev_priv, crtc->plane);
> +	I915_WRITE(IPS_CTL, 0);
> +
> +	/* We need to wait for a vblank before we can disable the plane. */
> +	intel_wait_for_vblank(dev, crtc->pipe);
> +}
> +
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> @@ -3387,6 +3434,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  			  intel_crtc->config.has_pch_encoder);
>  	intel_enable_plane(dev_priv, plane, pipe);
>  
> +	hsw_enable_ips(intel_crtc);
> +
>  	if (intel_crtc->config.has_pch_encoder)
>  		lpt_pch_enable(crtc);
>  
> @@ -3529,6 +3578,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>  	if (dev_priv->cfb_plane == plane)
>  		intel_disable_fbc(dev);
>  
> +	hsw_disable_ips(intel_crtc);
> +
>  	intel_disable_plane(dev_priv, plane, pipe);
>  
>  	if (intel_crtc->config.has_pch_encoder)
> @@ -5021,6 +5072,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
>  
>  	i9xx_get_pfit_config(crtc, pipe_config);
>  
> +	pipe_config->ips_enabled = false;

No need to ever clear a pipe_config since they are _always_ cleared to
zero. If we'd start doing that we'd very soon have a giant mess of
read-out code which clears things totally unrelated to the platform at
hand.

> +
>  	return true;
>  }
>  
> @@ -5890,6 +5943,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
>  
>  	ironlake_get_pfit_config(crtc, pipe_config);
>  
> +	pipe_config->ips_enabled = false;
> +
>  	return true;
>  }
>  
> @@ -6041,6 +6096,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>  	if (intel_display_power_enabled(dev, pfit_domain))
>  		ironlake_get_pfit_config(crtc, pipe_config);
>  
> +	pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
> +				   (I915_READ(IPS_CTL) & IPS_ENABLE);
> +
>  	return true;
>  }
>  
> @@ -6345,8 +6403,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	int palreg = PALETTE(intel_crtc->pipe);
> +	enum pipe pipe = intel_crtc->pipe;
> +	int palreg = PALETTE(pipe);
>  	int i;
> +	bool reenable_ips = false;
>  
>  	/* The clocks have to be on to load the palette. */
>  	if (!crtc->enabled || !intel_crtc->active)
> @@ -6354,7 +6414,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  
>  	/* use legacy palette for Ironlake */
>  	if (HAS_PCH_SPLIT(dev))
> -		palreg = LGC_PALETTE(intel_crtc->pipe);
> +		palreg = LGC_PALETTE(pipe);
> +
> +	/* Workaround : Do not read or write the pipe palette/gamma data while
> +	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
> +	 */

Does this w/a have an official name from the db? If so can you please add
the tag in Damien's new layout?

Cheers, Daniel

> +	if (intel_crtc->config.ips_enabled &&
> +	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
> +	     GAMMA_MODE_MODE_SPLIT)) {
> +		hsw_disable_ips(intel_crtc);
> +		reenable_ips = true;
> +	}
>  
>  	for (i = 0; i < 256; i++) {
>  		I915_WRITE(palreg + 4 * i,
> @@ -6362,6 +6432,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  			   (intel_crtc->lut_g[i] << 8) |
>  			   intel_crtc->lut_b[i]);
>  	}
> +
> +	if (reenable_ips)
> +		hsw_enable_ips(intel_crtc);
>  }
>  
>  static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
> @@ -8064,6 +8137,8 @@ intel_pipe_config_compare(struct drm_device *dev,
>  	PIPE_CONF_CHECK_I(pch_pfit.pos);
>  	PIPE_CONF_CHECK_I(pch_pfit.size);
>  
> +	PIPE_CONF_CHECK_I(ips_enabled);
> +
>  #undef PIPE_CONF_CHECK_I
>  #undef PIPE_CONF_CHECK_FLAGS
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index ba05cc7..5e4844a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -264,6 +264,8 @@ struct intel_crtc_config {
>  	/* FDI configuration, only valid if has_pch_encoder is set. */
>  	int fdi_lanes;
>  	struct intel_link_m_n fdi_m_n;
> +
> +	bool ips_enabled;
>  };
>  
>  struct intel_crtc {
> -- 
> 1.8.1.2
> 
> _______________________________________________
> 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] 16+ messages in thread

* [PATCH 1/3] drm/i915: implement IPS feature
  2013-05-21  8:41     ` Daniel Vetter
@ 2013-05-23 21:26       ` Paulo Zanoni
  2013-05-31 16:07         ` Rodrigo Vivi
  2013-05-31 16:30         ` Daniel Vetter
  0 siblings, 2 replies; 16+ messages in thread
From: Paulo Zanoni @ 2013-05-23 21:26 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Intermediate Pixel Storage is a feature that should reduce the number
of times the display engine wakes up memory to read pixels, so it
should allow deeper PC states. IPS can only be enabled on ULT pipe A
with 8:8:8 pipe pixel formats.

With eDP 1920x1080 and correct watermarks but without FBC this moves
my PC7 residency from 2.5% to around 38%.

v2: - It's tied to pipe A, not port A
    - Add pipe_config support (Chris)
    - Add some assertions (Chris)
    - Rebase against latest dinq
v3: - Don't ever set ips_enabled to false (Daniel)
    - Only check for ips_enabled at hsw_disable_ips (Daniel)

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      | 11 ++++++
 drivers/gpu/drm/i915/intel_display.c | 73 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h     |  2 +
 3 files changed, 84 insertions(+), 2 deletions(-)


The workaround we implement is called WANoName. What's the correct way to
proceed for WANoName?


diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 58230ea..5db20dc 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -977,6 +977,8 @@
 /* Framebuffer compression for Ivybridge */
 #define IVB_FBC_RT_BASE			0x7020
 
+#define IPS_CTL		0x43408
+#define   IPS_ENABLE	(1 << 31)
 
 #define _HSW_PIPE_SLICE_CHICKEN_1_A	0x420B0
 #define _HSW_PIPE_SLICE_CHICKEN_1_B	0x420B4
@@ -3620,6 +3622,15 @@
 #define _LGC_PALETTE_B           0x4a800
 #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
 
+#define _GAMMA_MODE_A		0x4a480
+#define _GAMMA_MODE_B		0x4ac80
+#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
+#define GAMMA_MODE_MODE_MASK	(3 << 0)
+#define GAMMA_MODE_MODE_8bit	(0 << 0)
+#define GAMMA_MODE_MODE_10bit	(1 << 0)
+#define GAMMA_MODE_MODE_12bit	(2 << 0)
+#define GAMMA_MODE_MODE_SPLIT	(3 << 0)
+
 /* interrupts */
 #define DE_MASTER_IRQ_CONTROL   (1 << 31)
 #define DE_SPRITEB_FLIP_DONE    (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1c0d6d3..bc99183 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3340,6 +3340,51 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+/* IPS only exists on ULT machines and is tied to pipe A. */
+static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
+{
+	return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
+}
+
+static void hsw_enable_ips(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (!hsw_crtc_supports_ips(crtc))
+		return;
+
+	if (crtc->config.pipe_bpp != 24)
+		return;
+
+	DRM_DEBUG_KMS("Enabling IPS\n");
+
+	crtc->config.ips_enabled = true;
+
+	/* We can only enable IPS after we enable a plane and wait for a vblank.
+	 * We guarantee that the plane is enabled by calling intel_enable_ips
+	 * only after intel_enable_plane. And intel_enable_plane already waits
+	 * for a vblank, so all we need to do here is to enable the IPS bit. */
+	assert_plane_enabled(dev_priv, crtc->plane);
+	I915_WRITE(IPS_CTL, IPS_ENABLE);
+}
+
+static void hsw_disable_ips(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!crtc->config.ips_enabled)
+		return;
+
+	DRM_DEBUG_KMS("Disabling IPS\n");
+
+	assert_plane_enabled(dev_priv, crtc->plane);
+	I915_WRITE(IPS_CTL, 0);
+
+	/* We need to wait for a vblank before we can disable the plane. */
+	intel_wait_for_vblank(dev, crtc->pipe);
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3387,6 +3432,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
 
+	hsw_enable_ips(intel_crtc);
+
 	if (intel_crtc->config.has_pch_encoder)
 		lpt_pch_enable(crtc);
 
@@ -3529,6 +3576,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	if (dev_priv->cfb_plane == plane)
 		intel_disable_fbc(dev);
 
+	hsw_disable_ips(intel_crtc);
+
 	intel_disable_plane(dev_priv, plane, pipe);
 
 	if (intel_crtc->config.has_pch_encoder)
@@ -6051,6 +6100,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 	if (intel_display_power_enabled(dev, pfit_domain))
 		ironlake_get_pfit_config(crtc, pipe_config);
 
+	pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
+				   (I915_READ(IPS_CTL) & IPS_ENABLE);
+
 	return true;
 }
 
@@ -6355,8 +6407,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int palreg = PALETTE(intel_crtc->pipe);
+	enum pipe pipe = intel_crtc->pipe;
+	int palreg = PALETTE(pipe);
 	int i;
+	bool reenable_ips = false;
 
 	/* The clocks have to be on to load the palette. */
 	if (!crtc->enabled || !intel_crtc->active)
@@ -6364,7 +6418,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 
 	/* use legacy palette for Ironlake */
 	if (HAS_PCH_SPLIT(dev))
-		palreg = LGC_PALETTE(intel_crtc->pipe);
+		palreg = LGC_PALETTE(pipe);
+
+	/* Workaround : Do not read or write the pipe palette/gamma data while
+	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+	 */
+	if (intel_crtc->config.ips_enabled &&
+	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
+	     GAMMA_MODE_MODE_SPLIT)) {
+		hsw_disable_ips(intel_crtc);
+		reenable_ips = true;
+	}
 
 	for (i = 0; i < 256; i++) {
 		I915_WRITE(palreg + 4 * i,
@@ -6372,6 +6436,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 			   (intel_crtc->lut_g[i] << 8) |
 			   intel_crtc->lut_b[i]);
 	}
+
+	if (reenable_ips)
+		hsw_enable_ips(intel_crtc);
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
@@ -8083,6 +8150,8 @@ intel_pipe_config_compare(struct drm_device *dev,
 	PIPE_CONF_CHECK_I(pch_pfit.pos);
 	PIPE_CONF_CHECK_I(pch_pfit.size);
 
+	PIPE_CONF_CHECK_I(ips_enabled);
+
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_FLAGS
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 57de0c1..2045974 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -268,6 +268,8 @@ struct intel_crtc_config {
 	/* FDI configuration, only valid if has_pch_encoder is set. */
 	int fdi_lanes;
 	struct intel_link_m_n fdi_m_n;
+
+	bool ips_enabled;
 };
 
 struct intel_crtc {
-- 
1.8.1.2

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

* Re: [PATCH 2/3] drm/i915: add enable_ips module option
  2013-05-16 19:56   ` Paulo Zanoni
@ 2013-05-31 16:04     ` Rodrigo Vivi
  0 siblings, 0 replies; 16+ messages in thread
From: Rodrigo Vivi @ 2013-05-31 16:04 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by:
Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Thu, May 16, 2013 at 4:56 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> IPS is still enabled by default. Feature requested by the power
> management team.
>
> This should also help testing the feature on some early pre-production
> hardware where there were relationship problems between IPS and PSR.
>
> v2: Rebase on top of the newest IPS implementation.
>
> Requested-by: Kristen Accardi <kristen.c.accardi@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c      | 4 ++++
>  drivers/gpu/drm/i915/i915_drv.h      | 1 +
>  drivers/gpu/drm/i915/intel_display.c | 3 ++-
>  3 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index a1a936f..0289f24 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -128,6 +128,10 @@ module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
>  MODULE_PARM_DESC(disable_power_well,
>                  "Disable the power well when possible (default: false)");
>
> +int i915_enable_ips __read_mostly = 1;
> +module_param_named(enable_ips, i915_enable_ips, int, 0600);
> +MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
> +
>  static struct drm_driver driver;
>  extern int intel_agp_enabled;
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 639ec0b..a25669f 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1460,6 +1460,7 @@ extern bool i915_enable_hangcheck __read_mostly;
>  extern int i915_enable_ppgtt __read_mostly;
>  extern unsigned int i915_preliminary_hw_support __read_mostly;
>  extern int i915_disable_power_well __read_mostly;
> +extern int i915_enable_ips __read_mostly;
>
>  extern int i915_suspend(struct drm_device *dev, pm_message_t state);
>  extern int i915_resume(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 5b41cf3..afde99e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3343,7 +3343,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  /* IPS only exists on ULT machines and is tied to pipe A. */
>  static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
>  {
> -       return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
> +       return (i915_enable_ips && IS_ULT(crtc->base.dev) &&
> +               crtc->pipe == PIPE_A);
>  }
>
>  static void hsw_enable_ips(struct intel_crtc *crtc)
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH 1/3] drm/i915: implement IPS feature
  2013-05-23 21:26       ` Paulo Zanoni
@ 2013-05-31 16:07         ` Rodrigo Vivi
  2013-05-31 16:30         ` Daniel Vetter
  1 sibling, 0 replies; 16+ messages in thread
From: Rodrigo Vivi @ 2013-05-31 16:07 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Thu, May 23, 2013 at 6:26 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> Intermediate Pixel Storage is a feature that should reduce the number
> of times the display engine wakes up memory to read pixels, so it
> should allow deeper PC states. IPS can only be enabled on ULT pipe A
> with 8:8:8 pipe pixel formats.
>
> With eDP 1920x1080 and correct watermarks but without FBC this moves
> my PC7 residency from 2.5% to around 38%.
>
> v2: - It's tied to pipe A, not port A
>     - Add pipe_config support (Chris)
>     - Add some assertions (Chris)
>     - Rebase against latest dinq
> v3: - Don't ever set ips_enabled to false (Daniel)
>     - Only check for ips_enabled at hsw_disable_ips (Daniel)
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h      | 11 ++++++
>  drivers/gpu/drm/i915/intel_display.c | 73 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h     |  2 +
>  3 files changed, 84 insertions(+), 2 deletions(-)
>
>
> The workaround we implement is called WANoName. What's the correct way to
> proceed for WANoName?
>
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 58230ea..5db20dc 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -977,6 +977,8 @@
>  /* Framebuffer compression for Ivybridge */
>  #define IVB_FBC_RT_BASE                        0x7020
>
> +#define IPS_CTL                0x43408
> +#define   IPS_ENABLE   (1 << 31)
>
>  #define _HSW_PIPE_SLICE_CHICKEN_1_A    0x420B0
>  #define _HSW_PIPE_SLICE_CHICKEN_1_B    0x420B4
> @@ -3620,6 +3622,15 @@
>  #define _LGC_PALETTE_B           0x4a800
>  #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
>
> +#define _GAMMA_MODE_A          0x4a480
> +#define _GAMMA_MODE_B          0x4ac80
> +#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
> +#define GAMMA_MODE_MODE_MASK   (3 << 0)
> +#define GAMMA_MODE_MODE_8bit   (0 << 0)
> +#define GAMMA_MODE_MODE_10bit  (1 << 0)
> +#define GAMMA_MODE_MODE_12bit  (2 << 0)
> +#define GAMMA_MODE_MODE_SPLIT  (3 << 0)
> +
>  /* interrupts */
>  #define DE_MASTER_IRQ_CONTROL   (1 << 31)
>  #define DE_SPRITEB_FLIP_DONE    (1 << 29)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 1c0d6d3..bc99183 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3340,6 +3340,51 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>         intel_wait_for_vblank(dev, intel_crtc->pipe);
>  }
>
> +/* IPS only exists on ULT machines and is tied to pipe A. */
> +static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
> +{
> +       return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
> +}
> +
> +static void hsw_enable_ips(struct intel_crtc *crtc)
> +{
> +       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> +
> +       if (!hsw_crtc_supports_ips(crtc))
> +               return;
> +
> +       if (crtc->config.pipe_bpp != 24)
> +               return;
> +
> +       DRM_DEBUG_KMS("Enabling IPS\n");
> +
> +       crtc->config.ips_enabled = true;
> +
> +       /* We can only enable IPS after we enable a plane and wait for a vblank.
> +        * We guarantee that the plane is enabled by calling intel_enable_ips
> +        * only after intel_enable_plane. And intel_enable_plane already waits
> +        * for a vblank, so all we need to do here is to enable the IPS bit. */
> +       assert_plane_enabled(dev_priv, crtc->plane);
> +       I915_WRITE(IPS_CTL, IPS_ENABLE);
> +}
> +
> +static void hsw_disable_ips(struct intel_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->base.dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       if (!crtc->config.ips_enabled)
> +               return;
> +
> +       DRM_DEBUG_KMS("Disabling IPS\n");
> +
> +       assert_plane_enabled(dev_priv, crtc->plane);
> +       I915_WRITE(IPS_CTL, 0);
> +
> +       /* We need to wait for a vblank before we can disable the plane. */
> +       intel_wait_for_vblank(dev, crtc->pipe);
> +}
> +
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
> @@ -3387,6 +3432,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>                           intel_crtc->config.has_pch_encoder);
>         intel_enable_plane(dev_priv, plane, pipe);
>
> +       hsw_enable_ips(intel_crtc);
> +
>         if (intel_crtc->config.has_pch_encoder)
>                 lpt_pch_enable(crtc);
>
> @@ -3529,6 +3576,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>         if (dev_priv->cfb_plane == plane)
>                 intel_disable_fbc(dev);
>
> +       hsw_disable_ips(intel_crtc);
> +
>         intel_disable_plane(dev_priv, plane, pipe);
>
>         if (intel_crtc->config.has_pch_encoder)
> @@ -6051,6 +6100,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>         if (intel_display_power_enabled(dev, pfit_domain))
>                 ironlake_get_pfit_config(crtc, pipe_config);
>
> +       pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
> +                                  (I915_READ(IPS_CTL) & IPS_ENABLE);
> +
>         return true;
>  }
>
> @@ -6355,8 +6407,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>         struct drm_device *dev = crtc->dev;
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -       int palreg = PALETTE(intel_crtc->pipe);
> +       enum pipe pipe = intel_crtc->pipe;
> +       int palreg = PALETTE(pipe);
>         int i;
> +       bool reenable_ips = false;
>
>         /* The clocks have to be on to load the palette. */
>         if (!crtc->enabled || !intel_crtc->active)
> @@ -6364,7 +6418,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>
>         /* use legacy palette for Ironlake */
>         if (HAS_PCH_SPLIT(dev))
> -               palreg = LGC_PALETTE(intel_crtc->pipe);
> +               palreg = LGC_PALETTE(pipe);
> +
> +       /* Workaround : Do not read or write the pipe palette/gamma data while
> +        * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
> +        */
> +       if (intel_crtc->config.ips_enabled &&
> +           ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
> +            GAMMA_MODE_MODE_SPLIT)) {
> +               hsw_disable_ips(intel_crtc);
> +               reenable_ips = true;
> +       }
>
>         for (i = 0; i < 256; i++) {
>                 I915_WRITE(palreg + 4 * i,
> @@ -6372,6 +6436,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>                            (intel_crtc->lut_g[i] << 8) |
>                            intel_crtc->lut_b[i]);
>         }
> +
> +       if (reenable_ips)
> +               hsw_enable_ips(intel_crtc);
>  }
>
>  static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
> @@ -8083,6 +8150,8 @@ intel_pipe_config_compare(struct drm_device *dev,
>         PIPE_CONF_CHECK_I(pch_pfit.pos);
>         PIPE_CONF_CHECK_I(pch_pfit.size);
>
> +       PIPE_CONF_CHECK_I(ips_enabled);
> +
>  #undef PIPE_CONF_CHECK_I
>  #undef PIPE_CONF_CHECK_FLAGS
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 57de0c1..2045974 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -268,6 +268,8 @@ struct intel_crtc_config {
>         /* FDI configuration, only valid if has_pch_encoder is set. */
>         int fdi_lanes;
>         struct intel_link_m_n fdi_m_n;
> +
> +       bool ips_enabled;
>  };
>
>  struct intel_crtc {
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry
  2013-05-13 19:00 ` [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry Paulo Zanoni
  2013-05-14 17:59   ` Rodrigo Vivi
@ 2013-05-31 16:08   ` Rodrigo Vivi
  1 sibling, 0 replies; 16+ messages in thread
From: Rodrigo Vivi @ 2013-05-31 16:08 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>

On Mon, May 13, 2013 at 4:00 PM, Paulo Zanoni <przanoni@gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
>
> It just prints whether it's supported/enabled/disabled. Feature
> requested by the power management team.
>
> Requested-by: Kristen Accardi <kristen.c.accardi@intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |   20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index a55630a..382ba64 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1311,6 +1311,25 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
>         return 0;
>  }
>
> +static int i915_ips_status(struct seq_file *m, void *unused)
> +{
> +       struct drm_info_node *node = (struct drm_info_node *) m->private;
> +       struct drm_device *dev = node->minor->dev;
> +       struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +       if (!IS_ULT(dev)) {
> +               seq_printf(m, "not supported\n");
> +               return 0;
> +       }
> +
> +       if (I915_READ(IPS_CTL) & IPS_ENABLE)
> +               seq_printf(m, "enabled\n");
> +       else
> +               seq_printf(m, "disabled\n");
> +
> +       return 0;
> +}
> +
>  static int i915_sr_status(struct seq_file *m, void *unused)
>  {
>         struct drm_info_node *node = (struct drm_info_node *) m->private;
> @@ -2108,6 +2127,7 @@ static struct drm_info_list i915_debugfs_list[] = {
>         {"i915_ring_freq_table", i915_ring_freq_table, 0},
>         {"i915_gfxec", i915_gfxec, 0},
>         {"i915_fbc_status", i915_fbc_status, 0},
> +       {"i915_ips_status", i915_ips_status, 0},
>         {"i915_sr_status", i915_sr_status, 0},
>         {"i915_opregion", i915_opregion, 0},
>         {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
> --
> 1.7.10.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

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

* Re: [PATCH 1/3] drm/i915: implement IPS feature
  2013-05-23 21:26       ` Paulo Zanoni
  2013-05-31 16:07         ` Rodrigo Vivi
@ 2013-05-31 16:30         ` Daniel Vetter
  1 sibling, 0 replies; 16+ messages in thread
From: Daniel Vetter @ 2013-05-31 16:30 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: intel-gfx, Paulo Zanoni

On Thu, May 23, 2013 at 06:26:28PM -0300, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Intermediate Pixel Storage is a feature that should reduce the number
> of times the display engine wakes up memory to read pixels, so it
> should allow deeper PC states. IPS can only be enabled on ULT pipe A
> with 8:8:8 pipe pixel formats.
> 
> With eDP 1920x1080 and correct watermarks but without FBC this moves
> my PC7 residency from 2.5% to around 38%.
> 
> v2: - It's tied to pipe A, not port A
>     - Add pipe_config support (Chris)
>     - Add some assertions (Chris)
>     - Rebase against latest dinq
> v3: - Don't ever set ips_enabled to false (Daniel)
>     - Only check for ips_enabled at hsw_disable_ips (Daniel)
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h      | 11 ++++++
>  drivers/gpu/drm/i915/intel_display.c | 73 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h     |  2 +
>  3 files changed, 84 insertions(+), 2 deletions(-)
> 
> 
> The workaround we implement is called WANoName. What's the correct way to
> proceed for WANoName?
> 
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 58230ea..5db20dc 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -977,6 +977,8 @@
>  /* Framebuffer compression for Ivybridge */
>  #define IVB_FBC_RT_BASE			0x7020
>  
> +#define IPS_CTL		0x43408
> +#define   IPS_ENABLE	(1 << 31)
>  
>  #define _HSW_PIPE_SLICE_CHICKEN_1_A	0x420B0
>  #define _HSW_PIPE_SLICE_CHICKEN_1_B	0x420B4
> @@ -3620,6 +3622,15 @@
>  #define _LGC_PALETTE_B           0x4a800
>  #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
>  
> +#define _GAMMA_MODE_A		0x4a480
> +#define _GAMMA_MODE_B		0x4ac80
> +#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
> +#define GAMMA_MODE_MODE_MASK	(3 << 0)
> +#define GAMMA_MODE_MODE_8bit	(0 << 0)
> +#define GAMMA_MODE_MODE_10bit	(1 << 0)
> +#define GAMMA_MODE_MODE_12bit	(2 << 0)
> +#define GAMMA_MODE_MODE_SPLIT	(3 << 0)
> +
>  /* interrupts */
>  #define DE_MASTER_IRQ_CONTROL   (1 << 31)
>  #define DE_SPRITEB_FLIP_DONE    (1 << 29)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 1c0d6d3..bc99183 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3340,6 +3340,51 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  	intel_wait_for_vblank(dev, intel_crtc->pipe);
>  }
>  
> +/* IPS only exists on ULT machines and is tied to pipe A. */
> +static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
> +{
> +	return (IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A);
> +}
> +
> +static void hsw_enable_ips(struct intel_crtc *crtc)
> +{
> +	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> +
> +	if (!hsw_crtc_supports_ips(crtc))
> +		return;
> +
> +	if (crtc->config.pipe_bpp != 24)
> +		return;
> +
> +	DRM_DEBUG_KMS("Enabling IPS\n");
> +
> +	crtc->config.ips_enabled = true;

Oops, I've found another one.

The general rule (there are some violations due to in-progress conversion)
is that the pipe_config should _never_ be changed in the ->mode_set and
->enable hooks. Instead it should be completely pre-calculated in the
compute_config stage. So can you please move the above code into a
haswell_compute_ips function and call it with a IS_HASWELL check from
ironlake_fdi_compute_config (maybe at the end where we compute the fdi
config)?

You can also dump the debug output and move that into dump_pipe_config.

The reason for that strict separation is that in the end I want to use the
pipe_config to decide about the different ways we can do modesets like:
- full enable/disable sequence
- fastboot for special cases + some fixups
- just an fb update
If not everything is pre-computed we'll have to deal with even more
special cases for this.

Cheers, Daniel

> +
> +	/* We can only enable IPS after we enable a plane and wait for a vblank.
> +	 * We guarantee that the plane is enabled by calling intel_enable_ips
> +	 * only after intel_enable_plane. And intel_enable_plane already waits
> +	 * for a vblank, so all we need to do here is to enable the IPS bit. */
> +	assert_plane_enabled(dev_priv, crtc->plane);
> +	I915_WRITE(IPS_CTL, IPS_ENABLE);
> +}
> +
> +static void hsw_disable_ips(struct intel_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (!crtc->config.ips_enabled)
> +		return;
> +
> +	DRM_DEBUG_KMS("Disabling IPS\n");
> +
> +	assert_plane_enabled(dev_priv, crtc->plane);
> +	I915_WRITE(IPS_CTL, 0);
> +
> +	/* We need to wait for a vblank before we can disable the plane. */
> +	intel_wait_for_vblank(dev, crtc->pipe);
> +}
> +
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> @@ -3387,6 +3432,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  			  intel_crtc->config.has_pch_encoder);
>  	intel_enable_plane(dev_priv, plane, pipe);
>  
> +	hsw_enable_ips(intel_crtc);
> +
>  	if (intel_crtc->config.has_pch_encoder)
>  		lpt_pch_enable(crtc);
>  
> @@ -3529,6 +3576,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>  	if (dev_priv->cfb_plane == plane)
>  		intel_disable_fbc(dev);
>  
> +	hsw_disable_ips(intel_crtc);
> +
>  	intel_disable_plane(dev_priv, plane, pipe);
>  
>  	if (intel_crtc->config.has_pch_encoder)
> @@ -6051,6 +6100,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>  	if (intel_display_power_enabled(dev, pfit_domain))
>  		ironlake_get_pfit_config(crtc, pipe_config);
>  
> +	pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
> +				   (I915_READ(IPS_CTL) & IPS_ENABLE);
> +
>  	return true;
>  }
>  
> @@ -6355,8 +6407,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	int palreg = PALETTE(intel_crtc->pipe);
> +	enum pipe pipe = intel_crtc->pipe;
> +	int palreg = PALETTE(pipe);
>  	int i;
> +	bool reenable_ips = false;
>  
>  	/* The clocks have to be on to load the palette. */
>  	if (!crtc->enabled || !intel_crtc->active)
> @@ -6364,7 +6418,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  
>  	/* use legacy palette for Ironlake */
>  	if (HAS_PCH_SPLIT(dev))
> -		palreg = LGC_PALETTE(intel_crtc->pipe);
> +		palreg = LGC_PALETTE(pipe);
> +
> +	/* Workaround : Do not read or write the pipe palette/gamma data while
> +	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
> +	 */
> +	if (intel_crtc->config.ips_enabled &&
> +	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
> +	     GAMMA_MODE_MODE_SPLIT)) {
> +		hsw_disable_ips(intel_crtc);
> +		reenable_ips = true;
> +	}
>  
>  	for (i = 0; i < 256; i++) {
>  		I915_WRITE(palreg + 4 * i,
> @@ -6372,6 +6436,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
>  			   (intel_crtc->lut_g[i] << 8) |
>  			   intel_crtc->lut_b[i]);
>  	}
> +
> +	if (reenable_ips)
> +		hsw_enable_ips(intel_crtc);
>  }
>  
>  static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
> @@ -8083,6 +8150,8 @@ intel_pipe_config_compare(struct drm_device *dev,
>  	PIPE_CONF_CHECK_I(pch_pfit.pos);
>  	PIPE_CONF_CHECK_I(pch_pfit.size);
>  
> +	PIPE_CONF_CHECK_I(ips_enabled);
> +
>  #undef PIPE_CONF_CHECK_I
>  #undef PIPE_CONF_CHECK_FLAGS
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 57de0c1..2045974 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -268,6 +268,8 @@ struct intel_crtc_config {
>  	/* FDI configuration, only valid if has_pch_encoder is set. */
>  	int fdi_lanes;
>  	struct intel_link_m_n fdi_m_n;
> +
> +	bool ips_enabled;
>  };
>  
>  struct intel_crtc {
> -- 
> 1.8.1.2
> 
> _______________________________________________
> 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] 16+ messages in thread

* [PATCH 1/3] drm/i915: implement IPS feature
@ 2013-05-31 19:33 Paulo Zanoni
  0 siblings, 0 replies; 16+ messages in thread
From: Paulo Zanoni @ 2013-05-31 19:33 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Intermediate Pixel Storage is a feature that should reduce the number
of times the display engine wakes up memory to read pixels, so it
should allow deeper PC states. IPS can only be enabled on ULT pipe A
with 8:8:8 pipe pixel formats.

With eDP 1920x1080 and correct watermarks but without FBC this moves
my PC7 residency from 2.5% to around 38%.

v2: - It's tied to pipe A, not port A
    - Add pipe_config support (Chris)
    - Add some assertions (Chris)
    - Rebase against latest dinq
v3: - Don't ever set ips_enabled to false (Daniel)
    - Only check for ips_enabled at hsw_disable_ips (Daniel)
v4: - Add hsw_compute_ips_config (Daniel)
    - Use the new dump_pipe_config (Daniel)

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      | 11 +++++
 drivers/gpu/drm/i915/intel_display.c | 78 ++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_drv.h     |  2 +
 3 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e004221..5ab0e31 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1020,6 +1020,8 @@
 /* Framebuffer compression for Ivybridge */
 #define IVB_FBC_RT_BASE			0x7020
 
+#define IPS_CTL		0x43408
+#define   IPS_ENABLE	(1 << 31)
 
 #define _HSW_PIPE_SLICE_CHICKEN_1_A	0x420B0
 #define _HSW_PIPE_SLICE_CHICKEN_1_B	0x420B4
@@ -3663,6 +3665,15 @@
 #define _LGC_PALETTE_B           0x4a800
 #define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
 
+#define _GAMMA_MODE_A		0x4a480
+#define _GAMMA_MODE_B		0x4ac80
+#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
+#define GAMMA_MODE_MODE_MASK	(3 << 0)
+#define GAMMA_MODE_MODE_8bit	(0 << 0)
+#define GAMMA_MODE_MODE_10bit	(1 << 0)
+#define GAMMA_MODE_MODE_12bit	(2 << 0)
+#define GAMMA_MODE_MODE_SPLIT	(3 << 0)
+
 /* interrupts */
 #define DE_MASTER_IRQ_CONTROL   (1 << 31)
 #define DE_SPRITEB_FLIP_DONE    (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 648049a..5ca8fe8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3247,6 +3247,42 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+/* IPS only exists on ULT machines and is tied to pipe A. */
+static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
+{
+	return IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A;
+}
+
+static void hsw_enable_ips(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (!crtc->config.ips_enabled)
+		return;
+
+	/* We can only enable IPS after we enable a plane and wait for a vblank.
+	 * We guarantee that the plane is enabled by calling intel_enable_ips
+	 * only after intel_enable_plane. And intel_enable_plane already waits
+	 * for a vblank, so all we need to do here is to enable the IPS bit. */
+	assert_plane_enabled(dev_priv, crtc->plane);
+	I915_WRITE(IPS_CTL, IPS_ENABLE);
+}
+
+static void hsw_disable_ips(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!crtc->config.ips_enabled)
+		return;
+
+	assert_plane_enabled(dev_priv, crtc->plane);
+	I915_WRITE(IPS_CTL, 0);
+
+	/* We need to wait for a vblank before we can disable the plane. */
+	intel_wait_for_vblank(dev, crtc->pipe);
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3294,6 +3330,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 			  intel_crtc->config.has_pch_encoder);
 	intel_enable_plane(dev_priv, plane, pipe);
 
+	hsw_enable_ips(intel_crtc);
+
 	if (intel_crtc->config.has_pch_encoder)
 		lpt_pch_enable(crtc);
 
@@ -3436,6 +3474,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	if (dev_priv->cfb_plane == plane)
 		intel_disable_fbc(dev);
 
+	hsw_disable_ips(intel_crtc);
+
 	intel_disable_plane(dev_priv, plane, pipe);
 
 	if (intel_crtc->config.has_pch_encoder)
@@ -3996,11 +4036,19 @@ retry:
 	return setup_ok ? 0 : -EINVAL;
 }
 
+static void hsw_compute_ips_config(struct intel_crtc *crtc,
+				   struct intel_crtc_config *pipe_config)
+{
+	pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
+				   pipe_config->pipe_bpp == 24;
+}
+
 static int intel_crtc_compute_config(struct drm_crtc *crtc,
 				     struct intel_crtc_config *pipe_config)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
 	if (HAS_PCH_SPLIT(dev)) {
 		/* FDI link clock is fixed at 2.7G */
@@ -4030,8 +4078,11 @@ static int intel_crtc_compute_config(struct drm_crtc *crtc,
 		pipe_config->pipe_bpp = 8*3;
 	}
 
+	if (IS_HASWELL(dev))
+		hsw_compute_ips_config(intel_crtc, pipe_config);
+
 	if (pipe_config->has_pch_encoder)
-		return ironlake_fdi_compute_config(to_intel_crtc(crtc), pipe_config);
+		return ironlake_fdi_compute_config(intel_crtc, pipe_config);
 
 	return 0;
 }
@@ -5937,6 +5988,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 	if (intel_display_power_enabled(dev, pfit_domain))
 		ironlake_get_pfit_config(crtc, pipe_config);
 
+	pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
+				   (I915_READ(IPS_CTL) & IPS_ENABLE);
+
 	return true;
 }
 
@@ -6241,8 +6295,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int palreg = PALETTE(intel_crtc->pipe);
+	enum pipe pipe = intel_crtc->pipe;
+	int palreg = PALETTE(pipe);
 	int i;
+	bool reenable_ips = false;
 
 	/* The clocks have to be on to load the palette. */
 	if (!crtc->enabled || !intel_crtc->active)
@@ -6250,7 +6306,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 
 	/* use legacy palette for Ironlake */
 	if (HAS_PCH_SPLIT(dev))
-		palreg = LGC_PALETTE(intel_crtc->pipe);
+		palreg = LGC_PALETTE(pipe);
+
+	/* Workaround : Do not read or write the pipe palette/gamma data while
+	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+	 */
+	if (intel_crtc->config.ips_enabled &&
+	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
+	     GAMMA_MODE_MODE_SPLIT)) {
+		hsw_disable_ips(intel_crtc);
+		reenable_ips = true;
+	}
 
 	for (i = 0; i < 256; i++) {
 		I915_WRITE(palreg + 4 * i,
@@ -6258,6 +6324,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 			   (intel_crtc->lut_g[i] << 8) |
 			   intel_crtc->lut_b[i]);
 	}
+
+	if (reenable_ips)
+		hsw_enable_ips(intel_crtc);
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
@@ -7685,6 +7754,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 	DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
 		      pipe_config->pch_pfit.pos,
 		      pipe_config->pch_pfit.size);
+	DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
 }
 
 static struct intel_crtc_config *
@@ -8001,6 +8071,8 @@ intel_pipe_config_compare(struct drm_device *dev,
 	PIPE_CONF_CHECK_I(pch_pfit.pos);
 	PIPE_CONF_CHECK_I(pch_pfit.size);
 
+	PIPE_CONF_CHECK_I(ips_enabled);
+
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_FLAGS
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bb4c50b..fdf6303 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -268,6 +268,8 @@ struct intel_crtc_config {
 	/* FDI configuration, only valid if has_pch_encoder is set. */
 	int fdi_lanes;
 	struct intel_link_m_n fdi_m_n;
+
+	bool ips_enabled;
 };
 
 struct intel_crtc {
-- 
1.8.1.2

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

end of thread, other threads:[~2013-05-31 19:33 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-13 19:00 [PATCH 1/3] drm/i915: implement IPS feature Paulo Zanoni
2013-05-13 19:00 ` [PATCH 2/3] drm/i915: add enable_ips module option Paulo Zanoni
2013-05-16 19:56   ` Paulo Zanoni
2013-05-31 16:04     ` Rodrigo Vivi
2013-05-13 19:00 ` [PATCH 3/3] drm/i915: add i915_ips_status debugfs entry Paulo Zanoni
2013-05-14 17:59   ` Rodrigo Vivi
2013-05-14 17:59     ` Rodrigo Vivi
2013-05-31 16:08   ` Rodrigo Vivi
2013-05-15  7:54 ` [PATCH 1/3] drm/i915: implement IPS feature Chris Wilson
2013-05-16 19:54   ` Paulo Zanoni
2013-05-18  3:18     ` Rodrigo Vivi
2013-05-21  8:41     ` Daniel Vetter
2013-05-23 21:26       ` Paulo Zanoni
2013-05-31 16:07         ` Rodrigo Vivi
2013-05-31 16:30         ` Daniel Vetter
2013-05-31 19:33 Paulo Zanoni

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