]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux...
authorDave Airlie <airlied@redhat.com>
Tue, 10 Jun 2014 06:39:21 +0000 (16:39 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 10 Jun 2014 06:39:21 +0000 (16:39 +1000)
There's really not a great deal this time due to me spending most of this window on Maxwell.  But, here's the random bits and pieces that's currently queued.
* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (25 commits)
  drm/gk208/gr: add missing registers to grctx init
  drm/nouveau/kms/nv04-nv40: fix pageflip events via special case.
  drm/nv50-/mc: fix kms pageflip events by reordering irq handling order.
  drm/nouveau/disp/nv04-nv40: abort scanoutpos query on vga analog.
  drm/nv50-/kms: wait for enough ring space in crtc_prepare()
  drm/nouveau/disp/dp: support training pattern 3
  drm/nouveau/disp/dp: support aux read interval during link training
  drm/gk104/gpio: fix incorrect interrupt register usage
  drm/nouveau/core: punt all object state change messages to trace level
  drm/nouveau/clk: allow end-user reclocking for nv40, nvaa, and nve0 clock types
  drm/nouveau/fb: default NvMemExec to on, turning it off is used for debugging only
  drm/nouveau/bios: fix a potential NULL deref in the PROM shadowing function
  drm/nouveau/i2c: bump the i2c delay for the adt7473
  drm/nouveau/therm/fan/tach: default to 2 pulses per revolution
  drm/nvf0/device: enable video decoding engines on gk110/gk208
  drm/nvf1/device: add support for 0xf1 (gk110b)
  drm/nouveau/device: support for probing GK20A
  drm/nouveau/graph: add GK20A support
  drm/nouveau/graph: pad firmware code at load time
  drm/nouveau/graph: enable when using external fw
  ...

48 files changed:
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/core/object.c
drivers/gpu/drm/nouveau/core/engine/device/nve0.c
drivers/gpu/drm/nouveau/core/engine/disp/dport.c
drivers/gpu/drm/nouveau/core/engine/disp/dport.h
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
drivers/gpu/drm/nouveau/core/engine/fifo/gk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h
drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
drivers/gpu/drm/nouveau/core/engine/graph/nve4.c
drivers/gpu/drm/nouveau/core/include/engine/fifo.h
drivers/gpu/drm/nouveau/core/include/engine/graph.h
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/include/subdev/ibus.h
drivers/gpu/drm/nouveau/core/subdev/bar/base.c
drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/clock/base.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c
drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c
drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c
drivers/gpu/drm/nouveau/core/subdev/ibus/gk20a.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nv50_display.c

index b7d216264775511bcb807566047d9c69db26ff31..1aaa2ef577d9eb7a71d2f3d71631d042763bf234 100644 (file)
@@ -102,6 +102,7 @@ nouveau-y += core/subdev/fb/nvaa.o
 nouveau-y += core/subdev/fb/nvaf.o
 nouveau-y += core/subdev/fb/nvc0.o
 nouveau-y += core/subdev/fb/nve0.o
+nouveau-y += core/subdev/fb/gk20a.o
 nouveau-y += core/subdev/fb/gm107.o
 nouveau-y += core/subdev/fb/ramnv04.o
 nouveau-y += core/subdev/fb/ramnv10.o
@@ -117,6 +118,7 @@ nouveau-y += core/subdev/fb/ramnva3.o
 nouveau-y += core/subdev/fb/ramnvaa.o
 nouveau-y += core/subdev/fb/ramnvc0.o
 nouveau-y += core/subdev/fb/ramnve0.o
+nouveau-y += core/subdev/fb/ramgk20a.o
 nouveau-y += core/subdev/fb/ramgm107.o
 nouveau-y += core/subdev/fb/sddr3.o
 nouveau-y += core/subdev/fb/gddr5.o
@@ -136,6 +138,7 @@ nouveau-y += core/subdev/i2c/nv94.o
 nouveau-y += core/subdev/i2c/nvd0.o
 nouveau-y += core/subdev/ibus/nvc0.o
 nouveau-y += core/subdev/ibus/nve0.o
+nouveau-y += core/subdev/ibus/gk20a.o
 nouveau-y += core/subdev/instmem/base.o
 nouveau-y += core/subdev/instmem/nv04.o
 nouveau-y += core/subdev/instmem/nv40.o
@@ -245,6 +248,7 @@ nouveau-y += core/engine/fifo/nv50.o
 nouveau-y += core/engine/fifo/nv84.o
 nouveau-y += core/engine/fifo/nvc0.o
 nouveau-y += core/engine/fifo/nve0.o
+nouveau-y += core/engine/fifo/gk20a.o
 nouveau-y += core/engine/fifo/nv108.o
 nouveau-y += core/engine/graph/ctxnv40.o
 nouveau-y += core/engine/graph/ctxnv50.o
@@ -255,6 +259,7 @@ nouveau-y += core/engine/graph/ctxnvc8.o
 nouveau-y += core/engine/graph/ctxnvd7.o
 nouveau-y += core/engine/graph/ctxnvd9.o
 nouveau-y += core/engine/graph/ctxnve4.o
+nouveau-y += core/engine/graph/ctxgk20a.o
 nouveau-y += core/engine/graph/ctxnvf0.o
 nouveau-y += core/engine/graph/ctxnv108.o
 nouveau-y += core/engine/graph/ctxgm107.o
@@ -275,6 +280,7 @@ nouveau-y += core/engine/graph/nvc8.o
 nouveau-y += core/engine/graph/nvd7.o
 nouveau-y += core/engine/graph/nvd9.o
 nouveau-y += core/engine/graph/nve4.o
+nouveau-y += core/engine/graph/gk20a.o
 nouveau-y += core/engine/graph/nvf0.o
 nouveau-y += core/engine/graph/nv108.o
 nouveau-y += core/engine/graph/gm107.o
index 7f48e288215f0ca2427b6bb0095db86042846f5a..12453855590403142578455e50bec1d9ad059b1e 100644 (file)
@@ -156,7 +156,7 @@ nouveau_object_ctor(struct nouveau_object *parent,
        }
 
        if (ret == 0) {
-               nv_debug(object, "created\n");
+               nv_trace(object, "created\n");
                atomic_set(&object->refcount, 1);
        }
 
@@ -166,7 +166,7 @@ nouveau_object_ctor(struct nouveau_object *parent,
 static void
 nouveau_object_dtor(struct nouveau_object *object)
 {
-       nv_debug(object, "destroying\n");
+       nv_trace(object, "destroying\n");
        nv_ofuncs(object)->dtor(object);
 }
 
@@ -337,7 +337,7 @@ nouveau_object_inc(struct nouveau_object *object)
                goto fail_self;
        }
 
-       nv_debug(object, "initialised\n");
+       nv_trace(object, "initialised\n");
        return 0;
 
 fail_self:
@@ -375,7 +375,7 @@ nouveau_object_decf(struct nouveau_object *object)
        if (object->parent)
                nouveau_object_dec(object->parent, false);
 
-       nv_debug(object, "stopped\n");
+       nv_trace(object, "stopped\n");
        return 0;
 }
 
