Re: [Nouveau] [PATCH 2/2] drm/nouveau: implement precise vblank timestamping

2012-04-26 Thread Lucas Stach
Hi Maarten,

Am Donnerstag, den 26.04.2012, 23:25 +0200 schrieb Maarten Maathuis:
> It seems a bit strange to go in between a register and defines that
> probably belong to that register.
> 
Yes, you are right. Thanks for catching this. I will fix this up, but
will wait for Ben's comments and/or other review feedback before
spamming the list with just another version of this patch.

-- Lucas
> On Thu, Apr 26, 2012 at 12:26 AM, Lucas Stach  wrote:
> >  #define NV_PCRTC_ENGINE_CTRL   0x00600860
> > +#define NV_PCRTC_STAT(i0)  (0x00600868 + 0x2000*(i0))
> >  #  define NV_CRTC_FSEL_I2C (1 << 4)
> >  #  define NV_CRTC_FSEL_OVERLAY (1 << 12)
> 
> 
> 


___
Nouveau mailing list
Nouveau@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/nouveau


Re: [Nouveau] [PATCH 2/2] drm/nouveau: implement precise vblank timestamping

2012-04-26 Thread Maarten Maathuis
It seems a bit strange to go in between a register and defines that
probably belong to that register.

On Thu, Apr 26, 2012 at 12:26 AM, Lucas Stach  wrote:
>  #define NV_PCRTC_ENGINE_CTRL                           0x00600860
> +#define NV_PCRTC_STAT(i0)                      (0x00600868 + 0x2000*(i0))
>  #      define NV_CRTC_FSEL_I2C                                 (1 << 4)
>  #      define NV_CRTC_FSEL_OVERLAY                             (1 << 12)



-- 
Far away from the primal instinct, the song seems to fade away, the
river get wider between your thoughts and the things we do and say.
___
Nouveau mailing list
Nouveau@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/nouveau


[Nouveau] [PATCH 2/2] drm/nouveau: implement precise vblank timestamping

2012-04-25 Thread Lucas Stach
This patch implements the driver hooks needed for precise vblank
timestamping. This is a complementary patch to Mario Kleiner's
patches to improve swap scheduling. With the complete
patchset applied nouveau will be able to provide correct and
precise pageflip timestamps (compliant to OML_sync_control spec)

v2: - Rebase on top of nouveau tree and update to reflect Ben's
  review feedback.

v3: - Split nv04+ and nv50+ paths into separate functions.
- Do not advertise precise vblank timestamping on nvd9+,
  as it's not confirmed to work and the nv50 codepath may
  not work due to moved regs.

Kudos to Mario for his many helpful comments and testing.

Signed-off-by: Lucas Stach 
Reviewed-by: Mario Kleiner 
Tested-by: Mario Kleiner 
---
 drivers/gpu/drm/nouveau/nouveau_display.c |   25 ++
 drivers/gpu/drm/nouveau/nouveau_reg.h |9 +++-
 drivers/gpu/drm/nouveau/nv04_display.c|   55 ++
 drivers/gpu/drm/nouveau/nv50_crtc.c   |   19 
 drivers/gpu/drm/nouveau/nv50_display.c|   71 +
 drivers/gpu/drm/nouveau/nvreg.h   |1 +
 6 files changed, 179 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index 2c0f415..810ba72 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -258,6 +258,27 @@ nouveau_display_fini(struct drm_device *dev)
 }
 
 int
