Re: [Intel-gfx] [PATCH 1/3] drm/i915: implement IPS feature

2013-05-15 Thread Chris Wilson
On Mon, May 13, 2013 at 04:00:08PM -0300, Paulo Zanoni wrote:
 From: Paulo Zanoni paulo.r.zan...@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 * 

[Intel-gfx] [RFC PATCH 0/3] vlv sideband refactoring

2013-05-15 Thread Jani Nikula
Okay, I'm stuck with this a bit, and whichever approach I choose I
expect there to be a bunch of bikeshedding. So I won't polish this
further before comments.

Both the intel_dpio_{read,write} and valleyview_{punit,nc}_{read,write}
use the IOSF sideband interface. They access the same registers and do
mostly the same stuff, but no shared code. There are even duplicate
register defines for the same registers. Both have locking, but the
former use dpio_lock and the latter rps.hw_lock. It's racy.

These patches refactor the sideband access to a single function that
expects dpio_lock to be held. The dpio_lock is only used for sideband
stuff, so it's a better match than rps.hw_lock for the purpose. The rps
stuff still needs rps.hw_lock, since it's used to protect more than just
the register access, so rps code will need to hold both locks.

The bikeshedding department:

1) Do we need to propagate sideband errors from the functions (like the
   valleyview_punit_* functions do), or, since the return values are
   never checked anywhere anyway, can we just convert to the
   intel_dpio_* style (functions return the register value only) for all
   of them?

2) There will be quite a few more ports. Add new wrappers for each of
   them, or create generic read/write functions that need a port
   argument?

3) Should the rps stuff take dpio_lock at a higher level than the
   wrappers? This is pretty much a requirement for the generic r/w
   function.

4) Does dpio really need a devfn different from the rest?

5) Your additional bikeshedding here. ;)


Cheers,
Jani.


Jani Nikula (3):
  drm/i915: group vlv iosf sideband register accessors to a new file
  drm/i915: refactor all vlv sideband accessors to use one helper
  drm/i915: drop redundant warnings on not holding dpio_lock

 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/i915_reg.h   |   93 -
 drivers/gpu/drm/i915/intel_display.c  |   37 --
 drivers/gpu/drm/i915/intel_dp.c   |6 --
 drivers/gpu/drm/i915/intel_hdmi.c |4 --
 drivers/gpu/drm/i915/intel_pm.c   |   60 
 drivers/gpu/drm/i915/intel_sideband.c |  121 +
 7 files changed, 165 insertions(+), 157 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_sideband.c

-- 
1.7.10.4

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


[Intel-gfx] [RFC PATCH 1/3] drm/i915: group vlv iosf sideband register accessors to a new file

2013-05-15 Thread Jani Nikula
No functional changes.

Signed-off-by: Jani Nikula jani.nik...@intel.com
---
 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/intel_display.c  |   37 --
 drivers/gpu/drm/i915/intel_pm.c   |   60 
 drivers/gpu/drm/i915/intel_sideband.c |  123 +
 4 files changed, 124 insertions(+), 97 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_sideband.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 91f3ac6..40034ec 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -36,6 +36,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
  intel_overlay.o \
  intel_sprite.o \
  intel_opregion.o \
+ intel_sideband.o \
  dvo_ch7xxx.o \
  dvo_ch7017.o \
  dvo_ivch.o \
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 7358e4e..39af0e2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -381,43 +381,6 @@ static const intel_limit_t intel_limits_vlv_dp = {
.find_pll = intel_vlv_find_best_pll,
 };
 
-u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
-{
-   WARN_ON(!mutex_is_locked(dev_priv-dpio_lock));
-
-   if (wait_for_atomic_us((I915_READ(DPIO_PKT)  DPIO_BUSY) == 0, 100)) {
-   DRM_ERROR(DPIO idle wait timed out\n);
-   return 0;
-   }
-
-   I915_WRITE(DPIO_REG, reg);
-   I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_READ | DPIO_PORTID |
-  DPIO_BYTE);
-   if (wait_for_atomic_us((I915_READ(DPIO_PKT)  DPIO_BUSY) == 0, 100)) {
-   DRM_ERROR(DPIO read wait timed out\n);
-   return 0;
-   }
-
-   return I915_READ(DPIO_DATA);
-}
-
-void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val)
-{
-   WARN_ON(!mutex_is_locked(dev_priv-dpio_lock));
-
-   if (wait_for_atomic_us((I915_READ(DPIO_PKT)  DPIO_BUSY) == 0, 100)) {
-   DRM_ERROR(DPIO idle wait timed out\n);
-   return;
-   }
-
-   I915_WRITE(DPIO_DATA, val);
-   I915_WRITE(DPIO_REG, reg);
-   I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID |
-  DPIO_BYTE);
-   if (wait_for_atomic_us((I915_READ(DPIO_PKT)  DPIO_BUSY) == 0, 100))
-   DRM_ERROR(DPIO write wait timed out\n);
-}
-
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
int refclk)
 {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 1a76572..a06118d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4952,66 +4952,6 @@ int sandybridge_pcode_write(struct drm_i915_private 
*dev_priv, u8 mbox, u32 val)
return 0;
 }
 