@@ -411,7 +411,7 @@ nouveau_object_decs(struct nouveau_object *object)
                }
        }
 
-       nv_debug(object, "suspended\n");
+       nv_trace(object, "suspended\n");
        return 0;
 
 fail_parent:
index 9784cbf8a9d20d2cf7d9706ca0fa5a571a720d74..459099e2515f4d823074067deb6910b0d3abec0f 100644 (file)
@@ -156,6 +156,23 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
                break;
+       case 0xea:
+               device->cname = "GK20A";
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
+               device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass;
+               device->oclass[NVDEV_SUBDEV_FB     ] =  gk20a_fb_oclass;
+               device->oclass[NVDEV_SUBDEV_IBUS   ] = &gk20a_ibus_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
+               device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+               device->oclass[NVDEV_ENGINE_FIFO   ] =  gk20a_fifo_oclass;
+               device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  gk20a_graph_oclass;
+               device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
+               device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;
+               break;
        case 0xf0:
                device->cname = "GK110";
                device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
@@ -184,11 +201,42 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
-#if 0
                device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
-#endif
+               device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass;
+               break;
+       case 0xf1:
+               device->cname = "GK110B";
+               device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass;
+               device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass;
+               device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass;
+               device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;
+               device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;
+               device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass;
+               device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass;
+               device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass;
+               device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;
+               device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass;
+               device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass;
+               device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;
+               device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass;
+               device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;
+               device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;
+               device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;
+               device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass;
+               device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;
+               device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+               device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass;
+               device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;
+               device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass;
+               device->oclass[NVDEV_ENGINE_DISP   ] =  nvf0_disp_oclass;
+               device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
+               device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
+               device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
+               device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
+               device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
+               device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass;
                break;
        case 0x108:
@@ -219,11 +267,9 @@ nve0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;
                device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;
-#if 0
                device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
-#endif
                break;
        default:
                nv_fatal(device, "unknown Kepler chipset\n");
index 3ca2d25b7f5e023b917dbd4dd246cd8e3fe64031..13903533d7a246c3a8aab8ce5c95cf47ddf1d70e 100644 (file)
@@ -48,7 +48,7 @@ struct dp_state {
        u8 version;
        struct nouveau_i2c_port *aux;
        int head;
-       u8  dpcd[4];
+       u8  dpcd[16];
        int link_nr;
        u32 link_bw;
        u8  stat[6];
@@ -149,7 +149,10 @@ dp_link_train_update(struct dp_state *dp, u32 delay)
 {
        int ret;
 
-       udelay(delay);
+       if (dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL])
+               mdelay(dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4);
+       else
+               udelay(delay);
 
        ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6);
        if (ret)
@@ -199,7 +202,10 @@ dp_link_train_eq(struct dp_state *dp)
        bool eq_done = false, cr_done = true;
        int tries = 0, i;
 
-       dp_set_training_pattern(dp, 2);
+       if (dp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED)
+               dp_set_training_pattern(dp, 3);
+       else
+               dp_set_training_pattern(dp, 2);
 
        do {
                if (dp_link_train_update(dp, 400))
@@ -313,8 +319,10 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,
        }
 
        /* bring capabilities within encoder limits */
+       if (nv_oclass(disp)->handle < NV_ENGINE(DISP, 0x90))
+               dp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
        if ((dp->dpcd[2] & 0x1f) > dp->outp->dpconf.link_nr) {
-               dp->dpcd[2] &= ~0x1f;
+               dp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
                dp->dpcd[2] |= dp->outp->dpconf.link_nr;
        }
        if (dp->dpcd[1] > dp->outp->dpconf.link_bw)
index 0e1bbd18ff6c4e4dc05d961d06a7f5e697643c07..43281c8e9e7b0f323a0148cc51d2335d05ee5ed4 100644 (file)
@@ -2,15 +2,15 @@
 #define __NVKM_DISP_DPORT_H__
 
 /* DPCD Receiver Capabilities */
-#define DPCD_RC00                                                       0x00000
-#define DPCD_RC00_DPCD_REV                                                 0xff
-#define DPCD_RC01                                                       0x00001
-#define DPCD_RC01_MAX_LINK_RATE                                            0xff
+#define DPCD_RC00_DPCD_REV                                              0x00000
+#define DPCD_RC01_MAX_LINK_RATE                                         0x00001
 #define DPCD_RC02                                                       0x00002
 #define DPCD_RC02_ENHANCED_FRAME_CAP                                       0x80
+#define DPCD_RC02_TPS3_SUPPORTED                                           0x40
 #define DPCD_RC02_MAX_LANE_COUNT                                           0x1f
 #define DPCD_RC03                                                       0x00003
 #define DPCD_RC03_MAX_DOWNSPREAD                                           0x01
+#define DPCD_RC0E_AUX_RD_INTERVAL                                       0x0000e
 
 /* DPCD Link Configuration */
 #define DPCD_LC00                                                       0x00100
index 6c89af7928892e0a80a99ae5e8960996d81babae..94a2cc69ec2c75809f0dcb7386d7b470bc5c6b93 100644 (file)
@@ -51,6 +51,14 @@ nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
        args->htotal  = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
        args->hblanke = args->htotal - 1;
 
+       /*
+        * If output is vga instead of digital then vtotal/htotal is invalid
+        * so we have to give up and trigger the timestamping fallback in the
+        * drm core.
+        */
+       if (!args->vtotal || !args->htotal)
+               return -ENOTSUPP;
+
        args->time[0] = ktime_to_ns(ktime_get());
        line = nv_rd32(priv, 0x600868 + (head * 0x2000));
        args->time[1] = ktime_to_ns(ktime_get());
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/core/engine/fifo/gk20a.c
new file mode 100644 (file)
index 0000000..327456e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "nve0.h"
+
+struct nouveau_oclass *
+gk20a_fifo_oclass = &(struct nve0_fifo_impl) {
+       .base.handle = NV_ENGINE(FIFO, 0xea),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nve0_fifo_ctor,
+               .dtor = nve0_fifo_dtor,
+               .init = nve0_fifo_init,
+               .fini = nve0_fifo_fini,
+       },
+       .channels = 128,
+}.base;
index 014344ebee66c4718ec5a59179b2ca6d1d80076f..e96b32bb1bbc5406bac7d1e72b51e68be4a43da3 100644 (file)
@@ -8,6 +8,7 @@ int  nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *,
                    struct nouveau_object **);
 void nve0_fifo_dtor(struct nouveau_object *);
 int  nve0_fifo_init(struct nouveau_object *);