+nouveau_get_vblank_timestamp(struct drm_device *dev, int crtc,
+int *max_error, struct timeval *vblank_time,
+unsigned flags)
+{
+   struct drm_crtc *drmcrtc;
+
+   if (crtc < 0 || crtc >= dev->num_crtcs) {
+   DRM_ERROR("Invalid crtc %d\n", crtc);
+   return -EINVAL;
+   }
+
+   list_for_each_entry(drmcrtc, &dev->mode_config.crtc_list, head) {
+   if(nouveau_crtc(drmcrtc)->index == crtc)
+   break;
+   }
+
+   return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
+   vblank_time, flags, drmcrtc);
+}
+
+int
 nouveau_display_create(struct drm_device *dev)
 {
struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -327,6 +348,10 @@ nouveau_display_create(struct drm_device *dev)
if (ret)
goto disp_create_err;
 
+   if (dev->driver->get_scanout_position)
+   dev->driver->get_vblank_timestamp =
+   nouveau_get_vblank_timestamp;
+
if (dev->mode_config.num_crtc) {
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret)
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h 
b/drivers/gpu/drm/nouveau/nouveau_reg.h
index 43a96b9..0ec1945 100644
--- a/drivers/gpu/drm/nouveau/nouveau_reg.h
+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
@@ -762,7 +762,7 @@
 #define NV50_PDISPLAY_CRTC_CLOCK 0x00610ad0
 #define NV50_PDISPLAY_CRTC_COLOR_CTRL0x00610ae0
 #define NV50_PDISPLAY_CRTC_SYNC_START_TO_BLANK_END   0x00610ae8
-#define NV50_PDISPLAY_CRTC_MODE_UNK1 0x00610af0
+#define NV50_PDISPLAY_CRTC_VBL_START 0x00610af0
 #define NV50_PDISPLAY_CRTC_DISPLAY_TOTAL 0x00610af8
 #define NV50_PDISPLAY_CRTC_SYNC_DURATION 0x00610b00
 #define NV50_PDISPLAY_CRTC_MODE_UNK2 0x00610b08
@@ -800,6 +800,13 @@
 #define NV50_PDISPLAY_SOR_CLK0x00614000
 #define NV50_PDISPLAY_SOR_CLK_CTRL2(i)  ((i) * 0x800 + 
0x614300)
 
+#define NV50_PDISPLAY_CRTC_STAT_VERT(i0)  (0x00616340 + 
0x800*(i0))
+#define NV50_PDISPLAY_CRTC_STAT_VERT_VLINE__MASK   0x
+#define NV50_PDISPLAY_CRTC_STAT_VERT_VBLANK_COUNT__MASK
0x
+#define NV50_PDISPLAY_CRTC_STAT_VERT_VBLANK_COUNT__SHIFT   16
+#define NV50_PDISPLAY_CRTC_STAT_HORZ(i0)  (0x00616344 + 
0x800*(i0))
+#define NV50_PDISPLAY_CRTC_STAT_HORZ_HLINE__MASK   0x
+
 #define NV50_PDISPLAY_VGACRTC(r)((r) + 
0x619400)
 
 #define NV50_PDISPLAY_DAC0x0061a000
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c 
b/drivers/gpu/drm/nouveau/nv04_display.c
index 7047d37..2622953 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/nv04_display.c
@@ -26,6 +26,7 @@
 #include "drm.h"
 #include "drm_crtc_helper.h"
 
+#include "nouveau_crtc.h"
 #include "nouveau_drv.h"
 #include "nouveau_fb.h"
 #include "nouveau_hw.h"
@@ -35,6 +36,58 @@
 static void nv04_vblank_crtc0_isr(struct drm_device *);
 static void nv04_vblank_crtc1_isr(struct drm_device *);
 