-static int vlv_punit_rw(struct drm_i915_private *dev_priv, u32 port, u8 opcode,
-   u8 addr, u32 *val)
-{
-   u32 cmd, devfn, be, bar;
-
-   bar = 0;
-   be = 0xf;
-   devfn = PCI_DEVFN(2, 0);
-
-   cmd = (devfn  IOSF_DEVFN_SHIFT) | (opcode  IOSF_OPCODE_SHIFT) |
-   (port  IOSF_PORT_SHIFT) | (be  IOSF_BYTE_ENABLES_SHIFT) |
-   (bar  IOSF_BAR_SHIFT);
-
-   WARN_ON(!mutex_is_locked(dev_priv-rps.hw_lock));
-
-   if (I915_READ(VLV_IOSF_DOORBELL_REQ)  IOSF_SB_BUSY) {
-   DRM_DEBUG_DRIVER(warning: pcode (%s) mailbox access failed\n,
-opcode == PUNIT_OPCODE_REG_READ ?
-read : write);
-   return -EAGAIN;
-   }
-
-   I915_WRITE(VLV_IOSF_ADDR, addr);
-   if (opcode == PUNIT_OPCODE_REG_WRITE)
-   I915_WRITE(VLV_IOSF_DATA, *val);
-   I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd);
-
-   if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ)  IOSF_SB_BUSY) == 0,
-5)) {
-   DRM_ERROR(timeout waiting for pcode %s (%d) to finish\n,
- opcode == PUNIT_OPCODE_REG_READ ? read : write,
- addr);
-   return -ETIMEDOUT;
-   }
-
-   if (opcode == PUNIT_OPCODE_REG_READ)
-   *val = I915_READ(VLV_IOSF_DATA);
-   I915_WRITE(VLV_IOSF_DATA, 0);
-
-   return 0;
-}
-
-int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val)
-{
-   return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_READ,
-   addr, val);
-}
-
-int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val)
-{
-   return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_WRITE,
-   addr, val);
-}
-
-int valleyview_nc_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val)
-{
-   return vlv_punit_rw(dev_priv, IOSF_PORT_NC, PUNIT_OPCODE_REG_READ,
-   addr, val);
-}
-
 int vlv_gpu_freq(int ddr_freq, 

[Intel-gfx] [RFC PATCH 3/3] drm/i915: drop redundant warnings on not holding dpio_lock

2013-05-15 Thread Jani Nikula
The lower level sideband read/write functions already do this.

Signed-off-by: Jani Nikula jani.nik...@intel.com
---
 drivers/gpu/drm/i915/intel_dp.c   |6 --
 drivers/gpu/drm/i915/intel_hdmi.c |4 
 2 files changed, 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2bb4009..12d5c18 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1428,8 +1428,6 @@ static void intel_pre_enable_dp(struct intel_encoder 
*encoder)
int pipe = intel_crtc-pipe;
u32 val;
 
-   WARN_ON(!mutex_is_locked(dev_priv-dpio_lock));
-
val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
val = 0;
if (pipe)
@@ -1456,8 +1454,6 @@ static void intel_dp_pre_pll_enable(struct intel_encoder 
*encoder)
if (!IS_VALLEYVIEW(dev))
return;
 
-   WARN_ON(!mutex_is_locked(dev_priv-dpio_lock));
-
/* Program Tx lane resets to default */
intel_dpio_write(dev_priv, DPIO_PCS_TX(port),
 DPIO_PCS_TX_LANE2_RESET |
@@ -1608,8 +1604,6 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp 
*intel_dp)
uint8_t train_set = intel_dp-train_set[0];
int port = vlv_dport_to_channel(dport);
 
-   WARN_ON(!mutex_is_locked(dev_priv-dpio_lock));
-
switch (train_set  DP_TRAIN_PRE_EMPHASIS_MASK) {
case DP_TRAIN_PRE_EMPHASIS_0:
preemph_reg_value = 0x0004000;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 93de5ff..9562fe4 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -988,8 +988,6 @@ static void intel_hdmi_pre_enable(struct intel_encoder 
*encoder)
if (!IS_VALLEYVIEW(dev))
return;
 
-   WARN_ON(!mutex_is_locked(dev_priv-dpio_lock));
-
/* Enable clock channels for this port */
val = intel_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
val = 0;
@@ -1033,8 +1031,6 @@ static void intel_hdmi_pre_pll_enable(struct 
intel_encoder *encoder)
if (!IS_VALLEYVIEW(dev))
return;
 
-   WARN_ON(!mutex_is_locked(dev_priv-dpio_lock));
-
/* Program Tx lane resets to default */
intel_dpio_write(dev_priv, DPIO_PCS_TX(port),
 DPIO_PCS_TX_LANE2_RESET |
-- 
1.7.10.4

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


[Intel-gfx] [RFC PATCH 2/3] drm/i915: refactor all vlv sideband accessors to use one helper

2013-05-15 Thread Jani Nikula
Based on work by Shobhit Kumar shobhit.ku...@intel.com and
Yogesh Mohan Marimuthu yogesh.mohan.marimu...@intel.com

Signed-off-by: Jani Nikula jani.nik...@intel.com
---
 drivers/gpu/drm/i915/i915_reg.h   |   93 ++
 drivers/gpu/drm/i915/intel_sideband.c |  102 -
 2 files changed, 93 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7af7ae6..fcee92b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -344,27 +344,54 @@
 #define  DEBUG_RESET_DISPLAY   (19)
 
 /*
- * DPIO - a special bus for various display related registers to hide behind:
- *  0x800c: m1, m2, n, p1, p2, k dividers
- *  0x8014: REF and SFR select
- *  0x8014: N divider, VCO select
- *  0x801c/3c: core clock bits
- *  0x8048/68: low pass filter coefficients
- *  0x8100: fast clock controls
+ * IOSF sideband
+ */
+#define VLV_IOSF_DOORBELL_REQ  (VLV_DISPLAY_BASE + 0x2100)
+#define   IOSF_DEVFN_SHIFT 24
+#define   IOSF_OPCODE_SHIFT16
+#define   IOSF_PORT_SHIFT  8
+#define   IOSF_BYTE_ENABLES_SHIFT  4
+#define   IOSF_BAR_SHIFT   1
+#define   IOSF_SB_BUSY (10)
+#define   IOSF_PORT_PUNIT  0x4
+#define   IOSF_PORT_NC 0x11
+#define   IOSF_PORT_DPIO   0x12
+#define VLV_IOSF_DATA  (VLV_DISPLAY_BASE + 0x2104)
+#define VLV_IOSF_ADDR  (VLV_DISPLAY_BASE + 0x2108)
+
+#define PUNIT_OPCODE_REG_READ  6
+#define PUNIT_OPCODE_REG_WRITE 7
+
+#define PUNIT_REG_GPU_LFM  0xd3
+#define PUNIT_REG_GPU_FREQ_REQ 0xd4
+#define PUNIT_REG_GPU_FREQ_STS 0xd8
+#define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc
+
+#define PUNIT_FUSE_BUS20xf6 /* bits 47:40 */
+#define PUNIT_FUSE_BUS10xf5 /* bits 55:48 */
+
+#define IOSF_NC_FB_GFX_FREQ_FUSE   0x1c
+#define   FB_GFX_MAX_FREQ_FUSE_SHIFT   3
+#define   FB_GFX_MAX_FREQ_FUSE_MASK0x07f8
+#define   FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT   11
+#define   FB_GFX_FGUARANTEED_FREQ_FUSE_MASK0x0007f800
+#define IOSF_NC_FB_GFX_FMAX_FUSE_HI0x34
+#define   FB_FMAX_VMIN_FREQ_HI_MASK0x0007
+#define IOSF_NC_FB_GFX_FMAX_FUSE_LO0x30
+#define   FB_FMAX_VMIN_FREQ_LO_SHIFT   27
+#define   FB_FMAX_VMIN_FREQ_LO_MASK0xf800
+
+/*
+ * DPIO - a special bus for various display related registers to hide behind
  *
  * DPIO is VLV only.
  *
  * Note: digital port B is DDI0, digital pot C is DDI1
  */
-#define DPIO_PKT   (VLV_DISPLAY_BASE + 0x2100)
-#define  DPIO_RID  (024)
-#define  DPIO_OP_WRITE (116)
-#define  DPIO_OP_READ  (016)
-#define  DPIO_PORTID   (0x128)
-#define  DPIO_BYTE (0xf4)
-#define  DPIO_BUSY (10) /* status only */
-#define DPIO_DATA  (VLV_DISPLAY_BASE + 0x2104)
-#define DPIO_REG   (VLV_DISPLAY_BASE + 0x2108)
+#define DPIO_DEVFN 0
+#define DPIO_OPCODE_REG_WRITE  1
+#define DPIO_OPCODE_REG_READ   0
+
 #define DPIO_CTL   (VLV_DISPLAY_BASE + 0x2110)
 #define  DPIO_MODSEL1  (13) /* if ref clk b == 27 */
 #define  DPIO_MODSEL0  (12) /* if ref clk a == 27 */
@@ -4541,40 +4568,6 @@
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT   8
 #define   GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16
 
-#define VLV_IOSF_DOORBELL_REQ  0x182100
-#define   IOSF_DEVFN_SHIFT 24
-#define   IOSF_OPCODE_SHIFT16
-#define   IOSF_PORT_SHIFT  8
-#define   IOSF_BYTE_ENABLES_SHIFT  4
-#define   IOSF_BAR_SHIFT   1
-#define   IOSF_SB_BUSY (10)
-#define   IOSF_PORT_PUNIT  0x4
-#define   IOSF_PORT_NC 0x11
-#define VLV_IOSF_DATA  0x182104
-#define VLV_IOSF_ADDR  0x182108
-
-#define PUNIT_OPCODE_REG_READ  6
-#define PUNIT_OPCODE_REG_WRITE 7
-
-#define PUNIT_REG_GPU_LFM  0xd3
-#define PUNIT_REG_GPU_FREQ_REQ 0xd4
-#define PUNIT_REG_GPU_FREQ_STS 0xd8
-#define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc
-
-#define PUNIT_FUSE_BUS20xf6 /* bits 47:40 */
-#define PUNIT_FUSE_BUS10xf5 /* bits 55:48 */
-
-#define IOSF_NC_FB_GFX_FREQ_FUSE   0x1c
-#define   FB_GFX_MAX_FREQ_FUSE_SHIFT   3
-#define   

Re: [Intel-gfx] debugging Haswell eDP black screen after S3

2013-05-15 Thread Ben Guthro
On Tue, May 14, 2013 at 5:01 PM, Ben Guthro b...@guthro.net wrote:
 I am attempting to debug an issue with some Haswell laptop systems
 which do not restore their screen after resuming from S3 when running
 on the stable 3.8 kernel (3.8.13)
 The backlight is OK, but the screen is just black.

 In trying to determine what was going wrong, I tried looking at the
 output of intel_reg_dumper, in a good, and bad case:

 diff -u good_reg.txt bad_reg.txt
 --- good_reg.txt2013-05-14 15:08:44.361997000 +
 +++ bad_reg.txt 2013-05-14 15:09:20.48000 +
 @@ -1,5 +1,4 @@
 - DCC: 0x (0xf340
 0xf37f 0x��
 -� )
 + DCC: 0x (0xf340
 0xf37f 0x��= � )
 CHDECMISC: 0x (none, ch2 enh disabled, ch1 enh
 disabled, ch0 enh disabled, flex disabled, ep not present)
C0DRB0: 0x (0x)
C0DRB1: 0x (0x)
 @@ -63,17 +62,17 @@
   PIPEA_DP_LINK_N: 0x
 CURSOR_A_BASE: 0x01061000
  CURSOR_A_CONTROL: 0x0427
 -   CURSOR_A_POSITION: 0x03a3032f
 +   CURSOR_A_POSITION: 0x01bb03fb
  FPA0: 0x (n = 0, m1 = 0, m2 = 0)
  FPA1: 0x (n = 0, m1 = 0, m2 = 0)
DPLL_A: 0x (disabled, non-dvo, VGA, default
 clock, unknown mode, p1 = 0, p2 = 0)
 DPLL_A_MD: 0x
 -HTOTAL_A: 0x0821077f (1920 active, 2082 total)
 -HBLANK_A: 0x0821077f (1920 start, 2082 end)
 - HSYNC_A: 0x081307af (1968 start, 2068 end)
 -VTOTAL_A: 0x045f0437 (1080 active, 1120 total)
 -VBLANK_A: 0x045f0437 (1080 start, 1120 end)
 - VSYNC_A: 0x044b0441 (1090 start, 1100 end)
 +HTOTAL_A: 0x (1 active, 1 total)
 +HBLANK_A: 0x (1 start, 1 end)
 + HSYNC_A: 0x (1 start, 1 end)
 +VTOTAL_A: 0x (1 active, 1 total)
 +VBLANK_A: 0x (1 start, 1 end)
 + VSYNC_A: 0x (1 start, 1 end)
 BCLRPAT_A: 0x
  VSYNCSHIFT_A: 0x
  DSPBCNTR: 0x4000 (disabled, pipe A)


 It appears the registers that are saved, and restored in
 i915_save_modeset_reg / i915_restore_modeset_reg is not working
 properly.

 When I put some debug in, I discovered that it was bailing out of
 i915_save_modeset_reg early since the DRIVER_MODESET bit was cleared.
 However, it was set at the end of i915_init()
 This, of course, confuses me.

 Am I seeing memory corruption here?

It looks like I misread the code here, inversing an if statement state.

That said, I don't really have any clues as to why the display is
black after resuming from S3

Is this an eDP training issue? Are there any changesets I can try backporting?
I tried this, but it didn't seem to help:
https://patchwork.kernel.org/patch/2516601/
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/6] drm/i915: add encoder get_config function v5

2013-05-15 Thread Paulo Zanoni
2013/5/14 Jesse Barnes jbar...@virtuousgeek.org:
 We can use this for fetching encoder specific pipe_config state, like
 mode flags, adjusted clock, etc.

 Just used for mode flags atm, so we can check the pipe config state at
 mode set time.

 v2: get_config when checking hw state too
 v3: fix DVO and LVDS mode flags (Ville)
 get SDVO DTD for flag fetch (Ville)
 v4: use input timings (Ville)
 correct command used (Ville)
 remove gen4 check (Ville)
 v5: get DDI flag config too

 Signed-off-by: Jesse Barnes jbar...@virtuousgeek.org
 Reviewed-by: Ville Syrjälä ville.syrj...@linux.intel.com
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

I applied this on my Haswell machine and booted it with both eDP-only
and eDP+DP and now I don't see those error messages anymore.


 ---
  drivers/gpu/drm/i915/intel_crt.c |   23 +++
  drivers/gpu/drm/i915/intel_ddi.c |   23 +++
  drivers/gpu/drm/i915/intel_display.c |   20 +---
  drivers/gpu/drm/i915/intel_dp.c  |   23 +++
  drivers/gpu/drm/i915/intel_drv.h |4 
  drivers/gpu/drm/i915/intel_dvo.c |   21 +
  drivers/gpu/drm/i915/intel_hdmi.c|   23 +++
  drivers/gpu/drm/i915/intel_lvds.c|   26 +
  drivers/gpu/drm/i915/intel_sdvo.c|   42 
 ++
  9 files changed, 202 insertions(+), 3 deletions(-)

 diff --git a/drivers/gpu/drm/i915/intel_crt.c 
 b/drivers/gpu/drm/i915/intel_crt.c
 index cc414f1..789c4ef 100644
 --- a/drivers/gpu/drm/i915/intel_crt.c
 +++ b/drivers/gpu/drm/i915/intel_crt.c
 @@ -81,6 +81,28 @@ static bool intel_crt_get_hw_state(struct intel_encoder 
 *encoder,
 return true;
  }

 +static void intel_crt_get_config(struct intel_encoder *encoder,
 +struct intel_crtc_config *pipe_config)
 +{
 +   struct drm_i915_private *dev_priv = encoder-base.dev-dev_private;
 +   struct intel_crt *crt = intel_encoder_to_crt(encoder);
 +   u32 tmp, flags = 0;
 +
 +   tmp = I915_READ(crt-adpa_reg);
 +
 +   if (tmp  ADPA_HSYNC_ACTIVE_HIGH)
 +   flags |= DRM_MODE_FLAG_PHSYNC;
 +   else
 +   flags |= DRM_MODE_FLAG_NHSYNC;
 +
 +   if (tmp  ADPA_VSYNC_ACTIVE_HIGH)
 +   flags |= DRM_MODE_FLAG_PVSYNC;
 +   else
 +   flags |= DRM_MODE_FLAG_NVSYNC;
 +
 +   pipe_config-adjusted_mode.flags |= flags;
 +}
 +
  static void intel_disable_crt(struct intel_encoder *encoder)
  {
 struct drm_i915_private *dev_priv = encoder-base.dev-dev_private;
 @@ -784,6 +806,7 @@ void intel_crt_init(struct drm_device *dev)
 crt-base.compute_config = intel_crt_compute_config;
 crt-base.disable = intel_disable_crt;
 crt-base.enable = intel_enable_crt;
 +   crt-base.get_config = intel_crt_get_config;
 if (I915_HAS_HOTPLUG(dev))
 crt-base.hpd_pin = HPD_CRT;
 if (HAS_DDI(dev))
 diff --git a/drivers/gpu/drm/i915/intel_ddi.c 
 b/drivers/gpu/drm/i915/intel_ddi.c
 index cddcf4a..27a74a9 100644
 --- a/drivers/gpu/drm/i915/intel_ddi.c
 +++ b/drivers/gpu/drm/i915/intel_ddi.c
 @@ -1254,6 +1254,28 @@ static void intel_ddi_hot_plug(struct intel_encoder 
 *intel_encoder)
 intel_dp_check_link_status(intel_dp);
  }

 +static void intel_ddi_get_config(struct intel_encoder *encoder,
 +struct intel_crtc_config *pipe_config)
 +{
 +   struct drm_i915_private *dev_priv = encoder-base.dev-dev_private;
 +   struct intel_crtc *intel_crtc = to_intel_crtc(encoder-base.crtc);
 +   enum transcoder cpu_transcoder = intel_crtc-config.cpu_transcoder;
 +   u32 temp, flags = 0;
 +
 +   temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
 +   if (temp  TRANS_DDI_PHSYNC)
 +   flags |= DRM_MODE_FLAG_PHSYNC;
 +   else
 +   flags |= DRM_MODE_FLAG_NHSYNC;
 +   if (temp  TRANS_DDI_PVSYNC)
 +   flags |= DRM_MODE_FLAG_PVSYNC;
 +   else
 +   flags |= DRM_MODE_FLAG_NVSYNC;
 +
 +   pipe_config-adjusted_mode.flags |= flags;
 +   pipe_config-pixel_multiplier = 1;
 +}
 +
  static void intel_ddi_destroy(struct drm_encoder *encoder)
  {
 /* HDMI has nothing special to destroy, so we can go with this. */
 @@ -1313,6 +1335,7 @@ void intel_ddi_init(struct drm_device *dev, enum port 
 port)
 intel_encoder-disable = intel_disable_ddi;
 intel_encoder-post_disable = intel_ddi_post_disable;
 intel_encoder-get_hw_state = intel_ddi_get_hw_state;
 +   intel_encoder-get_config = intel_ddi_get_config;

 intel_dig_port-port = port;
 intel_dig_port-port_reversal = I915_READ(DDI_BUF_CTL(port)) 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index 7358e4e..163b97e 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ 

Re: [Intel-gfx] [alsa-devel] [PATCH 1/2] drm/915: Add private api for power well usage

2013-05-15 Thread Wang, Xingchao
Hi Takashi,


 -Original Message-
 From: Takashi Iwai [mailto:ti...@suse.de]
 Sent: Tuesday, May 14, 2013 8:32 PM
 To: Wang Xingchao
 Cc: dan...@ffwll.ch; Girdwood, Liam R; alsa-de...@alsa-project.org; Zanoni,
 Paulo R; Li, Jocelyn; Lin, Mengdong; intel-gfx@lists.freedesktop.org; Wang,
 Xingchao; Barnes, Jesse; david.hennings...@canonical.com
 Subject: Re: [alsa-devel] [PATCH 1/2] drm/915: Add private api for power well
 usage
 
 At Tue, 14 May 2013 19:44:18 +0800,
 Wang Xingchao wrote:
 
  Haswell Display audio depends on power well in graphic side, it should
  request power well before use it and release power well after use.
  I915 will not shutdown power well if it detects audio is using.
  This patch protects display audio crash for Intel Haswell mobile
  C3 stepping board.
 
  Signed-off-by: Wang Xingchao xingchao.w...@linux.intel.com
  ---
   drivers/gpu/drm/i915/intel_pm.c |   76
 +++
   include/drm/i915_powerwell.h|   36 +++
   2 files changed, 105 insertions(+), 7 deletions(-)  create mode
  100644 include/drm/i915_powerwell.h
 
  diff --git a/drivers/gpu/drm/i915/intel_pm.c
  b/drivers/gpu/drm/i915/intel_pm.c index 0f4b46e..cf7e352 100644
  --- a/drivers/gpu/drm/i915/intel_pm.c
  +++ b/drivers/gpu/drm/i915/intel_pm.c
  @@ -4344,18 +4344,12 @@ bool intel_using_power_well(struct drm_device
 *dev)
  return true;
   }
 
  -void intel_set_power_well(struct drm_device *dev, bool enable)
  +static void enable_power_well(struct drm_device *dev, bool enable)
   {
  struct drm_i915_private *dev_priv = dev-dev_private;
  bool is_enabled, enable_requested;
  uint32_t tmp;
 
  -   if (!HAS_POWER_WELL(dev))
  -   return;
  -
  -   if (!i915_disable_power_well  !enable)
  -   return;
  -
  tmp = I915_READ(HSW_PWR_WELL_DRIVER);
  is_enabled = tmp  HSW_PWR_WELL_STATE;
  enable_requested = tmp  HSW_PWR_WELL_ENABLE; @@ -4378,6
 +4372,74 @@
  void intel_set_power_well(struct drm_device *dev, bool enable)
  }
   }
 
  +/* Global drm_device for display audio drvier usage */ static struct
  +drm_device *power_well_device;
  +/* Lock protecting power well setting */ static
  +DEFINE_SPINLOCK(powerwell_lock); static bool i915_power_well_using;
  +static int hsw_power_count;
  +
  +void i915_request_power_well(void)
  +{
  +   if (!power_well_device)
  +   return;
  +
  +   if (!IS_HASWELL(power_well_device))
  +   return;
  +
  +   spin_lock_irq(powerwell_lock);
  +   if (!hsw_power_count++) {
  +   enable_power_well(power_well_device, true);
  +   }
 
 Should be
   if (!hsw_power_count++  !i915_power_well_using)
   enable_power_well(power_well_device, true);

Fixed.

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


Re: [Intel-gfx] [PATCH 2/2] ALSA: hda - Add power-welll support for haswell HDA

2013-05-15 Thread Wang, Xingchao
Hi Takashi,

Thanks your quick feedback, please see my comments below.

 -Original Message-
 From: Takashi Iwai [mailto:ti...@suse.de]
 Sent: Tuesday, May 14, 2013 8:15 PM
 To: Wang Xingchao
 Cc: dan...@ffwll.ch; Girdwood, Liam R; david.hennings...@canonical.com; Lin,
 Mengdong; Li, Jocelyn; alsa-de...@alsa-project.org;
 intel-gfx@lists.freedesktop.org; Barnes, Jesse; Zanoni, Paulo R; Wang,
 Xingchao
 Subject: Re: [PATCH 2/2] ALSA: hda - Add power-welll support for haswell HDA
 
 At Tue, 14 May 2013 19:44:19 +0800,
 Wang Xingchao wrote:
 
  For Intel Haswell chip, HDA controller and codec have power well
  dependency from GPU side. This patch added support to request/release
  power well in audio driver. Power save feature should be enabled to
  get runtime power saving.
 
  Signed-off-by: Wang Xingchao xingchao.w...@linux.intel.com
  ---
   sound/pci/hda/Kconfig |8 
   sound/pci/hda/Makefile|3 ++
   sound/pci/hda/hda_i915.c  |   92
 +
   sound/pci/hda/hda_i915.h  |   35 +
   sound/pci/hda/hda_intel.c |   33 ++--
   5 files changed, 168 insertions(+), 3 deletions(-)  create mode
  100644 sound/pci/hda/hda_i915.c  create mode 100644
  sound/pci/hda/hda_i915.h
 
  diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index
  80a7d44..d9e71e4 100644
  --- a/sound/pci/hda/Kconfig
  +++ b/sound/pci/hda/Kconfig
  @@ -152,6 +152,14 @@ config SND_HDA_CODEC_HDMI
snd-hda-codec-hdmi.
This module is automatically loaded at probing.
 
  +config SND_HDA_I915
  +   bool Build Display HD-audio controller/codec power well support for 
  i915
 cards
  +   depends on DRM_I915
  +   default y
  +   help
  + Say Y here to include full HDMI and DisplayPort HD-audio
 controller/codec
  + support for Intel Haswell graphics cards based on the i915 driver.
 
 Do we need to make this selectable?
 If you have i915 driver, this can be always set.

Well, for Non-Haswell chips with SND_HDA_I915 compiled in, it do nothing as it 
has no  AZX_DCAPS_I915_POWERWELL set, so no power-well API called.
For Haswell chips, SND_HDA_I915 must be enabled otherwise display audio would 
fail. Anyway I added a note message in the choice to let
user know this option is a *must* one for Haswell chips.

 
 
   config SND_HDA_CODEC_CIRRUS
  bool Build Cirrus Logic codec support
  default y
  diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index
  24a2514..4b0a4bc 100644
  --- a/sound/pci/hda/Makefile
  +++ b/sound/pci/hda/Makefile
  @@ -6,6 +6,9 @@ snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
   snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
   snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
 
  +# for haswell power well
  +snd-hda-intel-$(CONFIG_SND_HDA_I915) +=hda_i915.o
  +
   # for trace-points
   CFLAGS_hda_codec.o := -I$(src)
   CFLAGS_hda_intel.o := -I$(src)
  diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c new
  file mode 100644 index 000..96ca9e7
  --- /dev/null
  +++ b/sound/pci/hda/hda_i915.c
  @@ -0,0 +1,92 @@
  +/*
  + *  hda_i915.c - routines for Haswell HDA controller power well
  +support
  + *
  + *  This program is free software; you can redistribute it and/or
  +modify it
  + *  under the terms of the GNU General Public License as published by
  +the Free
  + *  Software Foundation; either version 2 of the License, or (at your
  +option)
  + *  any later version.
  + *
  + *  This program is distributed in the hope that it will be useful,
  +but
  + *  WITHOUT ANY WARRANTY; without even the implied warranty of
  +MERCHANTABILITY
  + *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  +License
  + *  for more details.
  + *
  + *  You should have received a copy of the GNU General Public License
  + *  along with this program; if not, write to the Free Software
  +Foundation,
  + *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  + */
  +
  +#include linux/init.h
  +#include linux/module.h
  +#include sound/core.h
  +#include drm/i915_powerwell.h
  +#include hda_i915.h
  +
  +static const char *module_name = i915; static struct module *i915;
  +static void (*get_power)(void); static void (*put_power)(void);
  +
  +void hda_display_power(bool enable)
  +{
  +   if (!get_power || !put_power)
  +   return;
  +
  +   snd_printk(KERN_DEBUG HDA display power %s \n,
  +   enable ? Enable : Disable);
 
 Use snd_printdd() for such a frequent debug message.
 We don't want to see this message at each time you open/close the audio
 stream.

Fixed.

 
  +   if (enable)
  +   get_power();
  +   else
  +   put_power();
  +}
  +
  +/* in case i915 not loaded, try load i915 first */ static int
  +load_i915(void) {
  +   int err;
  +   mutex_lock(module_mutex);
  +   i915 = find_module(module_name);
  +   mutex_unlock(module_mutex);
  +
  +   if (!i915) {
  +   err = 

Re: [Intel-gfx] [PATCH 2/2] ALSA: hda - Add power-welll support for haswell HDA

2013-05-15 Thread Takashi Iwai
At Thu, 16 May 2013 03:51:16 +,
Wang, Xingchao wrote:
 
 Hi Takashi,
 
 Thanks your quick feedback, please see my comments below.
 
  -Original Message-
  From: Takashi Iwai [mailto:ti...@suse.de]
  Sent: Tuesday, May 14, 2013 8:15 PM
  To: Wang Xingchao
  Cc: dan...@ffwll.ch; Girdwood, Liam R; david.hennings...@canonical.com; Lin,
  Mengdong; Li, Jocelyn; alsa-de...@alsa-project.org;
  intel-gfx@lists.freedesktop.org; Barnes, Jesse; Zanoni, Paulo R; Wang,
  Xingchao
  Subject: Re: [PATCH 2/2] ALSA: hda - Add power-welll support for haswell HDA
  
  At Tue, 14 May 2013 19:44:19 +0800,
  Wang Xingchao wrote:
  
   For Intel Haswell chip, HDA controller and codec have power well
   dependency from GPU side. This patch added support to request/release
   power well in audio driver. Power save feature should be enabled to
   get runtime power saving.
  
   Signed-off-by: Wang Xingchao xingchao.w...@linux.intel.com
   ---
sound/pci/hda/Kconfig |8 
sound/pci/hda/Makefile|3 ++
sound/pci/hda/hda_i915.c  |   92
  +
sound/pci/hda/hda_i915.h  |   35 +
sound/pci/hda/hda_intel.c |   33 ++--
5 files changed, 168 insertions(+), 3 deletions(-)  create mode
   100644 sound/pci/hda/hda_i915.c  create mode 100644
   sound/pci/hda/hda_i915.h
  
   diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index
   80a7d44..d9e71e4 100644
   --- a/sound/pci/hda/Kconfig
   +++ b/sound/pci/hda/Kconfig
   @@ -152,6 +152,14 @@ config SND_HDA_CODEC_HDMI
   snd-hda-codec-hdmi.
   This module is automatically loaded at probing.
  
   +config SND_HDA_I915
   + bool Build Display HD-audio controller/codec power well support for 
   i915
  cards
   + depends on DRM_I915
   + default y
   + help
   +   Say Y here to include full HDMI and DisplayPort HD-audio
  controller/codec
   +   support for Intel Haswell graphics cards based on the i915 driver.
  
  Do we need to make this selectable?
  If you have i915 driver, this can be always set.
 
 Well, for Non-Haswell chips with SND_HDA_I915 compiled in, it do nothing as 
 it has no  AZX_DCAPS_I915_POWERWELL set, so no power-well API called.
 For Haswell chips, SND_HDA_I915 must be enabled otherwise display audio would 
 fail. Anyway I added a note message in the choice to let
 user know this option is a *must* one for Haswell chips.

Yes, but the problem is if the driver without CONFIG_SND_HDA_I915 is
used on Haswell.  Then the driver is loaded as if everything is OK
even though you know it's broken.

If you make this selectable, you should give an error from
hda_i915_init() in the case CONFIG_SND_HDA_i915=n, so that the driver
load shall fail.


 
  
  
config SND_HDA_CODEC_CIRRUS
 bool Build Cirrus Logic codec support
 default y
   diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index
   24a2514..4b0a4bc 100644
   --- a/sound/pci/hda/Makefile
   +++ b/sound/pci/hda/Makefile
   @@ -6,6 +6,9 @@ snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
  
   +# for haswell power well
   +snd-hda-intel-$(CONFIG_SND_HDA_I915) +=  hda_i915.o
   +
# for trace-points
CFLAGS_hda_codec.o := -I$(src)
CFLAGS_hda_intel.o := -I$(src)
   diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c new
   file mode 100644 index 000..96ca9e7
   --- /dev/null
   +++ b/sound/pci/hda/hda_i915.c
   @@ -0,0 +1,92 @@
   +/*
   + *  hda_i915.c - routines for Haswell HDA controller power well
   +support
   + *
   + *  This program is free software; you can redistribute it and/or
   +modify it
   + *  under the terms of the GNU General Public License as published by
   +the Free
   + *  Software Foundation; either version 2 of the License, or (at your
   +option)
   + *  any later version.
   + *
   + *  This program is distributed in the hope that it will be useful,
   +but
   + *  WITHOUT ANY WARRANTY; without even the implied warranty of
   +MERCHANTABILITY
   + *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   +License
   + *  for more details.
   + *
   + *  You should have received a copy of the GNU General Public License
   + *  along with this program; if not, write to the Free Software
   +Foundation,
   + *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   + */
   +
   +#include linux/init.h
   +#include linux/module.h
   +#include sound/core.h
   +#include drm/i915_powerwell.h
   +#include hda_i915.h
   +
   +static const char *module_name = i915; static struct module *i915;
   +static void (*get_power)(void); static void (*put_power)(void);
   +
   +void hda_display_power(bool enable)
   +{
   + if (!get_power || !put_power)
   + return;
   +
   + snd_printk(KERN_DEBUG HDA display power %s \n,
   + enable ? Enable : Disable);
  
  Use snd_printdd() for such