+int  nve0_fifo_fini(struct nouveau_object *, bool);
 
 struct nve0_fifo_impl {
        struct nouveau_oclass base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
new file mode 100644 (file)
index 0000000..224ee02
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ctxnvc0.h"
+
+static const struct nvc0_graph_pack
+gk20a_grctx_pack_mthd[] = {
+       { nve4_grctx_init_a097_0, 0xa297 },
+       { nvc0_grctx_init_902d_0, 0x902d },
+       {}
+};
+
+struct nouveau_oclass *
+gk20a_grctx_oclass = &(struct nvc0_grctx_oclass) {
+       .base.handle = NV_ENGCTX(GR, 0xea),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_context_ctor,
+               .dtor = nvc0_graph_context_dtor,
+               .init = _nouveau_graph_context_init,
+               .fini = _nouveau_graph_context_fini,
+               .rd32 = _nouveau_graph_context_rd32,
+               .wr32 = _nouveau_graph_context_wr32,
+       },
+       .main  = nve4_grctx_generate_main,
+       .mods  = nve4_grctx_generate_mods,
+       .unkn  = nve4_grctx_generate_unkn,
+       .hub   = nve4_grctx_pack_hub,
+       .gpc   = nve4_grctx_pack_gpc,
+       .zcull = nvc0_grctx_pack_zcull,
+       .tpc   = nve4_grctx_pack_tpc,
+       .ppc   = nve4_grctx_pack_ppc,
+       .icmd  = nve4_grctx_pack_icmd,
+       .mthd  = gk20a_grctx_pack_mthd,
+}.base;
index 48351b4d6d6bd8460ee83b2110f9e1adce7235bf..8de4a4291548897d85d84a2662f031b364bb3bc9 100644 (file)
@@ -545,10 +545,12 @@ nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
        mmio_list(0x408010, 0x80000000,  0, 0);
        mmio_list(0x419004, 0x00000000,  8, 1);
        mmio_list(0x419008, 0x00000000,  0, 0);
+       mmio_list(0x4064cc, 0x80000000,  0, 0);
        mmio_list(0x408004, 0x00000000,  8, 0);
        mmio_list(0x408008, 0x80000030,  0, 0);
        mmio_list(0x418808, 0x00000000,  8, 0);
        mmio_list(0x41880c, 0x80000030,  0, 0);
+       mmio_list(0x4064c8, 0x00c20200,  0, 0);
        mmio_list(0x418810, 0x80000000, 12, 2);
        mmio_list(0x419848, 0x10000000, 12, 2);
 
index 9c815d1f99ef9f32171d6ea636291c5aabff6eee..8da8b627b9d0a10299f683781be391074ae31d50 100644 (file)
@@ -69,7 +69,9 @@ extern struct nouveau_oclass *nvd7_grctx_oclass;
 extern struct nouveau_oclass *nvd9_grctx_oclass;
 
 extern struct nouveau_oclass *nve4_grctx_oclass;
+extern struct nouveau_oclass *gk20a_grctx_oclass;
 void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
+void nve4_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
 void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
 void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
 
@@ -151,6 +153,13 @@ extern const struct nvc0_graph_init nve4_grctx_init_gpm_0[];
 
 extern const struct nvc0_graph_init nve4_grctx_init_pes_0[];
 
+extern const struct nvc0_graph_pack nve4_grctx_pack_hub[];
+extern const struct nvc0_graph_pack nve4_grctx_pack_gpc[];
+extern const struct nvc0_graph_pack nve4_grctx_pack_tpc[];
+extern const struct nvc0_graph_pack nve4_grctx_pack_ppc[];
+extern const struct nvc0_graph_pack nve4_grctx_pack_icmd[];
+extern const struct nvc0_graph_init nve4_grctx_init_a097_0[];
+
 extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[];
 
 extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[];