+int
+nv04_display_scanoutpos_get(struct drm_device *dev

[Nouveau] [PATCH 2/2] drm/nouveau: implement precise vblank timestamping

2012-02-19 Thread Lucas Stach
This patch implements the driver hooks needed for precise vblank
timestamping. This is a complementary patch to Mario Kleiner's
patches to improve swap scheduling. With the complete
patchset applied nouveau will be able to provide correct and
precise pageflip timestamps (compliant to OML_sync_control spec)

v2: Rebase on top of nouveau tree and update to reflect Ben's
review feedback.

Kudos to Mario for his many helpful comments and testing.

Signed-off-by: Lucas Stach 
Reviewed-by: Mario Kleiner 
Tested-by: Mario Kleiner 
---
 drivers/gpu/drm/nouveau/nouveau_display.c |  124 +
 drivers/gpu/drm/nouveau/nouveau_drv.c |2 +
 drivers/gpu/drm/nouveau/nouveau_drv.h |5 +
 drivers/gpu/drm/nouveau/nouveau_reg.h |9 ++-
 drivers/gpu/drm/nouveau/nv50_crtc.c   |   19 +
 drivers/gpu/drm/nouveau/nvreg.h   |1 +
 6 files changed, 159 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index 818cfc9..b0cae44 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -635,3 +635,127 @@ nouveau_display_dumb_map_offset(struct drm_file 
*file_priv,
 
return -ENOENT;
 }
+
+int
+nouveau_get_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos)
+{
+   struct drm_nouveau_private *dev_priv = dev->dev_private;
+   int vline, hline, ret = 0;
+   u32 vbias, hbias, reg, vbl_start, vbl_end;
+   struct drm_crtc *drmcrtc;
+
+   if (crtc < 0 || crtc >= dev->num_crtcs) {
+   DRM_ERROR("Invalid crtc %d\n", crtc);
+   return -EINVAL;
+   }
+
+   list_for_each_entry(drmcrtc, &dev->mode_config.crtc_list, head) {
+   if (nouveau_crtc(drmcrtc)->index == crtc)
+   /* stop if we have found crtc with matching index */
+   break;
+   }
+
+   if (dev_priv->card_type >= NV_50) {
+   /* get vsync and hsync area */
+   reg = nv_rd32(dev, NV50_PDISPLAY_CRTC_C(crtc,
+  SYNC_START_TO_BLANK_END));
+   vbias = (reg >> 16) & 0x;
+   hbias = reg & 0x;
+
+   /* get vertical display size including bias as vbl_start
+* and vtotal as vbl_end */
+   vbl_start = (nv_rd32(dev, NV50_PDISPLAY_CRTC_C(crtc,
+ VBL_START)) >> 16) & 0x;
+   vbl_end = (nv_rd32(dev, NV50_PDISPLAY_CRTC_C(crtc,
+   DISPLAY_TOTAL)) >> 16) & 0x;
+
+   /* get current scanout position from PDISPLAY */
+   vline = nv_rd32(dev, NV50_PDISPLAY_CRTC_STAT_VERT(crtc))
+   & NV50_PDISPLAY_CRTC_STAT_VERT_VLINE__MASK;
+
+   /*
+* vline == 0 could be invalid:
+* Some gpu's get stuck on that value inside vblank. Try again
+* after one scanline duration, if it still reads 0 give up.
+*/
+   if (vline == 0) {
+   ndelay(drmcrtc->linedur_ns & 0x);
+   vline = nv_rd32(dev, NV50_PDISPLAY_CRTC_STAT_VERT(crtc))
+   & NV50_PDISPLAY_CRTC_STAT_VERT_VLINE__MASK;
+   }
+
+   hline = nv_rd32(dev, NV50_PDISPLAY_CRTC_STAT_HORZ(crtc))
+   & NV50_PDISPLAY_CRTC_STAT_HORZ_HLINE__MASK;
+
+   if ((vline > 0) && (vline < vbl_end))
+   ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
+
+   if ((vline >= vbl_start) || (vline < vbias)) {
+   /* we are in vblank so do a neg countdown */
+   ret |= DRM_SCANOUTPOS_INVBL;
+   vline -= (vline < vbias) ? vbias : (vbl_end + vbias);
+   hline -= hbias;
+   } else {
+   /* apply corrective offset */
+   vline -= vbias;
+   hline -= hbias;
+   }
+   } else {
+   /* get vsync area from PRAMDAC */
+   vbl_start = NVReadRAMDAC(dev, crtc, NV_PRAMDAC_FP_VDISPLAY_END)
+   & 0x;
+   vbl_end = (NVReadRAMDAC(dev, crtc, NV_PRAMDAC_FP_VTOTAL)
+  & 0x) + 1;
+
+   /* get current scanout position from PCRTC */
+   vline = nv_rd32(dev, NV_PCRTC_STAT(crtc)) & 0x;
+
+   /*
+* vline == 0 could be invalid:
+* Some gpu's get stuck on that value inside vblank. Try again
+* after one scanline duration, if it still reads 0 give up.
+*/
+   if (vline == 0) {
+   ndelay(drmcrtc->linedur_ns & 0x);
+   vline = nv_rd32(dev, NV_PCRTC_STAT(crtc)) & 0x;
+   

[Nouveau] [PATCH 2/2] drm/nouveau: implement precise vblank timestamping

2012-02-16 Thread Lucas Stach
This patch implements the driver hooks needed for precise vblank
timestamping. This is a complementary patch to Mario Kleiner's
patches to improve swap scheduling. With the complete
patchset applied nouveau will be able to provide correct and
precise pageflip timestamps (compliant to OML_sync_control spec)

v2: Rebase on top of nouveau tree and update to reflect Ben's
review feedback.

Kudos to Mario for his many helpful comments and testing.

Signed-off-by: Lucas Stach 
Reviewed-by: Mario Kleiner 
Tested-by: Mario Kleiner 
---
 drivers/gpu/drm/nouveau/nouveau_display.c |  124 +
 drivers/gpu/drm/nouveau/nouveau_drv.c |2 +
 drivers/gpu/drm/nouveau/nouveau_drv.h |5 +
 drivers/gpu/drm/nouveau/nouveau_reg.h |9 ++-
 drivers/gpu/drm/nouveau/nv50_crtc.c   |   19 +
 drivers/gpu/drm/nouveau/nvreg.h   |1 +
 6 files changed, 159 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index 818cfc9..1f836cd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -635,3 +635,127 @@ nouveau_display_dumb_map_offset(struct drm_file 
*file_priv,
 
return -ENOENT;
 }
+
+int
+nouveau_get_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos)
+{
+   struct drm_nouveau_private *dev_priv = dev->dev_private;
+   int vline, hline, ret = 0;
+   u32 vbias, hbias, reg, vbl_start, vbl_end;
+   struct drm_crtc *drmcrtc;
+
+   if (crtc < 0 || crtc >= dev->num_crtcs) {
+   DRM_ERROR("Invalid crtc %d\n", crtc);
+   return -EINVAL;
+   }
+
+   list_for_each_entry(drmcrtc, &dev->mode_config.crtc_list, head) {
+   if(nouveau_crtc(drmcrtc)->index == crtc)
+   /* stop if we have found crtc with matching index */
+   break;
+   }
+
+   if(dev_priv->card_type >= NV_50) {
+   /* get vsync and hsync area */
+   reg = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc,
+  SYNC_START_TO_BLANK_END));
+   vbias = (reg >> 16) & 0x;
+   hbias = reg & 0x;
+
+   /* get vertical display size including bias as vbl_start
+* and vtotal as vbl_end */
+   vbl_start = (nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc,
+ VBL_START)) >> 16) & 0x;
+   vbl_end = (nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc,
+   DISPLAY_TOTAL)) >> 16) & 0x;
+
+   /* get current scanout position from PDISPLAY */
+   vline = nv_rd32(dev, NV50_PDISPLAY_CRTC_STAT_VERT(crtc))
+   & NV50_PDISPLAY_CRTC_STAT_VERT_VLINE__MASK;
+
+   /*
+* vline == 0 could be invalid:
+* Some gpu's get stuck on that value inside vblank. Try again
+* after one scanline duration, if it still reads 0 give up.
+*/
+   if (vline == 0) {
+   ndelay(drmcrtc->linedur_ns & 0x);
+   vline = nv_rd32(dev, NV50_PDISPLAY_CRTC_STAT_VERT(crtc))
+   & NV50_PDISPLAY_CRTC_STAT_VERT_VLINE__MASK;
+   }
+
+   hline = nv_rd32(dev, NV50_PDISPLAY_CRTC_STAT_HORZ(crtc))
+   & NV50_PDISPLAY_CRTC_STAT_HORZ_HLINE__MASK;
+
+   if((vline > 0) && (vline < vbl_end))
+   ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
+
+   if((vline >= vbl_start) || (vline < vbias)) {
+   /* we are in vblank so do a neg countdown */
+   ret |= DRM_SCANOUTPOS_INVBL;
+   vline -= (vline < vbias) ? vbias : (vbl_end + vbias);
+   hline -= hbias;
+   } else {
+   /* apply corrective offset */
+   vline -= vbias;
+   hline -= hbias;
+   }
+   } else {
+   /* get vsync area from PRAMDAC */
+   vbl_start = NVReadRAMDAC(dev, crtc, NV_PRAMDAC_FP_VDISPLAY_END)
+   & 0x;
+   vbl_end = (NVReadRAMDAC(dev, crtc, NV_PRAMDAC_FP_VTOTAL)
+  & 0x) + 1;
+
+   /* get current scanout position from PCRTC */
+   vline = nv_rd32(dev, NV_PCRTC_STAT(crtc)) & 0x;
+
+   /*
+* vline == 0 could be invalid:
+* Some gpu's get stuck on that value inside vblank. Try again
+* after one scanline duration, if it still reads 0 give up.
+*/
+   if (vline == 0) {
+   ndelay(drmcrtc->linedur_ns & 0x);
+   vline = nv_rd32(dev, NV_PCRTC_STAT(crtc)) & 0x;
+