Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/nvidia Add vblank support



details:   https://anonhg.NetBSD.org/src/rev/f86103e9b18b
branches:  trunk
changeset: 341536:f86103e9b18b
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Tue Nov 10 22:14:05 2015 +0000

description:
Add vblank support

diffstat:

 sys/arch/arm/nvidia/tegra_dcreg.h    |   4 +-
 sys/arch/arm/nvidia/tegra_drm.c      |   8 ++-
 sys/arch/arm/nvidia/tegra_drm.h      |   8 ++-
 sys/arch/arm/nvidia/tegra_drm_mode.c |  89 +++++++++++++++++++++++++++++++++++-
 4 files changed, 103 insertions(+), 6 deletions(-)

diffs (220 lines):

diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_dcreg.h
--- a/sys/arch/arm/nvidia/tegra_dcreg.h Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_dcreg.h Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_dcreg.h,v 1.3 2015/07/23 15:08:19 skrll Exp $ */
+/* $NetBSD: tegra_dcreg.h,v 1.4 2015/11/10 22:14:05 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -73,6 +73,8 @@
 #define DC_CMD_INT_STATUS_REG                          0x0dc
 #define DC_CMD_INT_MASK_REG                            0x0e0
 #define DC_CMD_INT_ENABLE_REG                          0x0e4
+#define DC_CMD_INT_V_BLANK                             __BIT(2)
+
 #define DC_CMD_INT_TYPE_REG                            0x0e8
 #define DC_CMD_INT_POLARITY_REG                                0x0ec
 #define DC_CMD_SIGNAL_RAISE1_REG                       0x0f0
diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_drm.c
--- a/sys/arch/arm/nvidia/tegra_drm.c   Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.c   Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.c,v 1.1 2015/11/09 23:05:58 jmcneill Exp $ */
+/* $NetBSD: tegra_drm.c,v 1.2 2015/11/10 22:14:05 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.1 2015/11/09 23:05:58 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_drm.c,v 1.2 2015/11/10 22:14:05 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -79,6 +79,10 @@
        .dumb_map_offset = tegra_drm_dumb_map_offset,
        .dumb_destroy = tegra_drm_dumb_destroy,
 
+       .get_vblank_counter = tegra_drm_get_vblank_counter,
+       .enable_vblank = tegra_drm_enable_vblank,
+       .disable_vblank = tegra_drm_disable_vblank,
+
        .name = DRIVER_NAME,
        .desc = DRIVER_DESC,
        .date = DRIVER_DATE,
diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_drm.h
--- a/sys/arch/arm/nvidia/tegra_drm.h   Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm.h   Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm.h,v 1.1 2015/11/09 23:05:58 jmcneill Exp $ */
+/* $NetBSD: tegra_drm.h,v 1.2 2015/11/10 22:14:05 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -61,6 +61,8 @@
        bus_size_t              sc_dmasize;
        bus_dmamap_t            sc_dmamap;
        void                    *sc_dmap;
+
+       uint32_t                sc_vbl_received[2];
 };
 
 struct tegra_drmfb_attach_args {
@@ -78,6 +80,7 @@
        bus_size_t              size;
        int                     intr;
        int                     index;
+       void                    *ih;
 };
 
 struct tegra_encoder {
@@ -129,5 +132,8 @@
 
 int    tegra_drm_mode_init(struct drm_device *);
 int    tegra_drm_fb_init(struct drm_device *);
+u32    tegra_drm_get_vblank_counter(struct drm_device *, int);
+int    tegra_drm_enable_vblank(struct drm_device *, int);
+void   tegra_drm_disable_vblank(struct drm_device *, int);
 
 #endif /* _ARM_TEGRA_DRM_H */