index 49a14b116a5f81fd771da20c756478b7e7dfd839..c5b24923858792fb69869c697e9c34f5431918dd 100644 (file)
@@ -272,13 +272,13 @@ nve4_grctx_init_icmd_0[] = {
        {}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nve4_grctx_pack_icmd[] = {
        { nve4_grctx_init_icmd_0 },
        {}
 };
 
-static const struct nvc0_graph_init
+const struct nvc0_graph_init
 nve4_grctx_init_a097_0[] = {
        { 0x000800,   8, 0x40, 0x00000000 },
        { 0x000804,   8, 0x40, 0x00000000 },
@@ -697,7 +697,7 @@ nve4_grctx_init_be_0[] = {
        {}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nve4_grctx_pack_hub[] = {
        { nvc0_grctx_init_main_0 },
        { nve4_grctx_init_fe_0 },
@@ -737,7 +737,7 @@ nve4_grctx_init_gpm_0[] = {
        {}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nve4_grctx_pack_gpc[] = {
        { nvc0_grctx_init_gpc_unk_0 },
        { nvd9_grctx_init_prop_0 },
@@ -802,7 +802,7 @@ nve4_grctx_init_sm_0[] = {
        {}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nve4_grctx_pack_tpc[] = {
        { nvd7_grctx_init_pe_0 },
        { nve4_grctx_init_tex_0 },
@@ -826,7 +826,7 @@ nve4_grctx_init_cbm_0[] = {
        {}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nve4_grctx_pack_ppc[] = {
        { nve4_grctx_init_pes_0 },
        { nve4_grctx_init_cbm_0 },
@@ -838,7 +838,7 @@ nve4_grctx_pack_ppc[] = {
  * PGRAPH context implementation
  ******************************************************************************/
 
-static void
+void
 nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
        u32 magic[GPC_MAX][2];
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c b/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c
new file mode 100644 (file)
index 0000000..83048a5
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "nvc0.h"
+#include "ctxnvc0.h"
+
+static struct nouveau_oclass
+gk20a_graph_sclass[] = {
+       { 0x902d, &nouveau_object_ofuncs },
+       { 0xa040, &nouveau_object_ofuncs },
+       { 0xa297, &nouveau_object_ofuncs },
+       { 0xa0c0, &nouveau_object_ofuncs },
+       {}
+};
+
+struct nouveau_oclass *
+gk20a_graph_oclass = &(struct nvc0_graph_oclass) {
+       .base.handle = NV_ENGINE(GR, 0xea),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nvc0_graph_ctor,
+               .dtor = nvc0_graph_dtor,
+               .init = nve4_graph_init,
+               .fini = nve4_graph_fini,
+       },
+       .cclass = &gk20a_grctx_oclass,
+       .sclass = gk20a_graph_sclass,
+       .mmio = nve4_graph_pack_mmio,
+}.base;
index f3c7329da0a04c8870ccba95a9b525c2ebc3ddca..bf7bdb1f291efd9e7a2f5c92db554be638f62e4a 100644 (file)
@@ -894,6 +894,10 @@ nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base,
                        nv_wr32(priv, fuc_base + 0x0188, i >> 6);
                nv_wr32(priv, fuc_base + 0x0184, code->data[i]);
        }
+
+       /* code must be padded to 0x40 words */
+       for (; i & 0x3f; i++)
+               nv_wr32(priv, fuc_base + 0x0184, 0);
 }
 
 static void
@@ -1259,10 +1263,14 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_graph_oclass *oclass = (void *)bclass;
        struct nouveau_device *device = nv_device(parent);
        struct nvc0_graph_priv *priv;
+       bool use_ext_fw, enable;
        int ret, i;
 
-       ret = nouveau_graph_create(parent, engine, bclass,
-                                  (oclass->fecs.ucode != NULL), &priv);
+       use_ext_fw = nouveau_boolopt(device->cfgopt, "NvGrUseFW",
+                                    oclass->fecs.ucode == NULL);
+       enable = use_ext_fw || oclass->fecs.ucode != NULL;
+
+       ret = nouveau_graph_create(parent, engine, bclass, enable, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
@@ -1272,7 +1280,7 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 
        priv->base.units = nvc0_graph_units;
 
-       if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) {
+       if (use_ext_fw) {
                nv_info(priv, "using external firmware\n");
                if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) ||
                    nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) ||
index 90d44616c876e3d62d23dc619f16a6d24dab4b3a..75203a99d9021e7f18d1d7b721f6e10b2f5dba3a 100644 (file)
@@ -116,6 +116,7 @@ int  nvc0_graph_ctor(struct nouveau_object *, struct nouveau_object *,
                     struct nouveau_object **);
 void nvc0_graph_dtor(struct nouveau_object *);
 int  nvc0_graph_init(struct nouveau_object *);
+int  nve4_graph_fini(struct nouveau_object *, bool);
 int  nve4_graph_init(struct nouveau_object *);
 
 extern struct nouveau_oclass nvc0_graph_sclass[];
@@ -217,6 +218,7 @@ extern const struct nvc0_graph_init nve4_graph_init_main_0[];
 extern const struct nvc0_graph_init nve4_graph_init_tpccs_0[];
 extern const struct nvc0_graph_init nve4_graph_init_pe_0[];
 extern const struct nvc0_graph_init nve4_graph_init_be_0[];
+extern const struct nvc0_graph_pack nve4_graph_pack_mmio[];
 
 extern const struct nvc0_graph_init nvf0_graph_init_fe_0[];
 extern const struct nvc0_graph_init nvf0_graph_init_sked_0[];
index f7c0112171750253214a111931e7ffe3bb9c1c81..51e0c075ad342878b876f2828db31cd19a82aa9b 100644 (file)
@@ -151,7 +151,7 @@ nve4_graph_init_be_0[] = {
        {}
 };
 
-static const struct nvc0_graph_pack
+const struct nvc0_graph_pack
 nve4_graph_pack_mmio[] = {
        { nve4_graph_init_main_0 },
        { nvc0_graph_init_fe_0 },
@@ -189,7 +189,7 @@ nve4_graph_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
-static int
+int
 nve4_graph_fini(struct nouveau_object *object, bool suspend)
 {
        struct nvc0_graph_priv *priv = (void *)object;
index 26b6b2bb11121e28d4de88f08d4f308ab02fed7a..b639eb2c74ffc2cd087be99336f5774a3a6b4f91 100644 (file)
@@ -109,6 +109,7 @@ extern struct nouveau_oclass *nv50_fifo_oclass;
 extern struct nouveau_oclass *nv84_fifo_oclass;
 extern struct nouveau_oclass *nvc0_fifo_oclass;
 extern struct nouveau_oclass *nve0_fifo_oclass;
+extern struct nouveau_oclass *gk20a_fifo_oclass;
 extern struct nouveau_oclass *nv108_fifo_oclass;
 
 void nv04_fifo_intr(struct nouveau_subdev *);
index 871edfdf3d5ba4b91c87fafef697d61244b4e8a3..8c1d4772da0ccbd29e0dce305635e0c7dbbf8057 100644 (file)
@@ -68,6 +68,7 @@ extern struct nouveau_oclass *nvc8_graph_oclass;
 extern struct nouveau_oclass *nvd7_graph_oclass;
 extern struct nouveau_oclass *nvd9_graph_oclass;
 extern struct nouveau_oclass *nve4_graph_oclass;
+extern struct nouveau_oclass *gk20a_graph_oclass;
 extern struct nouveau_oclass *nvf0_graph_oclass;
 extern struct nouveau_oclass *nv108_graph_oclass;
 extern struct nouveau_oclass *gm107_graph_oclass;
index 8f4ced75444a95478887b4be5791fc99dd3499dc..c01e29c9f89ac023ce24c9229fe1cdf14e5c4c16 100644 (file)
@@ -77,6 +77,8 @@ struct nouveau_clock {
        int tstate; /* thermal adjustment (max-) */
        int dstate; /* display adjustment (min+) */
 
+       bool allow_reclock;
+
        int  (*read)(struct nouveau_clock *, enum nv_clk_src);
        int  (*calc)(struct nouveau_clock *, struct nouveau_cstate *);
        int  (*prog)(struct nouveau_clock *);
@@ -106,8 +108,8 @@ struct nouveau_clocks {
        int mdiv;
 };
 
-#define nouveau_clock_create(p,e,o,i,d)                                        \
-       nouveau_clock_create_((p), (e), (o), (i), sizeof(**d), (void **)d)
+#define nouveau_clock_create(p,e,o,i,r,d)                                      \
+       nouveau_clock_create_((p), (e), (o), (i), (r), sizeof(**d), (void **)d)
 #define nouveau_clock_destroy(p) ({                                            \
        struct nouveau_clock *clk = (p);                                       \
        _nouveau_clock_dtor(nv_object(clk));                                   \
@@ -121,7 +123,7 @@ struct nouveau_clocks {
 
 int  nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *,
                           struct nouveau_oclass *,
-                          struct nouveau_clocks *, int, void **);
+                          struct nouveau_clocks *, bool, int, void **);
 void _nouveau_clock_dtor(struct nouveau_object *);
 int _nouveau_clock_init(struct nouveau_object *);
 #define _nouveau_clock_fini _nouveau_subdev_fini
index 58c7ccdebb018787aa829961ac38f36059806ee7..871e73914b24eb7b75ca6d2d952a16ed4cc72ecc 100644 (file)
@@ -105,6 +105,7 @@ extern struct nouveau_oclass *nvaa_fb_oclass;
 extern struct nouveau_oclass *nvaf_fb_oclass;
 extern struct nouveau_oclass *nvc0_fb_oclass;
 extern struct nouveau_oclass *nve0_fb_oclass;
+extern struct nouveau_oclass *gk20a_fb_oclass;
 extern struct nouveau_oclass *gm107_fb_oclass;
 
 #include <subdev/bios/ramcfg.h>
index 88814f159d896a86709de0bbe3666fa435e2e994..31df634c0fdcaf775166b34ffc8a7ac54982ad75 100644 (file)
@@ -30,5 +30,6 @@ nouveau_ibus(void *obj)
 
 extern struct nouveau_oclass nvc0_ibus_oclass;
 extern struct nouveau_oclass nve0_ibus_oclass;
+extern struct nouveau_oclass gk20a_ibus_oclass;
 
 #endif
index bdf594116f3f2a1ab49698669ccf7a2b641c91ee..73b1ed20c8d597b5d6b4c9f67f91b24cb3814d30 100644 (file)
@@ -118,8 +118,10 @@ nouveau_bar_create_(struct nouveau_object *parent,
        if (ret)
                return ret;
 
-       bar->iomem = ioremap(nv_device_resource_start(device, 3),
-                            nv_device_resource_len(device, 3));
+       if (nv_device_resource_len(device, 3) != 0)
+               bar->iomem = ioremap(nv_device_resource_start(device, 3),
+                                    nv_device_resource_len(device, 3));
+
        return 0;
 }
 
index 3f30db62e6563d483d0a330aafe353692865c1c0..ca8139b9ab270f8a61ae836a8abfa62414a84654 100644 (file)
 
 #include "priv.h"
 
+struct nvc0_bar_priv_vm {
+       struct nouveau_gpuobj *mem;
+       struct nouveau_gpuobj *pgd;
+       struct nouveau_vm *vm;
+};
+
 struct nvc0_bar_priv {
        struct nouveau_bar base;
        spinlock_t lock;
-       struct {
-               struct nouveau_gpuobj *mem;
-               struct nouveau_gpuobj *pgd;
-               struct nouveau_vm *vm;
-       } bar[2];
+       struct nvc0_bar_priv_vm bar[2];
 };
 
 static int
@@ -79,87 +81,87 @@ nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma)
 }
 
 static int
-nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-             struct nouveau_oclass *oclass, void *data, u32 size,
-             struct nouveau_object **pobject)
+nvc0_bar_init_vm(struct nvc0_bar_priv *priv, struct nvc0_bar_priv_vm *bar_vm,
+                int bar_nr)
 {
-       struct nouveau_device *device = nv_device(parent);
-       struct nvc0_bar_priv *priv;
-       struct nouveau_gpuobj *mem;
+       struct nouveau_device *device = nv_device(&priv->base);
        struct nouveau_vm *vm;
+       resource_size_t bar_len;
        int ret;
 
-       ret = nouveau_bar_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       /* BAR3 */
        ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
-                               &priv->bar[0].mem);
-       mem = priv->bar[0].mem;
+                               &bar_vm->mem);
        if (ret)
                return ret;
 
        ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0,
-                               &priv->bar[0].pgd);
+                               &bar_vm->pgd);
        if (ret)
                return ret;
 
-       ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm);
+       bar_len = nv_device_resource_len(device, bar_nr);
+
+       ret = nouveau_vm_new(device, 0, bar_len, 0, &vm);
        if (ret)
                return ret;
 
        atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
 
-       ret = nouveau_gpuobj_new(nv_object(priv), NULL,
-                                (nv_device_resource_len(device, 3) >> 12) * 8,
-                                0x1000, NVOBJ_FLAG_ZERO_ALLOC,
-                                &vm->pgt[0].obj[0]);
-       vm->pgt[0].refcount[0] = 1;
-       if (ret)
-               return ret;
+       /*
+        * Bootstrap page table lookup.
+        */
+       if (bar_nr == 3) {
+               ret = nouveau_gpuobj_new(nv_object(priv), NULL,
+                                        (bar_len >> 12) * 8, 0x1000,
+                                        NVOBJ_FLAG_ZERO_ALLOC,
+                                       &vm->pgt[0].obj[0]);
+               vm->pgt[0].refcount[0] = 1;
+               if (ret)
+                       return ret;
+       }
 
-       ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd);
+       ret = nouveau_vm_ref(vm, &bar_vm->vm, bar_vm->pgd);
        nouveau_vm_ref(NULL, &vm, NULL);
        if (ret)
                return ret;
 
-       nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr));
-       nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr));
-       nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1));
-       nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1));
+       nv_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr));
+       nv_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr));
+       nv_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1));
+       nv_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1));
 
-       /* BAR1 */
-       ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0,
-                               &priv->bar[1].mem);
-       mem = priv->bar[1].mem;
-       if (ret)
-               return ret;
+       return 0;
+}
 
-       ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0,
-                               &priv->bar[1].pgd);
-       if (ret)
-               return ret;
+static int
+nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+             struct nouveau_oclass *oclass, void *data, u32 size,
+             struct nouveau_object **pobject)
+{
+       struct nouveau_device *device = nv_device(parent);
+       struct nvc0_bar_priv *priv;
+       bool has_bar3 = nv_device_resource_len(device, 3) != 0;
+       int ret;
 
-       ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm);
+       ret = nouveau_bar_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
        if (ret)
                return ret;
 
-       atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]);
+       /* BAR3 */
+       if (has_bar3) {
+               ret = nvc0_bar_init_vm(priv, &priv->bar[0], 3);
+               if (ret)
+                       return ret;
+               priv->base.alloc = nouveau_bar_alloc;
+               priv->base.kmap = nvc0_bar_kmap;
+       }
 
-       ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd);
-       nouveau_vm_ref(NULL, &vm, NULL);
+       /* BAR1 */
+       ret = nvc0_bar_init_vm(priv, &priv->bar[1], 1);
        if (ret)
                return ret;
 
-       nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr));
-       nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr));
-       nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1));
-       nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1));
-
-       priv->base.alloc = nouveau_bar_alloc;
-       priv->base.kmap = nvc0_bar_kmap;
        priv->base.umap = nvc0_bar_umap;
        priv->base.unmap = nvc0_bar_unmap;
        priv->base.flush = nv84_bar_flush;
@@ -201,7 +203,9 @@ nvc0_bar_init(struct nouveau_object *object)
        nv_mask(priv, 0x100c80, 0x00000001, 0x00000000);
 
        nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12);
-       nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12);
+       if (priv->bar[0].mem)
+               nv_wr32(priv, 0x001714,
+                       0xc0000000 | priv->bar[0].mem->addr >> 12);
        return 0;
 }
 
index 222e8ebb669dff496534331682e7a77c7e6bd9e0..d45704a2c2df5b6aa1b95eda83d990995955e4c5 100644 (file)
@@ -183,10 +183,11 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
                goto out;
 
        bios->data = kmalloc(bios->size, GFP_KERNEL);