diff -r fc40c414bcbc -r f86103e9b18b sys/arch/arm/nvidia/tegra_drm_mode.c
--- a/sys/arch/arm/nvidia/tegra_drm_mode.c      Tue Nov 10 20:56:20 2015 +0000
+++ b/sys/arch/arm/nvidia/tegra_drm_mode.c      Tue Nov 10 22:14:05 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tegra_drm_mode.c,v 1.3 2015/11/10 00:33:39 jmcneill Exp $ */
+/* $NetBSD: tegra_drm_mode.c,v 1.4 2015/11/10 22:14:05 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tegra_drm_mode.c,v 1.3 2015/11/10 00:33:39 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tegra_drm_mode.c,v 1.4 2015/11/10 22:14:05 jmcneill Exp $");
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
@@ -58,6 +58,7 @@
 
 static int     tegra_crtc_init(struct drm_device *, int);
 static void    tegra_crtc_destroy(struct drm_crtc *);
+static int     tegra_crtc_intr(void *);
 
 static const struct drm_crtc_funcs tegra_crtc_funcs = {
        .set_config = drm_crtc_helper_set_config,
@@ -187,6 +188,10 @@
        if (error)
                return error;
 
+       error = drm_vblank_init(ddev, 2);
+       if (error)
+               return error;
+
        return 0;
 }
 
@@ -275,9 +280,16 @@
        }
        crtc->size = size;
        crtc->intr = intr;
+       crtc->ih = intr_establish(intr, IPL_VM, IST_LEVEL | IST_MPSAFE,
+           tegra_crtc_intr, crtc);
+       if (crtc->ih == NULL) {
+               DRM_ERROR("failed to establish interrupt for crtc %d\n", index);
+       }
 
        tegra_car_dc_enable(crtc->index);
 
+       DC_WRITE(crtc, DC_CMD_INT_ENABLE_REG, DC_CMD_INT_V_BLANK);
+
        drm_crtc_init(ddev, &crtc->base, &tegra_crtc_funcs);
        drm_crtc_helper_add(&crtc->base, &tegra_crtc_helper_funcs);
 
@@ -289,6 +301,9 @@
 {
        struct tegra_crtc *tegra_crtc = to_tegra_crtc(crtc);
        drm_crtc_cleanup(crtc);
+       if (tegra_crtc->ih) {
+               intr_disestablish(tegra_crtc->ih);
+       }
        bus_space_unmap(tegra_crtc->bst, tegra_crtc->bsh, tegra_crtc->size);
        kmem_free(tegra_crtc, sizeof(*tegra_crtc));
 }
@@ -969,3 +984,73 @@
 
        return encoder;
 }
+
+static int
+tegra_crtc_intr(void *priv)
+{
+       struct tegra_crtc *tegra_crtc = priv;
+       struct drm_device *ddev = tegra_crtc->base.dev;
+       struct tegra_drm_softc * const sc = tegra_drm_private(ddev);
+       int rv = 0;
+
+       const uint32_t status = DC_READ(tegra_crtc, DC_CMD_INT_STATUS_REG);
+
+       if (status & DC_CMD_INT_V_BLANK) {
+               DC_WRITE(tegra_crtc, DC_CMD_INT_STATUS_REG, DC_CMD_INT_V_BLANK);
+               atomic_inc_32(&sc->sc_vbl_received[tegra_crtc->index]);
+               drm_handle_vblank(ddev, tegra_crtc->index);
+               rv = 1;
+       }
+
+       return rv;
+}
+
+u32
+tegra_drm_get_vblank_counter(struct drm_device *ddev, int crtc)
+{
+       struct tegra_drm_softc * const sc = tegra_drm_private(ddev);
+
+       if (crtc > 1)
+               return 0;
+
+       return sc->sc_vbl_received[crtc];
+}
+
+int
+tegra_drm_enable_vblank(struct drm_device *ddev, int crtc)
+{
+       struct tegra_crtc *tegra_crtc = NULL;
+       struct drm_crtc *iter;
+
+       list_for_each_entry(iter, &ddev->mode_config.crtc_list, head) {
+               if (to_tegra_crtc(iter)->index == crtc) {
+                       tegra_crtc = to_tegra_crtc(iter);
+                       break;
+               }
+       }
+       if (tegra_crtc == NULL)
+               return -EINVAL;
+
+       DC_SET_CLEAR(tegra_crtc, DC_CMD_INT_MASK_REG, DC_CMD_INT_V_BLANK, 0);
+
+       return 0;
+}
+
+void
+tegra_drm_disable_vblank(struct drm_device *ddev, int crtc)
+{
+       struct tegra_crtc *tegra_crtc = NULL;
+       struct drm_crtc *iter;
+
+       list_for_each_entry(iter, &ddev->mode_config.crtc_list, head) {
+               if (to_tegra_crtc(iter)->index == crtc) {
+                       tegra_crtc = to_tegra_crtc(iter);
+                       break;
+               }
+       }
+       if (tegra_crtc == NULL)
+               return;
+
+       DC_SET_CLEAR(tegra_crtc, DC_CMD_INT_MASK_REG, 0, DC_CMD_INT_V_BLANK);
+       DC_WRITE(tegra_crtc, DC_CMD_INT_STATUS_REG, DC_CMD_INT_V_BLANK);
+}



Home | Main Index | Thread Index | Old Index