-       if (bios->data) {
-               for (i = 0; i < bios->size; i += 4)
-                       ((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i);
-       }
+       if (!bios->data)
+               goto out;
+
+       for (i = 0; i < bios->size; i += 4)
+               ((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i);
 
        /* check the PCI record header */
        pcir = nv_ro16(bios, 0x0018);
index dd62baead39c54c9a906939576553b59bf9355a2..22351f594d2aaa72713fbb3d56f5151ec4c34e20 100644 (file)
@@ -346,8 +346,8 @@ nouveau_clock_ustate_update(struct nouveau_clock *clk, int req)
        struct nouveau_pstate *pstate;
        int i = 0;
 
-       /* YKW repellant */
-       return -ENOSYS;
+       if (!clk->allow_reclock)
+               return -ENOSYS;
 
        if (req != -1 && req != -2) {
                list_for_each_entry(pstate, &clk->states, head) {
@@ -456,6 +456,7 @@ nouveau_clock_create_(struct nouveau_object *parent,
                      struct nouveau_object *engine,
                      struct nouveau_oclass *oclass,
                      struct nouveau_clocks *clocks,
+                     bool allow_reclock,
                      int length, void **object)
 {
        struct nouveau_device *device = nv_device(parent);
@@ -478,6 +479,8 @@ nouveau_clock_create_(struct nouveau_object *parent,
                ret = nouveau_pstate_new(clk, idx++);
        } while (ret == 0);
 
+       clk->allow_reclock = allow_reclock;
+
        mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen);
        if (mode) {
                if (!strncasecmpz(mode, "disabled", arglen)) {
index b74db6cfc4e21ee8f811a08e54da3dfdc7f824a1..eb2d4425a49e45e87fe49983fda2fe48c69adf88 100644 (file)
@@ -82,7 +82,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, false,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index db7346f79080a2345c7a08c943ee934b4055a569..8a9e168397912f3d040846f548e5852ed1ca6c61 100644 (file)
@@ -213,7 +213,8 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv40_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, true,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index 250a6d96016bff563946563e93d2aec4a3eeba13..8c132772ba9ea526a5cd2f9339ace5e6a22fd299 100644 (file)
@@ -507,7 +507,7 @@ nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        int ret;
 
        ret = nouveau_clock_create(parent, engine, oclass, pclass->domains,
-                                 &priv);
+                                  false, &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index 4f5a1373f002b9c09e55f36e8a0acd24fd18ec46..9fb58354a80bd12d3be11866bff5078c23f55494 100644 (file)
@@ -302,7 +302,8 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nva3_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, false,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index 7a723b4f564d18f7506506a6f388db9de378ac9d..6a65fc9e9663a2187c4826efa4ddbb8e31400211 100644 (file)
@@ -421,7 +421,8 @@ nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvaa_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, true,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index c3105720ed246c08064c53c92d73db898366bdf7..dbf8517f54da906fc4ad634950217977565092f8 100644 (file)
@@ -437,7 +437,8 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nvc0_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, false,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
index d3c37c96f0e7eaeed97c08749bc23611642705db..4ac1aa30ea11f156adc347cc87839ae72ef7ebd1 100644 (file)
@@ -473,7 +473,8 @@ nve0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nve0_clock_priv *priv;
        int ret;
 
-       ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, &priv);
+       ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, true,
+                                  &priv);
        *pobject = nv_object(priv);
        if (ret)
                return ret;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c
new file mode 100644 (file)
index 0000000..a16024a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "nvc0.h"
+
+struct gk20a_fb_priv {
+       struct nouveau_fb base;
+};
+
+static int
+gk20a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+            struct nouveau_oclass *oclass, void *data, u32 size,
+            struct nouveau_object **pobject)
+{
+       struct gk20a_fb_priv *priv;
+       int ret;
+
+       ret = nouveau_fb_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+struct nouveau_oclass *
+gk20a_fb_oclass = &(struct nouveau_fb_impl) {
+       .base.handle = NV_SUBDEV(FB, 0xea),
+       .base.ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gk20a_fb_ctor,
+               .dtor = _nouveau_fb_dtor,
+               .init = _nouveau_fb_init,
+               .fini = _nouveau_fb_fini,
+       },
+       .memtype = nvc0_fb_memtype_valid,
+       .ram = &gk20a_ram_oclass,
+}.base;
index da74c889aed47a01b9a51eec66e3e22a5ca7fe9a..82273f832e42ef1fa5d7993e8db299c6e74be499 100644 (file)
@@ -32,6 +32,7 @@ extern struct nouveau_oclass nva3_ram_oclass;
 extern struct nouveau_oclass nvaa_ram_oclass;
 extern struct nouveau_oclass nvc0_ram_oclass;
 extern struct nouveau_oclass nve0_ram_oclass;
+extern struct nouveau_oclass gk20a_ram_oclass;
 extern struct nouveau_oclass gm107_ram_oclass;
 
 int nouveau_sddr3_calc(struct nouveau_ram *ram);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c
new file mode 100644 (file)
index 0000000..4d77d75
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "priv.h"
+
+#include <subdev/fb.h>
+
+struct gk20a_mem {
+       struct nouveau_mem base;
+       void *cpuaddr;
+       dma_addr_t handle;
+};
+#define to_gk20a_mem(m) container_of(m, struct gk20a_mem, base)
+
+static void
+gk20a_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
+{
+       struct device *dev = nv_device_base(nv_device(pfb));
+       struct gk20a_mem *mem = to_gk20a_mem(*pmem);
+
+       *pmem = NULL;
+       if (unlikely(mem == NULL))
+               return;
+
+       if (likely(mem->cpuaddr))
+               dma_free_coherent(dev, mem->base.size << PAGE_SHIFT,
+                                 mem->cpuaddr, mem->handle);
+
+       kfree(mem->base.pages);
+       kfree(mem);
+}
+
+static int
+gk20a_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,
+            u32 memtype, struct nouveau_mem **pmem)
+{
+       struct device *dev = nv_device_base(nv_device(pfb));
+       struct gk20a_mem *mem;
+       u32 type = memtype & 0xff;
+       u32 npages, order;
+       int i;
+
+       nv_debug(pfb, "%s: size: %llx align: %x, ncmin: %x\n", __func__, size,
+                align, ncmin);
+
+       npages = size >> PAGE_SHIFT;
+       if (npages == 0)
+               npages = 1;
+
+       if (align == 0)
+               align = PAGE_SIZE;
+       align >>= PAGE_SHIFT;
+
+       /* round alignment to the next power of 2, if needed */
+       order = fls(align);
+       if ((align & (align - 1)) == 0)
+               order--;
+       align = BIT(order);
+
+       /* ensure returned address is correctly aligned */
+       npages = max(align, npages);
+
+       mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+       if (!mem)
+               return -ENOMEM;
+
+       mem->base.size = npages;
+       mem->base.memtype = type;
+
+       mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages, GFP_KERNEL);
+       if (!mem->base.pages) {
+               kfree(mem);
+               return -ENOMEM;
+       }
+
+       *pmem = &mem->base;
+
+       mem->cpuaddr = dma_alloc_coherent(dev, npages << PAGE_SHIFT,
+                                         &mem->handle, GFP_KERNEL);
+       if (!mem->cpuaddr) {
+               nv_error(pfb, "%s: cannot allocate memory!\n", __func__);
+               gk20a_ram_put(pfb, pmem);
+               return -ENOMEM;
+       }
+
+       align <<= PAGE_SHIFT;
+
+       /* alignment check */
+       if (unlikely(mem->handle & (align - 1)))
+               nv_warn(pfb, "memory not aligned as requested: %pad (0x%x)\n",
+                       &mem->handle, align);
+
+       nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %pad, vaddr: %p\n",
+                npages << PAGE_SHIFT, align, &mem->handle, mem->cpuaddr);
+
+       for (i = 0; i < npages; i++)
+               mem->base.pages[i] = mem->handle + (PAGE_SIZE * i);
+
+       mem->base.offset = (u64)mem->base.pages[0];
+
+       return 0;
+}
+
+static int
+gk20a_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+             struct nouveau_oclass *oclass, void *data, u32 datasize,
+             struct nouveau_object **pobject)
+{
+       struct nouveau_ram *ram;
+       int ret;
+
+       ret = nouveau_ram_create(parent, engine, oclass, &ram);
+       *pobject = nv_object(ram);
+       if (ret)
+               return ret;
+       ram->type = NV_MEM_TYPE_STOLEN;
+       ram->size = get_num_physpages() << PAGE_SHIFT;
+
+       ram->get = gk20a_ram_get;
+       ram->put = gk20a_ram_put;
+
+       return 0;
+}
+
+struct nouveau_oclass
+gk20a_ram_oclass = {
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gk20a_ram_ctor,
+               .dtor = _nouveau_ram_dtor,
+               .init = _nouveau_ram_init,
+               .fini = _nouveau_ram_fini,
+       },
+};
index ef91b6e893afc4c4ca488453ea9f19ced5fa5861..e5d12c24cc43e132df49142ba23256c7e99599f5 100644 (file)
@@ -211,7 +211,7 @@ nv50_ram_prog(struct nouveau_fb *pfb)
        struct nv50_ram *ram = (void *)pfb->ram;
        struct nv50_ramseq *hwsq = &ram->hwsq;
 
-       ram_exec(hwsq, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
+       ram_exec(hwsq, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
        return 0;
 }
 
index 6eb97f16fbda97f40b1c0a9efbed47aacf030104..8076fb195dd514569466ae95d1ee12ef929ffab9 100644 (file)
@@ -309,7 +309,7 @@ nva3_ram_prog(struct nouveau_fb *pfb)
        struct nouveau_device *device = nv_device(pfb);
        struct nva3_ram *ram = (void *)pfb->ram;
        struct nva3_ramfuc *fuc = &ram->fuc;
-       ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
+       ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
        return 0;
 }
 
index 8edc92224c84a2ce31b3c5115ff0f31f7c37e0e4..5a6a5027f749f4b20cfd2cfc737be3d719e191ab 100644 (file)
@@ -408,7 +408,7 @@ nvc0_ram_prog(struct nouveau_fb *pfb)
        struct nouveau_device *device = nv_device(pfb);
        struct nvc0_ram *ram = (void *)pfb->ram;
        struct nvc0_ramfuc *fuc = &ram->fuc;
-       ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
+       ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
        return 0;
 }
 
index 16752192cf87acbb5e77a904fb3474e7f2de46d6..84c7efbc4f38bc1e72ca9530bdfb966ecd0805b3 100644 (file)
@@ -1111,7 +1111,7 @@ nve0_ram_prog(struct nouveau_fb *pfb)
        struct nouveau_device *device = nv_device(pfb);
        struct nve0_ram *ram = (void *)pfb->ram;
        struct nve0_ramfuc *fuc = &ram->fuc;
-       ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
+       ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
        return (ram->base.next == &ram->base.xition);
 }
 
index 16b8c5bf5efa90574495c3fb6530d9a66f487f8b..8988621373b071969727b35109a9fc49613d8b0e 100644 (file)
@@ -44,7 +44,7 @@ nve0_gpio_intr(struct nouveau_subdev *subdev)
        }
 
        nv_wr32(priv, 0xdc00, intr0);
-       nv_wr32(priv, 0xdc88, intr1);
+       nv_wr32(priv, 0xdc80, intr1);
 }
 
 void
@@ -52,8 +52,8 @@ nve0_gpio_intr_enable(struct nouveau_event *event, int line)
 {
        const u32 addr = line < 16 ? 0xdc00 : 0xdc80;
        const u32 mask = 0x00010001 << (line & 0xf);
-       nv_wr32(event->priv, addr + 0x08, mask);
-       nv_mask(event->priv, addr + 0x00, mask, mask);
+       nv_wr32(event->priv, addr + 0x00, mask);
+       nv_mask(event->priv, addr + 0x08, mask, mask);
 }
 
 void
@@ -61,8 +61,8 @@ nve0_gpio_intr_disable(struct nouveau_event *event, int line)
 {
        const u32 addr = line < 16 ? 0xdc00 : 0xdc80;
        const u32 mask = 0x00010001 << (line & 0xf);
-       nv_wr32(event->priv, addr + 0x08, mask);
-       nv_mask(event->priv, addr + 0x00, mask, 0x00000000);
+       nv_mask(event->priv, addr + 0x08, mask, 0x00000000);
+       nv_wr32(event->priv, addr + 0x00, mask);
 }
 
 int
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ibus/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/ibus/gk20a.c
new file mode 100644 (file)
index 0000000..245f0eb
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <subdev/ibus.h>
+#include <subdev/timer.h>
+
+struct gk20a_ibus_priv {
+       struct nouveau_ibus base;
+};
+
+static void
+gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv)
+{
+       nv_mask(priv, 0x137250, 0x3f, 0);
+
+       nv_mask(priv, 0x000200, 0x20, 0);
+       usleep_range(20, 30);
+       nv_mask(priv, 0x000200, 0x20, 0x20);
+
+       nv_wr32(priv, 0x12004c, 0x4);
+       nv_wr32(priv, 0x122204, 0x2);
+       nv_rd32(priv, 0x122204);
+}
+
+static void
+gk20a_ibus_intr(struct nouveau_subdev *subdev)
+{
+       struct gk20a_ibus_priv *priv = (void *)subdev;
+       u32 status0 = nv_rd32(priv, 0x120058);
+
+       if (status0 & 0x7) {
+               nv_debug(priv, "resetting priv ring\n");
+               gk20a_ibus_init_priv_ring(priv);
+       }
+
+       /* Acknowledge interrupt */
+       nv_mask(priv, 0x12004c, 0x2, 0x2);
+
+       if (!nv_wait(subdev, 0x12004c, 0x3f, 0x00))
+               nv_warn(priv, "timeout waiting for ringmaster ack\n");
+}
+
+static int
+gk20a_ibus_init(struct nouveau_object *object)
+{
+       struct gk20a_ibus_priv *priv = (void *)object;
+       int ret;
+
+       ret = _nouveau_ibus_init(object);
+       if (ret)
+               return ret;
+
+       gk20a_ibus_init_priv_ring(priv);
+
+       return 0;
+}
+
+static int
+gk20a_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+              struct nouveau_oclass *oclass, void *data, u32 size,
+              struct nouveau_object **pobject)
+{
+       struct gk20a_ibus_priv *priv;
+       int ret;
+
+       ret = nouveau_ibus_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       nv_subdev(priv)->intr = gk20a_ibus_intr;
+       return 0;
+}
+
+struct nouveau_oclass
+gk20a_ibus_oclass = {
+       .handle = NV_SUBDEV(IBUS, 0xea),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = gk20a_ibus_ctor,
+               .dtor = _nouveau_ibus_dtor,
+               .init = gk20a_ibus_init,
+               .fini = _nouveau_ibus_fini,
+       },
+};
index e8822a934c485742f9b2e8452225ec93ddec5f07..90d8bf8ce0dc5039735f46953e0ac0e134de8869 100644 (file)
@@ -26,6 +26,7 @@
 
 const struct nouveau_mc_intr
 nv50_mc_intr[] = {
+       { 0x04000000, NVDEV_ENGINE_DISP },  /* DISP before FIFO, so pageflip-timestamping works! */
        { 0x00000001, NVDEV_ENGINE_MPEG },
        { 0x00000100, NVDEV_ENGINE_FIFO },
        { 0x00001000, NVDEV_ENGINE_GR },
@@ -34,7 +35,6 @@ nv50_mc_intr[] = {
        { 0x00020000, NVDEV_ENGINE_VP },        /* NV84- */
        { 0x00100000, NVDEV_SUBDEV_TIMER },
        { 0x00200000, NVDEV_SUBDEV_GPIO },
-       { 0x04000000, NVDEV_ENGINE_DISP },
        { 0x10000000, NVDEV_SUBDEV_BUS },
        { 0x80000000, NVDEV_ENGINE_SW },
        { 0x0002d101, NVDEV_SUBDEV_FB },
index f8a6f18e2d3408f55b1447e55144e24ded4036f9..95b3d35388a86ee71d893d01b539f4087f1dd9e5 100644 (file)
@@ -26,6 +26,7 @@
 
 static const struct nouveau_mc_intr
 nv98_mc_intr[] = {
+       { 0x04000000, NVDEV_ENGINE_DISP },  /* DISP first, so pageflip timestamps work */
        { 0x00000001, NVDEV_ENGINE_PPP },
        { 0x00000100, NVDEV_ENGINE_FIFO },
        { 0x00001000, NVDEV_ENGINE_GR },
@@ -37,7 +38,6 @@ nv98_mc_intr[] = {
        { 0x00100000, NVDEV_SUBDEV_TIMER },
        { 0x00200000, NVDEV_SUBDEV_GPIO },
        { 0x00400000, NVDEV_ENGINE_COPY0 },     /* NVA3-     */
-       { 0x04000000, NVDEV_ENGINE_DISP },
        { 0x10000000, NVDEV_SUBDEV_BUS },
        { 0x80000000, NVDEV_ENGINE_SW },
        { 0x0042d101, NVDEV_SUBDEV_FB },
index 34472d3170974ca8e6207afe0a347f332130d6bd..ac7f99a15fa7b530e47316919a2aee655817f5a3 100644 (file)
@@ -26,6 +26,7 @@
 
 const struct nouveau_mc_intr
 nvc0_mc_intr[] = {
+       { 0x04000000, NVDEV_ENGINE_DISP },  /* DISP first, so pageflip timestamps work. */
        { 0x00000001, NVDEV_ENGINE_PPP },
        { 0x00000020, NVDEV_ENGINE_COPY0 },
        { 0x00000040, NVDEV_ENGINE_COPY1 },
@@ -40,7 +41,6 @@ nvc0_mc_intr[] = {
        { 0x00200000, NVDEV_SUBDEV_GPIO },
        { 0x01000000, NVDEV_SUBDEV_PWR },
        { 0x02000000, NVDEV_SUBDEV_LTCG },
-       { 0x04000000, NVDEV_ENGINE_DISP },
        { 0x08000000, NVDEV_SUBDEV_FB },
        { 0x10000000, NVDEV_SUBDEV_BUS },
        { 0x40000000, NVDEV_SUBDEV_IBUS },
index 7610fc5f8fa256de8038e3770ca227a3d0150c64..ca9ad9fd47be35b0fa491e301c95f0b1fda053ff 100644 (file)
@@ -60,9 +60,9 @@ static struct nouveau_i2c_board_info
 nv_board_infos[] = {
        { { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 0 },
        { { I2C_BOARD_INFO("w83781d", 0x2d) }, 0  },
-       { { I2C_BOARD_INFO("adt7473", 0x2e) }, 20  },
-       { { I2C_BOARD_INFO("adt7473", 0x2d) }, 20  },
-       { { I2C_BOARD_INFO("adt7473", 0x2c) }, 20  },
+       { { I2C_BOARD_INFO("adt7473", 0x2e) }, 40  },
+       { { I2C_BOARD_INFO("adt7473", 0x2d) }, 40  },
+       { { I2C_BOARD_INFO("adt7473", 0x2c) }, 40  },
        { { I2C_BOARD_INFO("f75375", 0x2e) }, 0  },
        { { I2C_BOARD_INFO("lm99", 0x4c) }, 0  },
        { { I2C_BOARD_INFO("lm90", 0x4c) }, 0  },
index 3b2c4580098bafea567ebadd0cfdb972adeadf93..0478b2e3fb1de76ee34e40a56e0d6209ffff1d60 100644 (file)
@@ -36,7 +36,7 @@ nva3_therm_fan_sense(struct nouveau_therm *therm)
        u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff;
        u32 ctrl = nv_rd32(therm, 0x00e720);
        if (ctrl & 0x00000001)
-               return tach * 60;
+               return tach * 60 / 2;
        return -ENODEV;
 }
 
index da764a4ed9588273fe6cf02ed0d6c589aa2ebda0..26fbc4f43a5feef6f5b0efa361ba3ff6ec7a8706 100644 (file)
@@ -798,6 +798,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
        struct drm_device *dev = drm->dev;
        struct nouveau_page_flip_state *s;
        unsigned long flags;
+       int crtcid = -1;
 
        spin_lock_irqsave(&dev->event_lock, flags);
 
@@ -808,8 +809,13 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
        }
 
        s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
-       if (s->event)
-               drm_send_vblank_event(dev, s->crtc, s->event);
+       if (s->event) {
+               /* Vblank timestamps/counts are only correct on >= NV-50 */
+               if (nv_device(drm->device)->card_type >= NV_50)
+                       crtcid = s->crtc;
+
+               drm_send_vblank_event(dev, crtcid, s->event);
+       }
 
        list_del(&s->head);
        if (ps)
index 79f6dc724a85f749c66ee1411a2aac7c00daf644..3c58854aff03832a539586f7985b79b2f8f9327a 100644 (file)
@@ -1,4 +1,4 @@
-       /*
+/*
  * Copyright 2011 Red Hat Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -957,7 +957,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
 
        nv50_display_flip_stop(crtc);
 
-       push = evo_wait(mast, 2);
+       push = evo_wait(mast, 6);
        if (push) {
                if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {
                        evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);