aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/include/asm/topology.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/include/asm/topology.h')
-rw-r--r--arch/s390/include/asm/topology.h13
1 files changed, 1 insertions, 12 deletions
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index 05425b18c0a..56af53093d2 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -26,21 +26,12 @@ extern struct cpu_topology_s390 cpu_topology[NR_CPUS];
#define mc_capable() 1
-static inline const struct cpumask *cpu_coregroup_mask(int cpu)
-{
- return &cpu_topology[cpu].core_mask;
-}
-
-static inline const struct cpumask *cpu_book_mask(int cpu)
-{
- return &cpu_topology[cpu].book_mask;
-}
-
int topology_cpu_init(struct cpu *);
int topology_set_cpu_management(int fc);
void topology_schedule_update(void);
void store_topology(struct sysinfo_15_1_x *info);
void topology_expect_change(void);
+const struct cpumask *cpu_coregroup_mask(int cpu);
#else /* CONFIG_SCHED_BOOK */
@@ -64,8 +55,6 @@ static inline void s390_init_cpu_topology(void)
};
#endif
-#define SD_BOOK_INIT SD_CPU_INIT
-
#include <asm-generic/topology.h>
#endif /* _ASM_S390_TOPOLOGY_H */
s='rem' style='width: 0.0%;'/> -rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nva3.c25
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/copy/nve0.c53
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/base.c566
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/ctrl.c144
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/gm100.c106
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv04.c89
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv10.c204
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv20.c131
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv30.c153
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv40.c427
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nv50.c460
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nvc0.c348
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/nve0.c280
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/priv.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/base.c172
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/conn.c172
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/conn.h59
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.c399
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dport.h75
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/gm107.c101
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv04.c98
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c936
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h106
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c204
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c82
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva0.c76
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c49
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c806
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c206
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c101
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outp.c137
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outp.h59
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c278
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h65
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c180
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/priv.h42
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c54
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c184
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c120
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/vga.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/falcon.c278
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/base.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/gk20a.c35
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c191
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c37
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c6
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c47
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c66
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c582
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c802
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h18
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c53
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c991
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c599
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c4152
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h179
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c797
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c103
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c354
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c275
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c522
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c2788
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c1021
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c885
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc (renamed from drivers/gpu/drm/nouveau/core/engine/graph/fuc/nvc0.fuc)197
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc378
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc542
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h473
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc542
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h473
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc525
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h874
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc42
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h537
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc437
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h863
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc42
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h537
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc696
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc540
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h916
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc540
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h916
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc842
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h1538
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc40
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h1047
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc766
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h1469
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc40
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h1044
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc229
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/nve0.fuc400
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/fuc/os.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c47
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/gm107.c465
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv04.c16
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv10.c30
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv108.c223
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv20.c19
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv25.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv30.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv34.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv35.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.c28
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv50.c299
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c1281
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h187
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c133
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c128
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c115
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c136
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c191
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nve0.c576
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nve4.c360
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c244
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c68
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h15
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c102
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c194
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv84.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/base.c449
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c109
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c143
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h26
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c70
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c78
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c96
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c173
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h17
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c162
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c71
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h91
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c52
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/ppp/nvc0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv04.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv10.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv50.c124
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nv50.h47
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/software/nvc0.c148
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/vp/nv84.c27
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/vp/nv98.c110
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/vp/nvc0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/vp/nve0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/xtensa.c176
166 files changed, 31632 insertions, 13758 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c
index 1d9f614cb97..1e8e75c0684 100644
--- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv84.c
@@ -19,24 +19,19 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
- * Authors: Ben Skeggs
+ * Authors: Ben Skeggs, Ilia Mirkin
*/
-#include <core/engctx.h>
-#include <core/class.h>
-
+#include <engine/xtensa.h>
#include <engine/bsp.h>
-struct nv84_bsp_priv {
- struct nouveau_engine base;
-};
-
/*******************************************************************************
* BSP object classes
******************************************************************************/
static struct nouveau_oclass
nv84_bsp_sclass[] = {
+ { 0x74b0, &nouveau_object_ofuncs },
{},
};
@@ -48,7 +43,7 @@ static struct nouveau_oclass
nv84_bsp_cclass = {
.handle = NV_ENGCTX(BSP, 0x84),
.ofuncs = &(struct nouveau_ofuncs) {
- .ctor = _nouveau_engctx_ctor,
+ .ctor = _nouveau_xtensa_engctx_ctor,
.dtor = _nouveau_engctx_dtor,
.init = _nouveau_engctx_init,
.fini = _nouveau_engctx_fini,
@@ -66,10 +61,10 @@ nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
- struct nv84_bsp_priv *priv;
+ struct nouveau_xtensa *priv;
int ret;
- ret = nouveau_engine_create(parent, engine, oclass, true,
+ ret = nouveau_xtensa_create(parent, engine, oclass, 0x103000, true,
"PBSP", "bsp", &priv);
*pobject = nv_object(priv);
if (ret)
@@ -78,6 +73,8 @@ nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_subdev(priv)->unit = 0x04008000;
nv_engine(priv)->cclass = &nv84_bsp_cclass;
nv_engine(priv)->sclass = nv84_bsp_sclass;
+ priv->fifo_val = 0x1111;
+ priv->unkd28 = 0x90044;
return 0;
}
@@ -86,8 +83,10 @@ nv84_bsp_oclass = {
.handle = NV_ENGINE(BSP, 0x84),
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv84_bsp_ctor,
- .dtor = _nouveau_engine_dtor,
- .init = _nouveau_engine_init,
- .fini = _nouveau_engine_fini,
+ .dtor = _nouveau_xtensa_dtor,
+ .init = _nouveau_xtensa_init,
+ .fini = _nouveau_xtensa_fini,
+ .rd32 = _nouveau_xtensa_rd32,
+ .wr32 = _nouveau_xtensa_wr32,
},
};
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c
new file mode 100644
index 00000000000..6b089e022fd
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin
+ */
+
+#include <engine/falcon.h>
+#include <engine/bsp.h>
+
+struct nv98_bsp_priv {
+ struct nouveau_falcon base;
+};
+
+/*******************************************************************************
+ * BSP object classes
+ ******************************************************************************/
+
+static struct nouveau_oclass
+nv98_bsp_sclass[] = {
+ { 0x88b1, &nouveau_object_ofuncs },
+ { 0x85b1, &nouveau_object_ofuncs },
+ { 0x86b1, &nouveau_object_ofuncs },
+ {},
+};
+
+/*******************************************************************************
+ * PBSP context
+ ******************************************************************************/
+
+static struct nouveau_oclass
+nv98_bsp_cclass = {
+ .handle = NV_ENGCTX(BSP, 0x98),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nouveau_falcon_context_ctor,
+ .dtor = _nouveau_falcon_context_dtor,
+ .init = _nouveau_falcon_context_init,
+ .fini = _nouveau_falcon_context_fini,
+ .rd32 = _nouveau_falcon_context_rd32,
+ .wr32 = _nouveau_falcon_context_wr32,
+ },
+};
+
+/*******************************************************************************
+ * PBSP engine/subdev functions
+ ******************************************************************************/
+
+static int
+nv98_bsp_init(struct nouveau_object *object)
+{
+ struct nv98_bsp_priv *priv = (void *)object;
+ int ret;
+
+ ret = nouveau_falcon_init(&priv->base);
+ if (ret)
+ return ret;
+
+ nv_wr32(priv, 0x084010, 0x0000ffd2);
+ nv_wr32(priv, 0x08401c, 0x0000fff2);
+ return 0;
+}
+
+static int
+nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nv98_bsp_priv *priv;
+ int ret;
+
+ ret = nouveau_falcon_create(parent, engine, oclass, 0x084000, true,
+ "PBSP", "bsp", &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ nv_subdev(priv)->unit = 0x04008000;
+ nv_engine(priv)->cclass = &nv98_bsp_cclass;
+ nv_engine(priv)->sclass = nv98_bsp_sclass;
+ return 0;
+}
+
+struct nouveau_oclass
+nv98_bsp_oclass = {
+ .handle = NV_ENGINE(BSP, 0x98),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nv98_bsp_ctor,
+ .dtor = _nouveau_falcon_dtor,
+ .init = nv98_bsp_init,
+ .fini = _nouveau_falcon_fini,
+ .rd32 = _nouveau_falcon_rd32,
+ .wr32 = _nouveau_falcon_wr32,
+ },
+};
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c
index 0a5aa6bb087..ce860de43e6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nvc0.c
@@ -22,8 +22,7 @@
* Authors: Maarten Lankhorst
*/
-#include <core/falcon.h>
-
+#include <engine/falcon.h>
#include <engine/bsp.h>
struct nvc0_bsp_priv {
@@ -91,6 +90,7 @@ nvc0_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00008000;
+ nv_subdev(priv)->intr = nouveau_falcon_intr;
nv_engine(priv)->cclass = &nvc0_bsp_cclass;
nv_engine(priv)->sclass = nvc0_bsp_sclass;
return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c
index d4f23bbd75b..ba6aeca0285 100644
--- a/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nve0.c
@@ -22,8 +22,7 @@
* Authors: Ben Skeggs
*/
-#include <core/falcon.h>
-
+#include <engine/falcon.h>
#include <engine/bsp.h>
struct nve0_bsp_priv {
@@ -91,6 +90,7 @@ nve0_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00008000;
+ nv_subdev(priv)->intr = nouveau_falcon_intr;
nv_engine(priv)->cclass = &nve0_bsp_cclass;
nv_engine(priv)->sclass = nve0_bsp_sclass;
return 0;
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h
index c92520f3ed4..241b2720120 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nva3.fuc.h
@@ -1,4 +1,4 @@
-static u32 nva3_pcopy_data[] = {
+uint32_t nva3_pcopy_data[] = {
/* 0x0000: ctx_object */
0x00000000,
/* 0x0004: ctx_dma */
@@ -183,7 +183,7 @@ static u32 nva3_pcopy_data[] = {
0x00000800,
};
-static u32 nva3_pcopy_code[] = {
+uint32_t nva3_pcopy_code[] = {
/* 0x0000: main */
0x04fe04bd,
0x3517f000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h
index 0d98c6c0958..98cc4216a37 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/fuc/nvc0.fuc.h
@@ -1,4 +1,4 @@
-static u32 nvc0_pcopy_data[] = {
+uint32_t nvc0_pcopy_data[] = {
/* 0x0000: ctx_object */
0x00000000,
/* 0x0004: ctx_query_address_high */
@@ -171,7 +171,7 @@ static u32 nvc0_pcopy_data[] = {
0x00000800,
};
-static u32 nvc0_pcopy_code[] = {
+uint32_t nvc0_pcopy_code[] = {
/* 0x0000: main */
0x04fe04bd,
0x3517f000,
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
index 283248c7b05..f31527733e0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
@@ -22,15 +22,17 @@
* Authors: Ben Skeggs
*/
-#include <core/falcon.h>
-#include <core/class.h>
-#include <core/enum.h>
+#include <engine/falcon.h>
+#include <engine/fifo.h>
+#include <engine/copy.h>
#include <subdev/fb.h>
#include <subdev/vm.h>
-#include <engine/fifo.h>
-#include <engine/copy.h>
+#include <core/client.h>
+#include <core/class.h>
+#include <core/enum.h>
+
#include "fuc/nva3.fuc.h"
@@ -100,8 +102,9 @@ nva3_copy_intr(struct nouveau_subdev *subdev)
if (stat & 0x00000040) {
nv_error(falcon, "DISPATCH_ERROR [");
nouveau_enum_print(nva3_copy_isr_error_name, ssta);
- printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n",
- chid, inst << 12, subc, mthd, data);
+ pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n",
+ chid, inst << 12, nouveau_client_name(engctx), subc,
+ mthd, data);
nv_wo32(falcon, 0x004, 0x00000040);
stat &= ~0x00000040;
}
@@ -115,13 +118,6 @@ nva3_copy_intr(struct nouveau_subdev *subdev)
}
static int
-nva3_copy_tlb_flush(struct nouveau_engine *engine)
-{
- nv50_vm_flush_engine(&engine->base, 0x0d);
- return 0;
-}
-
-static int
nva3_copy_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
@@ -140,7 +136,6 @@ nva3_copy_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_subdev(priv)->intr = nva3_copy_intr;
nv_engine(priv)->cclass = &nva3_copy_cclass;
nv_engine(priv)->sclass = nva3_copy_sclass;
- nv_engine(priv)->tlb_flush = nva3_copy_tlb_flush;
nv_falcon(priv)->code.data = nva3_pcopy_code;
nv_falcon(priv)->code.size = sizeof(nva3_pcopy_code);
nv_falcon(priv)->data.data = nva3_pcopy_data;
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
index b3ed2737e21..ac3291f781f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c
@@ -22,13 +22,15 @@
* Authors: Ben Skeggs
*/
-#include <core/falcon.h>
-#include <core/class.h>
-#include <core/enum.h>
-
+#include <engine/falcon.h>
#include <engine/fifo.h>
#include <engine/copy.h>
+#include <core/class.h>
+#include <core/enum.h>
+#include <core/class.h>
+#include <core/enum.h>
+
#include "fuc/nvc0.fuc.h"
struct nvc0_copy_priv {
@@ -103,9 +105,6 @@ nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_copy_priv *priv;
int ret;
- if (nv_rd32(parent, 0x022500) & 0x00000100)
- return -ENODEV;
-
ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, true,
"PCE0", "copy0", &priv);
*pobject = nv_object(priv);
@@ -131,9 +130,6 @@ nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nvc0_copy_priv *priv;
int ret;
- if (nv_rd32(parent, 0x022500) & 0x00000200)
- return -ENODEV;
-
ret = nouveau_falcon_create(parent, engine, oclass, 0x105000, true,
"PCE1", "copy1", &priv);
*pobject = nv_object(priv);
diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
index dbbe9e8998f..748a61eb3c6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c
@@ -67,6 +67,19 @@ nve0_copy_cclass = {
* PCOPY engine/subdev functions
******************************************************************************/
+static void
+nve0_copy_intr(struct nouveau_subdev *subdev)
+{
+ const int ce = nv_subidx(nv_object(subdev)) - NVDEV_ENGINE_COPY0;
+ struct nve0_copy_priv *priv = (void *)subdev;
+ u32 stat = nv_rd32(priv, 0x104908 + (ce * 0x1000));
+
+ if (stat) {
+ nv_warn(priv, "unhandled intr 0x%08x\n", stat);
+ nv_wr32(priv, 0x104908 + (ce * 0x1000), stat);
+ }
+}
+
static int
nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -75,9 +88,6 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nve0_copy_priv *priv;
int ret;
- if (nv_rd32(parent, 0x022500) & 0x00000100)
- return -ENODEV;
-
ret = nouveau_engine_create(parent, engine, oclass, true,
"PCE0", "copy0", &priv);
*pobject = nv_object(priv);
@@ -85,6 +95,7 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00000040;
+ nv_subdev(priv)->intr = nve0_copy_intr;
nv_engine(priv)->cclass = &nve0_copy_cclass;
nv_engine(priv)->sclass = nve0_copy_sclass;
return 0;
@@ -98,9 +109,6 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nve0_copy_priv *priv;
int ret;
- if (nv_rd32(parent, 0x022500) & 0x00000200)
- return -ENODEV;
-
ret = nouveau_engine_create(parent, engine, oclass, true,
"PCE1", "copy1", &priv);
*pobject = nv_object(priv);
@@ -108,6 +116,28 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
return ret;
nv_subdev(priv)->unit = 0x00000080;
+ nv_subdev(priv)->intr = nve0_copy_intr;
+ nv_engine(priv)->cclass = &nve0_copy_cclass;
+ nv_engine(priv)->sclass = nve0_copy_sclass;
+ return 0;
+}
+
+static int
+nve0_copy2_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nve0_copy_priv *priv;
+ int ret;
+
+ ret = nouveau_engine_create(parent, engine, oclass, true,
+ "PCE2", "copy2", &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ nv_subdev(priv)->unit = 0x00200000;
+ nv_subdev(priv)->intr = nve0_copy_intr;
nv_engine(priv)->cclass = &nve0_copy_cclass;
nv_engine(priv)->sclass = nve0_copy_sclass;
return 0;
@@ -134,3 +164,14 @@ nve0_copy1_oclass = {
.fini = _nouveau_engine_fini,
},
};
+
+struct nouveau_oclass
+nve0_copy2_oclass = {
+ .handle = NV_ENGINE(COPY2, 0xe0),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nve0_copy2_ctor,
+ .dtor = _nouveau_engine_dtor,
+ .init = _nouveau_engine_init,
+ .fini = _nouveau_engine_fini,
+ },
+};
diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h
index 09962e4210e..38676c74e6e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h
+++ b/drivers/gpu/drm/nouveau/core/engine/crypt/fuc/nv98.fuc.h
@@ -1,4 +1,4 @@
-static uint32_t nv98_pcrypt_data[] = {
+uint32_t nv98_pcrypt_data[] = {
/* 0x0000: ctx_dma */
/* 0x0000: ctx_dma_query */
0x00000000,
@@ -150,7 +150,7 @@ static uint32_t nv98_pcrypt_data[] = {
0x00000000,
};
-static uint32_t nv98_pcrypt_code[] = {
+uint32_t nv98_pcrypt_code[] = {
0x17f004bd,
0x0010fe35,
0xf10004fe,
diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
index b9749051272..2551dafbec7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
@@ -22,6 +22,7 @@
* Authors: Ben Skeggs
*/
+#include <core/client.h>
#include <core/os.h>
#include <core/enum.h>
#include <core/class.h>
@@ -126,10 +127,11 @@ nv84_crypt_intr(struct nouveau_subdev *subdev)
chid = pfifo->chid(pfifo, engctx);
if (stat) {
- nv_error(priv, "");
+ nv_error(priv, "%s", "");
nouveau_bitfield_print(nv84_crypt_intr_mask, stat);
- printk(" ch %d [0x%010llx] mthd 0x%04x data 0x%08x\n",
- chid, (u64)inst << 12, mthd, data);
+ pr_cont(" ch %d [0x%010llx %s] mthd 0x%04x data 0x%08x\n",
+ chid, (u64)inst << 12, nouveau_client_name(engctx),
+ mthd, data);
}
nv_wr32(priv, 0x102130, stat);
@@ -139,13 +141,6 @@ nv84_crypt_intr(struct nouveau_subdev *subdev)
}
static int
-nv84_crypt_tlb_flush(struct nouveau_engine *engine)
-{
- nv50_vm_flush_engine(&engine->base, 0x0a);
- return 0;
-}
-
-static int
nv84_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
@@ -163,7 +158,6 @@ nv84_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_subdev(priv)->intr = nv84_crypt_intr;
nv_engine(priv)->cclass = &nv84_crypt_cclass;
nv_engine(priv)->sclass = nv84_crypt_sclass;
- nv_engine(priv)->tlb_flush = nv84_crypt_tlb_flush;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
index 21986f3bf0c..c7082377ec7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
+++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
@@ -22,15 +22,16 @@
* Authors: Ben Skeggs
*/
+#include <core/client.h>
#include <core/os.h>
#include <core/enum.h>
#include <core/class.h>
#include <core/engctx.h>
-#include <core/falcon.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
+#include <engine/falcon.h>
#include <engine/fifo.h>
#include <engine/crypt.h>
@@ -102,8 +103,9 @@ nv98_crypt_intr(struct nouveau_subdev *subdev)
if (stat & 0x00000040) {
nv_error(priv, "DISPATCH_ERROR [");
nouveau_enum_print(nv98_crypt_isr_error_name, ssta);
- printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n",
- chid, (u64)inst << 12, subc, mthd, data);
+ pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n",
+ chid, (u64)inst << 12, nouveau_client_name(engctx),
+ subc, mthd, data);
nv_wr32(priv, 0x087004, 0x00000040);
stat &= ~0x00000040;
}
@@ -117,13 +119,6 @@ nv98_crypt_intr(struct nouveau_subdev *subdev)
}
static int
-nv98_crypt_tlb_flush(struct nouveau_engine *engine)
-{
- nv50_vm_flush_engine(&engine->base, 0x0a);
- return 0;
-}
-
-static int
nv98_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
@@ -141,7 +136,6 @@ nv98_crypt_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_subdev(priv)->intr = nv98_crypt_intr;
nv_engine(priv)->cclass = &nv98_crypt_cclass;
nv_engine(priv)->sclass = nv98_crypt_sclass;
- nv_engine(priv)->tlb_flush = nv98_crypt_tlb_flush;
nv_falcon(priv)->code.data = nv98_pcrypt_code;
nv_falcon(priv)->code.size = sizeof(nv98_pcrypt_code);
nv_falcon(priv)->data.data = nv98_pcrypt_data;
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
new file mode 100644
index 00000000000..18c8c7245b7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <core/object.h>
+#include <core/device.h>
+#include <core/client.h>
+#include <core/option.h>
+
+#include <core/class.h>
+
+#include "priv.h"
+
+static DEFINE_MUTEX(nv_devices_mutex);
+static LIST_HEAD(nv_devices);
+
+struct nouveau_device *
+nouveau_device_find(u64 name)
+{
+ struct nouveau_device *device, *match = NULL;
+ mutex_lock(&nv_devices_mutex);
+ list_for_each_entry(device, &nv_devices, head) {
+ if (device->handle == name) {
+ match = device;
+ break;
+ }
+ }
+ mutex_unlock(&nv_devices_mutex);
+ return match;
+}
+
+/******************************************************************************
+ * nouveau_devobj (0x0080): class implementation
+ *****************************************************************************/
+struct nouveau_devobj {
+ struct nouveau_parent base;
+ struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
+};
+
+static const u64 disable_map[] = {
+ [NVDEV_SUBDEV_VBIOS] = NV_DEVICE_DISABLE_VBIOS,
+ [NVDEV_SUBDEV_DEVINIT] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_GPIO] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_I2C] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_MXM] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_BUS] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_LTCG] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_IBUS] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_VM] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_BAR] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_VOLT] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_SUBDEV_PWR] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_ENGINE_PERFMON] = NV_DEVICE_DISABLE_CORE,
+ [NVDEV_ENGINE_FIFO] = NV_DEVICE_DISABLE_FIFO,
+ [NVDEV_ENGINE_SW] = NV_DEVICE_DISABLE_FIFO,
+ [NVDEV_ENGINE_GR] = NV_DEVICE_DISABLE_GRAPH,
+ [NVDEV_ENGINE_MPEG] = NV_DEVICE_DISABLE_MPEG,
+ [NVDEV_ENGINE_ME] = NV_DEVICE_DISABLE_ME,
+ [NVDEV_ENGINE_VP] = NV_DEVICE_DISABLE_VP,
+ [NVDEV_ENGINE_CRYPT] = NV_DEVICE_DISABLE_CRYPT,
+ [NVDEV_ENGINE_BSP] = NV_DEVICE_DISABLE_BSP,
+ [NVDEV_ENGINE_PPP] = NV_DEVICE_DISABLE_PPP,
+ [NVDEV_ENGINE_COPY0] = NV_DEVICE_DISABLE_COPY0,
+ [NVDEV_ENGINE_COPY1] = NV_DEVICE_DISABLE_COPY1,
+ [NVDEV_ENGINE_VIC] = NV_DEVICE_DISABLE_VIC,
+ [NVDEV_ENGINE_VENC] = NV_DEVICE_DISABLE_VENC,
+ [NVDEV_ENGINE_DISP] = NV_DEVICE_DISABLE_DISP,
+ [NVDEV_SUBDEV_NR] = 0,
+};
+
+static int
+nouveau_devobj_ctor(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_client *client = nv_client(parent);
+ struct nouveau_device *device;
+ struct nouveau_devobj *devobj;
+ struct nv_device_class *args = data;
+ u32 boot0, strap;
+ u64 disable, mmio_base, mmio_size;
+ void __iomem *map;
+ int ret, i, c;
+
+ if (size < sizeof(struct nv_device_class))
+ return -EINVAL;
+
+ /* find the device subdev that matches what the client requested */
+ device = nv_device(client->device);
+ if (args->device != ~0) {
+ device = nouveau_device_find(args->device);
+ if (!device)
+ return -ENODEV;
+ }
+
+ ret = nouveau_parent_create(parent, nv_object(device), oclass, 0,
+ nouveau_control_oclass,
+ (1ULL << NVDEV_ENGINE_DMAOBJ) |
+ (1ULL << NVDEV_ENGINE_FIFO) |
+ (1ULL << NVDEV_ENGINE_DISP) |
+ (1ULL << NVDEV_ENGINE_PERFMON), &devobj);
+ *pobject = nv_object(devobj);
+ if (ret)
+ return ret;
+
+ mmio_base = nv_device_resource_start(device, 0);
+ mmio_size = nv_device_resource_len(device, 0);
+
+ /* translate api disable mask into internal mapping */
+ disable = args->debug0;
+ for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
+ if (args->disable & disable_map[i])
+ disable |= (1ULL << i);
+ }
+
+ /* identify the chipset, and determine classes of subdev/engines */
+ if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) &&
+ !device->card_type) {
+ map = ioremap(mmio_base, 0x102000);
+ if (map == NULL)
+ return -ENOMEM;
+
+ /* switch mmio to cpu's native endianness */
+#ifndef __BIG_ENDIAN
+ if (ioread32_native(map + 0x000004) != 0x00000000)
+#else
+ if (ioread32_native(map + 0x000004) == 0x00000000)
+#endif
+ iowrite32_native(0x01000001, map + 0x000004);
+
+ /* read boot0 and strapping information */
+ boot0 = ioread32_native(map + 0x000000);
+ strap = ioread32_native(map + 0x101000);
+ iounmap(map);
+
+ /* determine chipset and derive architecture from it */
+ if ((boot0 & 0x1f000000) > 0) {
+ device->chipset = (boot0 & 0x1ff00000) >> 20;
+ switch (device->chipset & 0x1f0) {
+ case 0x010: {
+ if (0x461 & (1 << (device->chipset & 0xf)))
+ device->card_type = NV_10;
+ else
+ device->card_type = NV_11;
+ break;
+ }
+ case 0x020: device->card_type = NV_20; break;
+ case 0x030: device->card_type = NV_30; break;
+ case 0x040:
+ case 0x060: device->card_type = NV_40; break;
+ case 0x050:
+ case 0x080:
+ case 0x090:
+ case 0x0a0: device->card_type = NV_50; break;
+ case 0x0c0: device->card_type = NV_C0; break;
+ case 0x0d0: device->card_type = NV_D0; break;
+ case 0x0e0:
+ case 0x0f0:
+ case 0x100: device->card_type = NV_E0; break;
+ case 0x110: device->card_type = GM100; break;
+ default:
+ break;
+ }
+ } else
+ if ((boot0 & 0xff00fff0) == 0x20004000) {
+ if (boot0 & 0x00f00000)
+ device->chipset = 0x05;
+ else
+ device->chipset = 0x04;
+ device->card_type = NV_04;
+ }
+
+ switch (device->card_type) {
+ case NV_04: ret = nv04_identify(device); break;
+ case NV_10:
+ case NV_11: ret = nv10_identify(device); break;
+ case NV_20: ret = nv20_identify(device); break;
+ case NV_30: ret = nv30_identify(device); break;
+ case NV_40: ret = nv40_identify(device); break;
+ case NV_50: ret = nv50_identify(device); break;
+ case NV_C0:
+ case NV_D0: ret = nvc0_identify(device); break;
+ case NV_E0: ret = nve0_identify(device); break;
+ case GM100: ret = gm100_identify(device); break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret) {
+ nv_error(device, "unknown chipset, 0x%08x\n", boot0);
+ return ret;
+ }
+
+ nv_info(device, "BOOT0 : 0x%08x\n", boot0);
+ nv_info(device, "Chipset: %s (NV%02X)\n",
+ device->cname, device->chipset);
+ nv_info(device, "Family : NV%02X\n", device->card_type);
+
+ /* determine frequency of timing crystal */
+ if ( device->card_type <= NV_10 || device->chipset < 0x17 ||
+ (device->chipset >= 0x20 && device->chipset < 0x25))
+ strap &= 0x00000040;
+ else
+ strap &= 0x00400040;
+
+ switch (strap) {
+ case 0x00000000: device->crystal = 13500; break;
+ case 0x00000040: device->crystal = 14318; break;
+ case 0x00400000: device->crystal = 27000; break;
+ case 0x00400040: device->crystal = 25000; break;
+ }
+
+ nv_debug(device, "crystal freq: %dKHz\n", device->crystal);
+ }
+
+ if (!(args->disable & NV_DEVICE_DISABLE_MMIO) &&
+ !nv_subdev(device)->mmio) {
+ nv_subdev(device)->mmio = ioremap(mmio_base, mmio_size);
+ if (!nv_subdev(device)->mmio) {
+ nv_error(device, "unable to map device registers\n");
+ return -ENOMEM;
+ }
+ }
+
+ /* ensure requested subsystems are available for use */
+ for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) {
+ if (!(oclass = device->oclass[i]) || (disable & (1ULL << i)))
+ continue;
+
+ if (device->subdev[i]) {
+ nouveau_object_ref(device->subdev[i],
+ &devobj->subdev[i]);
+ continue;
+ }
+
+ ret = nouveau_object_ctor(nv_object(device), NULL,
+ oclass, NULL, i,
+ &devobj->subdev[i]);
+ if (ret == -ENODEV)
+ continue;
+ if (ret)
+ return ret;
+
+ device->subdev[i] = devobj->subdev[i];
+
+ /* note: can't init *any* subdevs until devinit has been run
+ * due to not knowing exactly what the vbios init tables will
+ * mess with. devinit also can't be run until all of its
+ * dependencies have been created.
+ *
+ * this code delays init of any subdev until all of devinit's
+ * dependencies have been created, and then initialises each
+ * subdev in turn as they're created.
+ */
+ while (i >= NVDEV_SUBDEV_DEVINIT_LAST && c <= i) {
+ struct nouveau_object *subdev = devobj->subdev[c++];
+ if (subdev && !nv_iclass(subdev, NV_ENGINE_CLASS)) {
+ ret = nouveau_object_inc(subdev);
+ if (ret)
+ return ret;
+ atomic_dec(&nv_object(device)->usecount);
+ } else
+ if (subdev) {
+ nouveau_subdev_reset(subdev);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void
+nouveau_devobj_dtor(struct nouveau_object *object)
+{
+ struct nouveau_devobj *devobj = (void *)object;
+ int i;
+
+ for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
+ nouveau_object_ref(NULL, &devobj->subdev[i]);
+
+ nouveau_parent_destroy(&devobj->base);
+}
+
+static u8
+nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
+{
+ return nv_rd08(object->engine, addr);
+}
+
+static u16
+nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
+{
+ return nv_rd16(object->engine, addr);
+}
+
+static u32
+nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
+{
+ return nv_rd32(object->engine, addr);
+}
+
+static void
+nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
+{
+ nv_wr08(object->engine, addr, data);
+}
+
+static void
+nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
+{
+ nv_wr16(object->engine, addr, data);
+}
+
+static void
+nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
+{
+ nv_wr32(object->engine, addr, data);
+}
+
+static struct nouveau_ofuncs
+nouveau_devobj_ofuncs = {
+ .ctor = nouveau_devobj_ctor,
+ .dtor = nouveau_devobj_dtor,
+ .init = _nouveau_parent_init,
+ .fini = _nouveau_parent_fini,
+ .rd08 = nouveau_devobj_rd08,
+ .rd16 = nouveau_devobj_rd16,
+ .rd32 = nouveau_devobj_rd32,
+ .wr08 = nouveau_devobj_wr08,
+ .wr16 = nouveau_devobj_wr16,
+ .wr32 = nouveau_devobj_wr32,
+};
+
+/******************************************************************************
+ * nouveau_device: engine functions
+ *****************************************************************************/
+static struct nouveau_oclass
+nouveau_device_sclass[] = {
+ { 0x0080, &nouveau_devobj_ofuncs },
+ {}
+};
+
+static int
+nouveau_device_fini(struct nouveau_object *object, bool suspend)
+{
+ struct nouveau_device *device = (void *)object;
+ struct nouveau_object *subdev;
+ int ret, i;
+
+ for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
+ ret = nouveau_object_dec(subdev, suspend);
+ if (ret && suspend)
+ goto fail;
+ }
+ }
+ }
+
+ ret = 0;
+fail:
+ for (; ret && i < NVDEV_SUBDEV_NR; i++) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
+ ret = nouveau_object_inc(subdev);
+ if (ret) {
+ /* XXX */
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int
+nouveau_device_init(struct nouveau_object *object)
+{
+ struct nouveau_device *device = (void *)object;
+ struct nouveau_object *subdev;
+ int ret, i;
+
+ for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
+ ret = nouveau_object_inc(subdev);
+ if (ret)
+ goto fail;
+ } else {
+ nouveau_subdev_reset(subdev);
+ }
+ }
+ }
+
+ ret = 0;
+fail:
+ for (--i; ret && i >= 0; i--) {
+ if ((subdev = device->subdev[i])) {
+ if (!nv_iclass(subdev, NV_ENGINE_CLASS))
+ nouveau_object_dec(subdev, false);
+ }
+ }
+
+ return ret;
+}
+
+static void
+nouveau_device_dtor(struct nouveau_object *object)
+{
+ struct nouveau_device *device = (void *)object;
+
+ mutex_lock(&nv_devices_mutex);
+ list_del(&device->head);
+ mutex_unlock(&nv_devices_mutex);
+
+ if (nv_subdev(device)->mmio)
+ iounmap(nv_subdev(device)->mmio);
+
+ nouveau_engine_destroy(&device->base);
+}
+
+resource_size_t
+nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
+{
+ if (nv_device_is_pci(device)) {
+ return pci_resource_start(device->pdev, bar);
+ } else {
+ struct resource *res;
+ res = platform_get_resource(device->platformdev,
+ IORESOURCE_MEM, bar);
+ if (!res)
+ return 0;
+ return res->start;
+ }
+}
+
+resource_size_t
+nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
+{
+ if (nv_device_is_pci(device)) {
+ return pci_resource_len(device->pdev, bar);
+ } else {
+ struct resource *res;
+ res = platform_get_resource(device->platformdev,
+ IORESOURCE_MEM, bar);
+ if (!res)
+ return 0;
+ return resource_size(res);
+ }
+}
+
+dma_addr_t
+nv_device_map_page(struct nouveau_device *device, struct page *page)
+{
+ dma_addr_t ret;
+
+ if (nv_device_is_pci(device)) {
+ ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(device->pdev, ret))
+ ret = 0;
+ } else {
+ ret = page_to_phys(page);
+ }
+
+ return ret;
+}
+
+void
+nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
+{
+ if (nv_device_is_pci(device))
+ pci_unmap_page(device->pdev, addr, PAGE_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
+}
+
+int
+nv_device_get_irq(struct nouveau_device *device, bool stall)
+{
+ if (nv_device_is_pci(device)) {
+ return device->pdev->irq;
+ } else {
+ return platform_get_irq_byname(device->platformdev,
+ stall ? "stall" : "nonstall");
+ }
+}
+
+static struct nouveau_oclass
+nouveau_device_oclass = {
+ .handle = NV_ENGINE(DEVICE, 0x00),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .dtor = nouveau_device_dtor,
+ .init = nouveau_device_init,
+ .fini = nouveau_device_fini,
+ },
+};
+
+int
+nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
+ const char *sname, const char *cfg, const char *dbg,
+ int length, void **pobject)
+{
+ struct nouveau_device *device;
+ int ret = -EEXIST;
+
+ mutex_lock(&nv_devices_mutex);
+ list_for_each_entry(device, &nv_devices, head) {
+ if (device->handle == name)
+ goto done;
+ }
+
+ ret = nouveau_engine_create_(NULL, NULL, &nouveau_device_oclass, true,
+ "DEVICE", "device", length, pobject);
+ device = *pobject;
+ if (ret)
+ goto done;
+
+ switch (type) {
+ case NOUVEAU_BUS_PCI:
+ device->pdev = dev;
+ break;
+ case NOUVEAU_BUS_PLATFORM:
+ device->platformdev = dev;
+ break;
+ }
+ device->handle = name;
+ device->cfgopt = cfg;
+ device->dbgopt = dbg;
+ device->name = sname;
+
+ nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE");
+ nv_engine(device)->sclass = nouveau_device_sclass;
+ list_add(&device->head, &nv_devices);
+done:
+ mutex_unlock(&nv_devices_mutex);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
new file mode 100644
index 00000000000..4b69bf56ed0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include <core/object.h>
+#include <core/class.h>
+
+#include <subdev/clock.h>
+
+#include "priv.h"
+
+static int
+nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ struct nouveau_clock *clk = nouveau_clock(object);
+ struct nv_control_pstate_info *args = data;
+
+ if (size < sizeof(*args))
+ return -EINVAL;
+
+ if (clk) {
+ args->count = clk->state_nr;
+ args->ustate = clk->ustate;
+ args->pstate = clk->pstate;
+ } else {
+ args->count = 0;
+ args->ustate = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE;
+ args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static int
+nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ struct nouveau_clock *clk = nouveau_clock(object);
+ struct nv_control_pstate_attr *args = data;
+ struct nouveau_clocks *domain;
+ struct nouveau_pstate *pstate;
+ struct nouveau_cstate *cstate;
+ int i = 0, j = -1;
+ u32 lo, hi;
+
+ if ((size < sizeof(*args)) || !clk ||
+ (args->state >= 0 && args->state >= clk->state_nr))
+ return -EINVAL;
+ domain = clk->domains;
+
+ while (domain->name != nv_clk_src_max) {
+ if (domain->mname && ++j == args->index)
+ break;
+ domain++;
+ }
+
+ if (domain->name == nv_clk_src_max)
+ return -EINVAL;
+
+ if (args->state != NV_CONTROL_PSTATE_ATTR_STATE_CURRENT) {
+ list_for_each_entry(pstate, &clk->states, head) {
+ if (i++ == args->state)
+ break;
+ }
+
+ lo = pstate->base.domain[domain->name];
+ hi = lo;
+ list_for_each_entry(cstate, &pstate->list, head) {
+ lo = min(lo, cstate->domain[domain->name]);
+ hi = max(hi, cstate->domain[domain->name]);
+ }
+
+ args->state = pstate->pstate;
+ } else {
+ lo = max(clk->read(clk, domain->name), 0);
+ hi = lo;
+ }
+
+ snprintf(args->name, sizeof(args->name), "%s", domain->mname);
+ snprintf(args->unit, sizeof(args->unit), "MHz");
+ args->min = lo / domain->mdiv;
+ args->max = hi / domain->mdiv;
+
+ args->index = 0;
+ while ((++domain)->name != nv_clk_src_max) {
+ if (domain->mname) {
+ args->index = ++j;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int
+nouveau_control_mthd_pstate_user(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ struct nouveau_clock *clk = nouveau_clock(object);
+ struct nv_control_pstate_user *args = data;
+
+ if (size < sizeof(*args) || !clk)
+ return -EINVAL;
+
+ return nouveau_clock_ustate(clk, args->state);
+}
+
+struct nouveau_oclass
+nouveau_control_oclass[] = {
+ { .handle = NV_CONTROL_CLASS,
+ .ofuncs = &nouveau_object_ofuncs,
+ .omthds = (struct nouveau_omthds[]) {
+ { NV_CONTROL_PSTATE_INFO,
+ NV_CONTROL_PSTATE_INFO, nouveau_control_mthd_pstate_info },
+ { NV_CONTROL_PSTATE_ATTR,
+ NV_CONTROL_PSTATE_ATTR, nouveau_control_mthd_pstate_attr },
+ { NV_CONTROL_PSTATE_USER,
+ NV_CONTROL_PSTATE_USER, nouveau_control_mthd_pstate_user },
+ {},
+ },
+ },
+ {}
+};
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/gm100.c b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
new file mode 100644
index 00000000000..a520029e25d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/therm.h>
+#include <subdev/mxm.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/ltcg.h>
+#include <subdev/ibus.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/pwr.h>
+#include <subdev/volt.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/disp.h>
+#include <engine/copy.h>
+#include <engine/bsp.h>
+#include <engine/vp.h>
+#include <engine/ppp.h>
+#include <engine/perfmon.h>
+
+int
+gm100_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0x117:
+ device->cname = "GM107";
+ 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;
+#if 0
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
+#endif
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = gm107_devinit_oclass;
+ 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 ] = gm107_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gm107_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;
+#if 0
+ device->oclass[NVDEV_SUBDEV_PWR ] = &nv108_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+#endif
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = gm107_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = gm107_disp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
+#if 0
+ device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
+#endif
+ 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 Maxwell chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
new file mode 100644
index 00000000000..40b29d0214c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/disp.h>
+
+int
+nv04_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0x04:
+ device->cname = "NV04";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv04_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x05:
+ device->cname = "NV05";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv05_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ default:
+ nv_fatal(device, "unknown RIVA chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
new file mode 100644
index 00000000000..5f7c25ff523
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/disp.h>
+
+int
+nv10_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0x10:
+ device->cname = "NV10";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x15:
+ device->cname = "NV15";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x16:
+ device->cname = "NV16";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x1a:
+ device->cname = "nForce";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x11:
+ device->cname = "NV11";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x17:
+ device->cname = "NV17";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x1f:
+ device->cname = "nForce2";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x18:
+ device->cname = "NV18";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ default:
+ nv_fatal(device, "unknown Celsius chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
new file mode 100644
index 00000000000..75fed11bba0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/therm.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/disp.h>
+
+int
+nv20_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0x20:
+ device->cname = "NV20";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv20_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv20_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x25:
+ device->cname = "NV25";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x28:
+ device->cname = "NV28";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x2a:
+ device->cname = "NV2A";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv2a_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ default:
+ nv_fatal(device, "unknown Kelvin chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
new file mode 100644
index 00000000000..36919d7db7c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/mpeg.h>
+#include <engine/disp.h>
+
+int
+nv30_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0x30:
+ device->cname = "NV30";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x35:
+ device->cname = "NV35";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv04_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv35_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x31:
+ device->cname = "NV31";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x36:
+ device->cname = "NV36";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv36_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ case 0x34:
+ device->cname = "NV34";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv34_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv31_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ break;
+ default:
+ nv_fatal(device, "unknown Rankine chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
new file mode 100644
index 00000000000..1130a62be2c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/vm.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/therm.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+#include <subdev/volt.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/mpeg.h>
+#include <engine/disp.h>
+#include <engine/perfmon.h>
+
+int
+nv40_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0x40:
+ device->cname = "NV40";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv40_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x41:
+ device->cname = "NV41";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv41_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x42:
+ device->cname = "NV42";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv41_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x43:
+ device->cname = "NV43";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv41_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv40_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x45:
+ device->cname = "NV45";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv40_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x47:
+ device->cname = "G70";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv47_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x49:
+ device->cname = "G71";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv49_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x4b:
+ device->cname = "G73";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv40_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv49_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x44:
+ device->cname = "NV44";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv44_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x46:
+ device->cname = "G72";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x4a:
+ device->cname = "NV44A";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv44_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x4c:
+ device->cname = "C61";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x4e:
+ device->cname = "C51";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv4e_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv4e_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x63:
+ device->cname = "C73";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x67:
+ device->cname = "C67";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ case 0x68:
+ device->cname = "C68";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv44_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv40_perfmon_oclass;
+ break;
+ default:
+ nv_fatal(device, "unknown Curie chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
new file mode 100644
index 00000000000..ef0b0bde1a9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/therm.h>
+#include <subdev/mxm.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/pwr.h>
+#include <subdev/volt.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/mpeg.h>
+#include <engine/vp.h>
+#include <engine/crypt.h>
+#include <engine/bsp.h>
+#include <engine/ppp.h>
+#include <engine/copy.h>
+#include <engine/disp.h>
+#include <engine/perfmon.h>
+
+int
+nv50_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0x50:
+ device->cname = "G80";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv50_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv50_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv50_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv50_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv50_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv50_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv50_perfmon_oclass;
+ break;
+ case 0x84:
+ device->cname = "G84";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv84_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv84_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0x86:
+ device->cname = "G86";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv84_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv84_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0x92:
+ device->cname = "G92";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv84_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv50_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv50_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv84_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0x94:
+ device->cname = "G94";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv84_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv94_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0x96:
+ device->cname = "G96";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv84_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv94_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0x98:
+ device->cname = "G98";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv98_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv98_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0xa0:
+ device->cname = "G200";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv84_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nv84_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv84_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv84_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv84_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva0_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0xaa:
+ device->cname = "MCP77/MCP78";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv98_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nvaa_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv98_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0xac:
+ device->cname = "MCP79/MCP7A";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nv98_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nvaa_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv98_vp_oclass;
+ device->oclass[NVDEV_ENGINE_CRYPT ] = &nv98_crypt_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nv94_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nv84_perfmon_oclass;
+ break;
+ case 0xa3:
+ device->cname = "GT215";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nva3_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_MPEG ] = &nv84_mpeg_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv98_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
+ break;
+ case 0xa5:
+ device->cname = "GT216";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nva3_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv98_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
+ break;
+ case 0xa8:
+ device->cname = "GT218";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nva3_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nva3_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv98_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
+ break;
+ case 0xaf:
+ device->cname = "MCP89";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nvaf_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nv98_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nv94_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nvaf_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
+ device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nv98_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nv98_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nv98_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nva3_copy_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = nva3_perfmon_oclass;
+ break;
+ default:
+ nv_fatal(device, "unknown Tesla chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
new file mode 100644
index 00000000000..8d55ed633b1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/therm.h>
+#include <subdev/mxm.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/ltcg.h>
+#include <subdev/ibus.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/pwr.h>
+#include <subdev/volt.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/vp.h>
+#include <engine/bsp.h>
+#include <engine/ppp.h>
+#include <engine/copy.h>
+#include <engine/disp.h>
+#include <engine/perfmon.h>
+
+int
+nvc0_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0xc0:
+ device->cname = "GF100";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nvc0_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvc0_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xc4:
+ device->cname = "GF104";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nvc0_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xc3:
+ device->cname = "GF106";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_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 ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xce:
+ device->cname = "GF114";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nvc0_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xcf:
+ device->cname = "GF116";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_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 ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xc1:
+ device->cname = "GF108";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_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 ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvc1_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xc8:
+ device->cname = "GF110";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = nvc0_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = &nvc0_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvc8_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_COPY1 ] = &nvc0_copy1_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nva3_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xd9:
+ device->cname = "GF119";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nvd0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_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 ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvd9_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nvd0_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ case 0xd7:
+ device->cname = "GF117";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nvd0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = gf117_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_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 ] = nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_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 ] = nvc0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nvd7_graph_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nvc0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nvc0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nvc0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nvd0_disp_oclass;
+ device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
+ break;
+ default:
+ nv_fatal(device, "unknown Fermi chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
new file mode 100644
index 00000000000..2d1e97d4264
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bus.h>
+#include <subdev/gpio.h>
+#include <subdev/i2c.h>
+#include <subdev/clock.h>
+#include <subdev/therm.h>
+#include <subdev/mxm.h>
+#include <subdev/devinit.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+#include <subdev/fb.h>
+#include <subdev/ltcg.h>
+#include <subdev/ibus.h>
+#include <subdev/instmem.h>
+#include <subdev/vm.h>
+#include <subdev/bar.h>
+#include <subdev/pwr.h>
+#include <subdev/volt.h>
+
+#include <engine/device.h>
+#include <engine/dmaobj.h>
+#include <engine/fifo.h>
+#include <engine/software.h>
+#include <engine/graph.h>
+#include <engine/disp.h>
+#include <engine/copy.h>
+#include <engine/bsp.h>
+#include <engine/vp.h>
+#include <engine/ppp.h>
+#include <engine/perfmon.h>
+
+int
+nve0_identify(struct nouveau_device *device)
+{
+ switch (device->chipset) {
+ case 0xe4:
+ device->cname = "GK104";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nve0_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 ] = nve4_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nve0_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] = &nve0_perfmon_oclass;
+ break;
+ case 0xe7:
+ device->cname = "GK107";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nve0_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 ] = nve4_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nve0_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] = &nve0_perfmon_oclass;
+ break;
+ case 0xe6:
+ device->cname = "GK106";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nve0_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 ] = nve4_graph_oclass;
+ device->oclass[NVDEV_ENGINE_DISP ] = nve0_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] = &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;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nve0_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 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:
+ device->cname = "GK208";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = nve0_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 ] = &nv108_pwr_oclass;
+ device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+ device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = nv108_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;
+ break;
+ default:
+ nv_fatal(device, "unknown Kepler chipset\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/priv.h b/drivers/gpu/drm/nouveau/core/engine/device/priv.h
new file mode 100644
index 00000000000..035fd5b9cfc
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/device/priv.h
@@ -0,0 +1,8 @@
+#ifndef __NVKM_DEVICE_PRIV_H__
+#define __NVKM_DEVICE_PRIV_H__
+
+#include <engine/device.h>
+
+extern struct nouveau_oclass nouveau_control_oclass[];
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/base.c b/drivers/gpu/drm/nouveau/core/engine/disp/base.c
new file mode 100644
index 00000000000..9c38c5e4050
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/base.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include "priv.h"
+#include "outp.h"
+#include "conn.h"
+
+static int
+nouveau_disp_hpd_check(struct nouveau_event *event, u32 types, int index)
+{
+ struct nouveau_disp *disp = event->priv;
+ struct nvkm_output *outp;
+ list_for_each_entry(outp, &disp->outp, head) {
+ if (outp->conn->index == index) {
+ if (outp->conn->hpd.event)
+ return 0;
+ break;
+ }
+ }
+ return -ENOSYS;
+}
+
+int
+_nouveau_disp_fini(struct nouveau_object *object, bool suspend)
+{
+ struct nouveau_disp *disp = (void *)object;
+ struct nvkm_output *outp;
+ int ret;
+
+ list_for_each_entry(outp, &disp->outp, head) {
+ ret = nv_ofuncs(outp)->fini(nv_object(outp), suspend);
+ if (ret && suspend)
+ goto fail_outp;
+ }
+
+ return nouveau_engine_fini(&disp->base, suspend);
+
+fail_outp:
+ list_for_each_entry_continue_reverse(outp, &disp->outp, head) {
+ nv_ofuncs(outp)->init(nv_object(outp));
+ }
+
+ return ret;
+}
+
+int
+_nouveau_disp_init(struct nouveau_object *object)
+{
+ struct nouveau_disp *disp = (void *)object;
+ struct nvkm_output *outp;
+ int ret;
+
+ ret = nouveau_engine_init(&disp->base);
+ if (ret)
+ return ret;
+
+ list_for_each_entry(outp, &disp->outp, head) {
+ ret = nv_ofuncs(outp)->init(nv_object(outp));
+ if (ret)
+ goto fail_outp;
+ }
+
+ return ret;
+
+fail_outp:
+ list_for_each_entry_continue_reverse(outp, &disp->outp, head) {
+ nv_ofuncs(outp)->fini(nv_object(outp), false);
+ }
+
+ return ret;
+}
+
+void
+_nouveau_disp_dtor(struct nouveau_object *object)
+{
+ struct nouveau_disp *disp = (void *)object;
+ struct nvkm_output *outp, *outt;
+
+ nouveau_event_destroy(&disp->vblank);
+
+ if (disp->outp.next) {
+ list_for_each_entry_safe(outp, outt, &disp->outp, head) {
+ nouveau_object_ref(NULL, (struct nouveau_object **)&outp);
+ }
+ }
+
+ nouveau_engine_destroy(&disp->base);
+}
+
+int
+nouveau_disp_create_(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, int heads,
+ const char *intname, const char *extname,
+ int length, void **pobject)
+{
+ struct nouveau_disp_impl *impl = (void *)oclass;
+ struct nouveau_bios *bios = nouveau_bios(parent);
+ struct nouveau_disp *disp;
+ struct nouveau_oclass **sclass;
+ struct nouveau_object *object;
+ struct dcb_output dcbE;
+ u8 hpd = 0, ver, hdr;
+ u32 data;
+ int ret, i;
+
+ ret = nouveau_engine_create_(parent, engine, oclass, true,
+ intname, extname, length, pobject);
+ disp = *pobject;
+ if (ret)
+ return ret;
+
+ INIT_LIST_HEAD(&disp->outp);
+
+ /* create output objects for each display path in the vbios */
+ i = -1;
+ while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE))) {
+ if (dcbE.type == DCB_OUTPUT_UNUSED)
+ continue;
+ if (dcbE.type == DCB_OUTPUT_EOL)
+ break;
+ data = dcbE.location << 4 | dcbE.type;
+
+ oclass = nvkm_output_oclass;
+ sclass = impl->outp;
+ while (sclass && sclass[0]) {
+ if (sclass[0]->handle == data) {
+ oclass = sclass[0];
+ break;
+ }
+ sclass++;
+ }
+
+ nouveau_object_ctor(*pobject, *pobject, oclass,
+ &dcbE, i, &object);
+ hpd = max(hpd, (u8)(dcbE.connector + 1));
+ }
+
+ ret = nouveau_event_create(3, hpd, &disp->hpd);
+ if (ret)
+ return ret;
+
+ disp->hpd->priv = disp;
+ disp->hpd->check = nouveau_disp_hpd_check;
+
+ ret = nouveau_event_create(1, heads, &disp->vblank);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/conn.c b/drivers/gpu/drm/nouveau/core/engine/disp/conn.c
new file mode 100644
index 00000000000..4ffbc70ecf5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/conn.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/gpio.h>
+
+#include "conn.h"
+#include "outp.h"
+
+static void
+nvkm_connector_hpd_work(struct work_struct *w)
+{
+ struct nvkm_connector *conn = container_of(w, typeof(*conn), hpd.work);
+ struct nouveau_disp *disp = nouveau_disp(conn);
+ struct nouveau_gpio *gpio = nouveau_gpio(conn);
+ u32 send = NVKM_HPD_UNPLUG;
+ if (gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.event->index))
+ send = NVKM_HPD_PLUG;
+ nouveau_event_trigger(disp->hpd, send, conn->index);
+ nouveau_event_get(conn->hpd.event);
+}
+
+static int
+nvkm_connector_hpd(void *data, u32 type, int index)
+{
+ struct nvkm_connector *conn = data;
+ DBG("HPD: %d\n", type);
+ schedule_work(&conn->hpd.work);
+ return NVKM_EVENT_DROP;
+}
+
+int
+_nvkm_connector_fini(struct nouveau_object *object, bool suspend)
+{
+ struct nvkm_connector *conn = (void *)object;
+ if (conn->hpd.event)
+ nouveau_event_put(conn->hpd.event);
+ return nouveau_object_fini(&conn->base, suspend);
+}
+
+int
+_nvkm_connector_init(struct nouveau_object *object)
+{
+ struct nvkm_connector *conn = (void *)object;
+ int ret = nouveau_object_init(&conn->base);
+ if (ret == 0) {
+ if (conn->hpd.event)
+ nouveau_event_get(conn->hpd.event);
+ }
+ return ret;
+}
+
+void
+_nvkm_connector_dtor(struct nouveau_object *object)
+{
+ struct nvkm_connector *conn = (void *)object;
+ nouveau_event_ref(NULL, &conn->hpd.event);
+ nouveau_object_destroy(&conn->base);
+}
+
+int
+nvkm_connector_create_(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass,
+ struct nvbios_connE *info, int index,
+ int length, void **pobject)
+{
+ static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 };
+ struct nouveau_gpio *gpio = nouveau_gpio(parent);
+ struct nouveau_disp *disp = (void *)engine;
+ struct nvkm_connector *conn;
+ struct nvkm_output *outp;
+ struct dcb_gpio_func func;
+ int ret;
+
+ list_for_each_entry(outp, &disp->outp, head) {
+ if (outp->conn && outp->conn->index == index) {
+ atomic_inc(&nv_object(outp->conn)->refcount);
+ *pobject = outp->conn;
+ return 1;
+ }
+ }
+
+ ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
+ conn = *pobject;
+ if (ret)
+ return ret;
+
+ conn->info = *info;
+ conn->index = index;
+
+ DBG("type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x\n",
+ info->type, info->location, info->hpd, info->dp,
+ info->di, info->sr, info->lcdid);
+
+ if ((info->hpd = ffs(info->hpd))) {
+ if (--info->hpd >= ARRAY_SIZE(hpd)) {
+ ERR("hpd %02x unknown\n", info->hpd);
+ goto done;
+ }
+ info->hpd = hpd[info->hpd];
+
+ ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func);
+ if (ret) {
+ ERR("func %02x lookup failed, %d\n", info->hpd, ret);
+ goto done;
+ }
+
+ ret = nouveau_event_new(gpio->events, NVKM_GPIO_TOGGLED,
+ func.line, nvkm_connector_hpd,
+ conn, &conn->hpd.event);
+ if (ret) {
+ ERR("func %02x failed, %d\n", info->hpd, ret);
+ } else {
+ DBG("func %02x (HPD)\n", info->hpd);
+ }
+ }
+
+done:
+ INIT_WORK(&conn->hpd.work, nvkm_connector_hpd_work);
+ return 0;
+}
+
+int
+_nvkm_connector_ctor(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *info, u32 index,
+ struct nouveau_object **pobject)
+{
+ struct nvkm_connector *conn;
+ int ret;
+
+ ret = nvkm_connector_create(parent, engine, oclass, info, index, &conn);
+ *pobject = nv_object(conn);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct nouveau_oclass *
+nvkm_connector_oclass = &(struct nvkm_connector_impl) {
+ .base = {
+ .handle = 0,
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nvkm_connector_ctor,
+ .dtor = _nvkm_connector_dtor,
+ .init = _nvkm_connector_init,
+ .fini = _nvkm_connector_fini,
+ },
+ },
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/conn.h b/drivers/gpu/drm/nouveau/core/engine/disp/conn.h
new file mode 100644
index 00000000000..035ebeacbb1
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/conn.h
@@ -0,0 +1,59 @@
+#ifndef __NVKM_DISP_CONN_H__
+#define __NVKM_DISP_CONN_H__
+
+#include "priv.h"
+
+struct nvkm_connector {
+ struct nouveau_object base;
+ struct list_head head;
+
+ struct nvbios_connE info;
+ int index;
+
+ struct {
+ struct nouveau_eventh *event;
+ struct work_struct work;
+ } hpd;
+};
+
+#define nvkm_connector_create(p,e,c,b,i,d) \
+ nvkm_connector_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d)
+#define nvkm_connector_destroy(d) ({ \
+ struct nvkm_connector *disp = (d); \
+ _nvkm_connector_dtor(nv_object(disp)); \
+})
+#define nvkm_connector_init(d) ({ \
+ struct nvkm_connector *disp = (d); \
+ _nvkm_connector_init(nv_object(disp)); \
+})
+#define nvkm_connector_fini(d,s) ({ \
+ struct nvkm_connector *disp = (d); \
+ _nvkm_connector_fini(nv_object(disp), (s)); \
+})
+
+int nvkm_connector_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, struct nvbios_connE *,
+ int, int, void **);
+
+int _nvkm_connector_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+void _nvkm_connector_dtor(struct nouveau_object *);
+int _nvkm_connector_init(struct nouveau_object *);
+int _nvkm_connector_fini(struct nouveau_object *, bool);
+
+struct nvkm_connector_impl {
+ struct nouveau_oclass base;
+};
+
+#ifndef MSG
+#define MSG(l,f,a...) do { \
+ struct nvkm_connector *_conn = (void *)conn; \
+ nv_##l(nv_object(conn)->engine, "%02x:%02x%02x: "f, _conn->index, \
+ _conn->info.location, _conn->info.type, ##a); \
+} while(0)
+#define DBG(f,a...) MSG(debug, f, ##a)
+#define ERR(f,a...) MSG(error, f, ##a)
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
index d0817d94454..a66b27c0fca 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c
@@ -49,13 +49,23 @@ int
nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
{
const u32 doff = (or * 0x800);
- int load = -EINVAL;
+
+ nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000);
+ nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
+
nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval);
- udelay(9500);
- nv_wr32(priv, 0x61a00c + doff, 0x80000000);
- load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27;
- nv_wr32(priv, 0x61a00c + doff, 0x00000000);
- return load;
+ mdelay(9);
+ udelay(500);
+ loadval = nv_mask(priv, 0x61a00c + doff, 0xffffffff, 0x00000000);
+
+ nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000);
+ nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
+
+ nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval);
+ if (!(loadval & 0x80000000))
+ return -ETIMEDOUT;
+
+ return (loadval & 0x38000000) >> 27;
}
int
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
new file mode 100644
index 00000000000..5a5b59b2113
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright 2013 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/bios.h>
+#include <subdev/bios/dcb.h>
+#include <subdev/bios/dp.h>
+#include <subdev/bios/init.h>
+#include <subdev/i2c.h>
+
+#include <engine/disp.h>
+
+#include <core/class.h>
+
+#include "dport.h"
+#include "outpdp.h"
+
+/******************************************************************************
+ * link training
+ *****************************************************************************/
+struct dp_state {
+ struct nvkm_output_dp *outp;
+ int link_nr;
+ u32 link_bw;
+ u8 stat[6];
+ u8 conf[4];
+ bool pc2;
+ u8 pc2stat;
+ u8 pc2conf[2];
+};
+
+static int
+dp_set_link_config(struct dp_state *dp)
+{
+ struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp);
+ struct nvkm_output_dp *outp = dp->outp;
+ struct nouveau_disp *disp = nouveau_disp(outp);
+ struct nouveau_bios *bios = nouveau_bios(disp);
+ struct nvbios_init init = {
+ .subdev = nv_subdev(disp),
+ .bios = bios,
+ .offset = 0x0000,
+ .outp = &outp->base.info,
+ .crtc = -1,
+ .execute = 1,
+ };
+ u32 lnkcmp;
+ u8 sink[2];
+ int ret;
+
+ DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
+
+ /* set desired link configuration on the source */
+ if ((lnkcmp = dp->outp->info.lnkcmp)) {
+ if (outp->version < 0x30) {
+ while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp))
+ lnkcmp += 4;
+ init.offset = nv_ro16(bios, lnkcmp + 2);
+ } else {
+ while ((dp->link_bw / 27000) < nv_ro08(bios, lnkcmp))
+ lnkcmp += 3;
+ init.offset = nv_ro16(bios, lnkcmp + 1);
+ }
+
+ nvbios_exec(&init);
+ }
+
+ ret = impl->lnk_ctl(outp, dp->link_nr, dp->link_bw / 27000,
+ outp->dpcd[DPCD_RC02] &
+ DPCD_RC02_ENHANCED_FRAME_CAP);
+ if (ret) {
+ if (ret < 0)
+ ERR("lnk_ctl failed with %d\n", ret);
+ return ret;
+ }
+
+ impl->lnk_pwr(outp, dp->link_nr);
+
+ /* set desired link configuration on the sink */
+ sink[0] = dp->link_bw / 27000;
+ sink[1] = dp->link_nr;
+ if (outp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP)
+ sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN;
+
+ return nv_wraux(outp->base.edid, DPCD_LC00_LINK_BW_SET, sink, 2);
+}
+
+static void
+dp_set_training_pattern(struct dp_state *dp, u8 pattern)
+{
+ struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp);
+ struct nvkm_output_dp *outp = dp->outp;
+ u8 sink_tp;
+
+ DBG("training pattern %d\n", pattern);
+ impl->pattern(outp, pattern);
+
+ nv_rdaux(outp->base.edid, DPCD_LC02, &sink_tp, 1);
+ sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET;
+ sink_tp |= pattern;
+ nv_wraux(outp->base.edid, DPCD_LC02, &sink_tp, 1);
+}
+
+static int
+dp_link_train_commit(struct dp_state *dp, bool pc)
+{
+ struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp);
+ struct nvkm_output_dp *outp = dp->outp;
+ int ret, i;
+
+ for (i = 0; i < dp->link_nr; i++) {
+ u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
+ u8 lpc2 = (dp->pc2stat >> (i * 2)) & 0x3;
+ u8 lpre = (lane & 0x0c) >> 2;
+ u8 lvsw = (lane & 0x03) >> 0;
+ u8 hivs = 3 - lpre;
+ u8 hipe = 3;
+ u8 hipc = 3;
+
+ if (lpc2 >= hipc)
+ lpc2 = hipc | DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED;
+ if (lpre >= hipe) {
+ lpre = hipe | DPCD_LC03_MAX_SWING_REACHED; /* yes. */
+ lvsw = hivs = 3 - (lpre & 3);
+ } else
+ if (lvsw >= hivs) {
+ lvsw = hivs | DPCD_LC03_MAX_SWING_REACHED;
+ }
+
+ dp->conf[i] = (lpre << 3) | lvsw;
+ dp->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4);
+
+ DBG("config lane %d %02x %02x\n", i, dp->conf[i], lpc2);
+ impl->drv_ctl(outp, i, lvsw & 3, lpre & 3, lpc2 & 3);
+ }
+
+ ret = nv_wraux(outp->base.edid, DPCD_LC03(0), dp->conf, 4);
+ if (ret)
+ return ret;
+
+ if (pc) {
+ ret = nv_wraux(outp->base.edid, DPCD_LC0F, dp->pc2conf, 2);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+dp_link_train_update(struct dp_state *dp, bool pc, u32 delay)
+{
+ struct nvkm_output_dp *outp = dp->outp;
+ int ret;
+
+ if (outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL])
+ mdelay(outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4);
+ else
+ udelay(delay);
+
+ ret = nv_rdaux(outp->base.edid, DPCD_LS02, dp->stat, 6);
+ if (ret)
+ return ret;
+
+ if (pc) {
+ ret = nv_rdaux(outp->base.edid, DPCD_LS0C, &dp->pc2stat, 1);
+ if (ret)
+ dp->pc2stat = 0x00;
+ DBG("status %6ph pc2 %02x\n", dp->stat, dp->pc2stat);
+ } else {
+ DBG("status %6ph\n", dp->stat);
+ }
+
+ return 0;
+}
+
+static int
+dp_link_train_cr(struct dp_state *dp)
+{
+ bool cr_done = false, abort = false;
+ int voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET;
+ int tries = 0, i;
+
+ dp_set_training_pattern(dp, 1);
+
+ do {
+ if (dp_link_train_commit(dp, false) ||
+ dp_link_train_update(dp, false, 100))
+ break;
+
+ cr_done = true;
+ for (i = 0; i < dp->link_nr; i++) {
+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
+ if (!(lane & DPCD_LS02_LANE0_CR_DONE)) {
+ cr_done = false;
+ if (dp->conf[i] & DPCD_LC03_MAX_SWING_REACHED)
+ abort = true;
+ break;
+ }
+ }
+
+ if ((dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET) != voltage) {
+ voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET;
+ tries = 0;
+ }
+ } while (!cr_done && !abort && ++tries < 5);
+
+ return cr_done ? 0 : -1;
+}
+
+static int
+dp_link_train_eq(struct dp_state *dp)
+{
+ struct nvkm_output_dp *outp = dp->outp;
+ bool eq_done = false, cr_done = true;
+ int tries = 0, i;
+
+ if (outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED)
+ dp_set_training_pattern(dp, 3);
+ else
+ dp_set_training_pattern(dp, 2);
+
+ do {
+ if ((tries &&
+ dp_link_train_commit(dp, dp->pc2)) ||
+ dp_link_train_update(dp, dp->pc2, 400))
+ break;
+
+ eq_done = !!(dp->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE);
+ for (i = 0; i < dp->link_nr && eq_done; i++) {
+ u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf;
+ if (!(lane & DPCD_LS02_LANE0_CR_DONE))
+ cr_done = false;
+ if (!(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) ||
+ !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED))
+ eq_done = false;
+ }
+ } while (!eq_done && cr_done && ++tries <= 5);
+
+ return eq_done ? 0 : -1;
+}
+
+static void
+dp_link_train_init(struct dp_state *dp, bool spread)
+{
+ struct nvkm_output_dp *outp = dp->outp;
+ struct nouveau_disp *disp = nouveau_disp(outp);
+ struct nouveau_bios *bios = nouveau_bios(disp);
+ struct nvbios_init init = {
+ .subdev = nv_subdev(disp),
+ .bios = bios,
+ .outp = &outp->base.info,
+ .crtc = -1,
+ .execute = 1,
+ };
+
+ /* set desired spread */
+ if (spread)
+ init.offset = outp->info.script[2];
+ else
+ init.offset = outp->info.script[3];
+ nvbios_exec(&init);
+
+ /* pre-train script */
+ init.offset = outp->info.script[0];
+ nvbios_exec(&init);
+}
+
+static void
+dp_link_train_fini(struct dp_state *dp)
+{
+ struct nvkm_output_dp *outp = dp->outp;
+ struct nouveau_disp *disp = nouveau_disp(outp);
+ struct nouveau_bios *bios = nouveau_bios(disp);
+ struct nvbios_init init = {
+ .subdev = nv_subdev(disp),
+ .bios = bios,
+ .outp = &outp->base.info,
+ .crtc = -1,
+ .execute = 1,
+ };
+
+ /* post-train script */
+ init.offset = outp->info.script[1],
+ nvbios_exec(&init);
+}
+
+static const struct dp_rates {
+ u32 rate;
+ u8 bw;
+ u8 nr;
+} nouveau_dp_rates[] = {
+ { 2160000, 0x14, 4 },
+ { 1080000, 0x0a, 4 },
+ { 1080000, 0x14, 2 },
+ { 648000, 0x06, 4 },
+ { 540000, 0x0a, 2 },
+ { 540000, 0x14, 1 },
+ { 324000, 0x06, 2 },
+ { 270000, 0x0a, 1 },
+ { 162000, 0x06, 1 },
+ {}
+};
+
+void
+nouveau_dp_train(struct work_struct *w)
+{
+ struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work);
+ struct nouveau_disp *disp = nouveau_disp(outp);
+ const struct dp_rates *cfg = nouveau_dp_rates;
+ struct dp_state _dp = {
+ .outp = outp,
+ }, *dp = &_dp;
+ u32 datarate = 0;
+ int ret;
+
+ /* bring capabilities within encoder limits */
+ if (nv_mclass(disp) < NVD0_DISP_CLASS)
+ outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
+ if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) {
+ outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
+ outp->dpcd[2] |= outp->base.info.dpconf.link_nr;
+ }
+ if (outp->dpcd[1] > outp->base.info.dpconf.link_bw)
+ outp->dpcd[1] = outp->base.info.dpconf.link_bw;
+ dp->pc2 = outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED;
+
+ /* restrict link config to the lowest required rate, if requested */
+ if (datarate) {
+ datarate = (datarate / 8) * 10; /* 8B/10B coding overhead */
+ while (cfg[1].rate >= datarate)
+ cfg++;
+ }
+ cfg--;
+
+ /* disable link interrupt handling during link training */
+ nouveau_event_put(outp->irq);
+
+ /* enable down-spreading and execute pre-train script from vbios */
+ dp_link_train_init(dp, outp->dpcd[3] & 0x01);
+
+ while (ret = -EIO, (++cfg)->rate) {
+ /* select next configuration supported by encoder and sink */
+ while (cfg->nr > (outp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT) ||
+ cfg->bw > (outp->dpcd[DPCD_RC01_MAX_LINK_RATE]))
+ cfg++;
+ dp->link_bw = cfg->bw * 27000;
+ dp->link_nr = cfg->nr;
+
+ /* program selected link configuration */
+ ret = dp_set_link_config(dp);
+ if (ret == 0) {
+ /* attempt to train the link at this configuration */
+ memset(dp->stat, 0x00, sizeof(dp->stat));
+ if (!dp_link_train_cr(dp) &&
+ !dp_link_train_eq(dp))
+ break;
+ } else
+ if (ret) {
+ /* dp_set_link_config() handled training, or
+ * we failed to communicate with the sink.
+ */
+ break;
+ }
+ }
+
+ /* finish link training and execute post-train script from vbios */
+ dp_set_training_pattern(dp, 0);
+ if (ret < 0)
+ ERR("link training failed\n");
+
+ dp_link_train_fini(dp);
+
+ /* signal completion and enable link interrupt handling */
+ DBG("training complete\n");
+ atomic_set(&outp->lt.done, 1);
+ wake_up(&outp->lt.wait);
+ nouveau_event_get(outp->irq);
+}
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.h b/drivers/gpu/drm/nouveau/core/engine/disp/dport.h
new file mode 100644
index 00000000000..5628d2d5ec7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.h
@@ -0,0 +1,75 @@
+#ifndef __NVKM_DISP_DPORT_H__
+#define __NVKM_DISP_DPORT_H__
+
+/* DPCD Receiver Capabilities */
+#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_LINK_BW_SET 0x00100
+#define DPCD_LC01 0x00101
+#define DPCD_LC01_ENHANCED_FRAME_EN 0x80
+#define DPCD_LC01_LANE_COUNT_SET 0x1f
+#define DPCD_LC02 0x00102
+#define DPCD_LC02_TRAINING_PATTERN_SET 0x03
+#define DPCD_LC03(l) ((l) + 0x00103)
+#define DPCD_LC03_MAX_PRE_EMPHASIS_REACHED 0x20
+#define DPCD_LC03_PRE_EMPHASIS_SET 0x18
+#define DPCD_LC03_MAX_SWING_REACHED 0x04
+#define DPCD_LC03_VOLTAGE_SWING_SET 0x03
+#define DPCD_LC0F 0x0010f
+#define DPCD_LC0F_LANE1_MAX_POST_CURSOR2_REACHED 0x40
+#define DPCD_LC0F_LANE1_POST_CURSOR2_SET 0x30
+#define DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED 0x04
+#define DPCD_LC0F_LANE0_POST_CURSOR2_SET 0x03
+#define DPCD_LC10 0x00110
+#define DPCD_LC10_LANE3_MAX_POST_CURSOR2_REACHED 0x40
+#define DPCD_LC10_LANE3_POST_CURSOR2_SET 0x30
+#define DPCD_LC10_LANE2_MAX_POST_CURSOR2_REACHED 0x04
+#define DPCD_LC10_LANE2_POST_CURSOR2_SET 0x03
+
+/* DPCD Link/Sink Status */
+#define DPCD_LS02 0x00202
+#define DPCD_LS02_LANE1_SYMBOL_LOCKED 0x40
+#define DPCD_LS02_LANE1_CHANNEL_EQ_DONE 0x20
+#define DPCD_LS02_LANE1_CR_DONE 0x10
+#define DPCD_LS02_LANE0_SYMBOL_LOCKED 0x04
+#define DPCD_LS02_LANE0_CHANNEL_EQ_DONE 0x02
+#define DPCD_LS02_LANE0_CR_DONE 0x01
+#define DPCD_LS03 0x00203
+#define DPCD_LS03_LANE3_SYMBOL_LOCKED 0x40
+#define DPCD_LS03_LANE3_CHANNEL_EQ_DONE 0x20
+#define DPCD_LS03_LANE3_CR_DONE 0x10
+#define DPCD_LS03_LANE2_SYMBOL_LOCKED 0x04
+#define DPCD_LS03_LANE2_CHANNEL_EQ_DONE 0x02
+#define DPCD_LS03_LANE2_CR_DONE 0x01
+#define DPCD_LS04 0x00204
+#define DPCD_LS04_LINK_STATUS_UPDATED 0x80
+#define DPCD_LS04_DOWNSTREAM_PORT_STATUS_CHANGED 0x40
+#define DPCD_LS04_INTERLANE_ALIGN_DONE 0x01
+#define DPCD_LS06 0x00206
+#define DPCD_LS06_LANE1_PRE_EMPHASIS 0xc0
+#define DPCD_LS06_LANE1_VOLTAGE_SWING 0x30
+#define DPCD_LS06_LANE0_PRE_EMPHASIS 0x0c
+#define DPCD_LS06_LANE0_VOLTAGE_SWING 0x03
+#define DPCD_LS07 0x00207
+#define DPCD_LS07_LANE3_PRE_EMPHASIS 0xc0
+#define DPCD_LS07_LANE3_VOLTAGE_SWING 0x30
+#define DPCD_LS07_LANE2_PRE_EMPHASIS 0x0c
+#define DPCD_LS07_LANE2_VOLTAGE_SWING 0x03
+#define DPCD_LS0C 0x0020c
+#define DPCD_LS0C_LANE3_POST_CURSOR2 0xc0
+#define DPCD_LS0C_LANE2_POST_CURSOR2 0x30
+#define DPCD_LS0C_LANE1_POST_CURSOR2 0x0c
+#define DPCD_LS0C_LANE0_POST_CURSOR2 0x03
+
+void nouveau_dp_train(struct work_struct *);
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
new file mode 100644
index 00000000000..9fc7447fec9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <engine/software.h>
+#include <engine/disp.h>
+
+#include <core/class.h>
+
+#include "nv50.h"
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
+static struct nouveau_oclass
+gm107_disp_sclass[] = {
+ { GM107_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
+ { GM107_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
+ { GM107_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
+ { GM107_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
+ { GM107_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+ {}
+};
+
+static struct nouveau_oclass
+gm107_disp_base_oclass[] = {
+ { GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ {}
+};
+
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
+static int
+gm107_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nv50_disp_priv *priv;
+ int heads = nv_rd32(parent, 0x022448);
+ int ret;
+
+ ret = nouveau_disp_create(parent, engine, oclass, heads,
+ "PDISP", "display", &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ nv_engine(priv)->sclass = gm107_disp_base_oclass;
+ nv_engine(priv)->cclass = &nv50_disp_cclass;
+ nv_subdev(priv)->intr = nvd0_disp_intr;
+ INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
+ priv->sclass = gm107_disp_sclass;
+ priv->head.nr = heads;
+ priv->dac.nr = 3;
+ priv->sor.nr = 4;
+ priv->dac.power = nv50_dac_power;
+ priv->dac.sense = nv50_dac_sense;
+ priv->sor.power = nv50_sor_power;
+ priv->sor.hda_eld = nvd0_hda_eld;
+ priv->sor.hdmi = nvd0_hdmi_ctrl;
+ return 0;
+}
+
+struct nouveau_oclass *
+gm107_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x07),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gm107_disp_ctor,
+ .dtor = _nouveau_disp_dtor,
+ .init = _nouveau_disp_init,
+ .fini = _nouveau_disp_fini,
+ },
+ .base.outp = nvd0_disp_outp_sclass,
+ .mthd.core = &nve0_disp_mast_mthd_chan,
+ .mthd.base = &nvd0_disp_sync_mthd_chan,
+ .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+ .mthd.prev = -0x020000,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
index 373dbcc523b..a19e7d79b84 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
@@ -36,6 +36,8 @@ nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
if (data && data[0]) {
for (i = 0; i < size; i++)
nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]);
+ for (; i < 0x60; i++)
+ nv_wr32(priv, 0x61c440 + soff, (i << 8));
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003);
} else
if (data) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
index dc57e24fc1d..717639386ce 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
@@ -41,6 +41,8 @@ nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
if (data && data[0]) {
for (i = 0; i < size; i++)
nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]);
+ for (; i < 0x60; i++)
+ nv_wr32(priv, 0x10ec00 + soff, (i << 8));
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003);
} else
if (data) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
index 0d36bdc5141..7fdade6e604 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminv84.c
@@ -55,6 +55,10 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_wr32(priv, 0x616510 + hoff, 0x00000000);
nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000001);
+ nv_mask(priv, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
+ nv_mask(priv, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
+ nv_mask(priv, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
+
/* ??? */
nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
index f065fc248ad..db8c6fd4627 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
@@ -55,6 +55,10 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_wr32(priv, 0x61c510 + soff, 0x00000000);
nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000001);
+ nv_mask(priv, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
+ nv_mask(priv, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
+ nv_mask(priv, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
+
/* ??? */
nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
index 1c919f2af89..a32666ed0c4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
@@ -22,23 +22,79 @@
* Authors: Ben Skeggs
*/
-#include <engine/disp.h>
+#include "priv.h"
+
+#include <core/event.h>
+#include <core/class.h>
struct nv04_disp_priv {
struct nouveau_disp base;
};
+static int
+nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ struct nv04_disp_priv *priv = (void *)object->engine;
+ struct nv04_display_scanoutpos *args = data;
+ const int head = (mthd & NV04_DISP_MTHD_HEAD);
+ u32 line;
+
+ if (size < sizeof(*args))
+ return -EINVAL;
+
+ args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
+ args->vtotal = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
+ args->vblanke = args->vtotal - 1;
+
+ args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
+ 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());
+ args->hline = (line & 0xffff0000) >> 16;
+ args->vline = (line & 0x0000ffff);
+ return 0;
+}
+
+#define HEAD_MTHD(n) (n), (n) + 0x01
+
+static struct nouveau_omthds
+nv04_disp_omthds[] = {
+ { HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
+ {}
+};
+
static struct nouveau_oclass
nv04_disp_sclass[] = {
+ { NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
{},
};
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
static void
-nv04_disp_intr_vblank(struct nv04_disp_priv *priv, int crtc)
+nv04_disp_vblank_enable(struct nouveau_event *event, int type, int head)
{
- struct nouveau_disp *disp = &priv->base;
- if (disp->vblank.notify)
- disp->vblank.notify(disp->vblank.data, crtc);
+ nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);
+}
+
+static void
+nv04_disp_vblank_disable(struct nouveau_event *event, int type, int head)
+{
+ nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);
}
static void
@@ -47,27 +103,36 @@ nv04_disp_intr(struct nouveau_subdev *subdev)
struct nv04_disp_priv *priv = (void *)subdev;
u32 crtc0 = nv_rd32(priv, 0x600100);
u32 crtc1 = nv_rd32(priv, 0x602100);
+ u32 pvideo;
if (crtc0 & 0x00000001) {
- nv04_disp_intr_vblank(priv, 0);
+ nouveau_event_trigger(priv->base.vblank, 1, 0);
nv_wr32(priv, 0x600100, 0x00000001);
}
if (crtc1 & 0x00000001) {
- nv04_disp_intr_vblank(priv, 1);
+ nouveau_event_trigger(priv->base.vblank, 1, 1);
nv_wr32(priv, 0x602100, 0x00000001);
}
+
+ if (nv_device(priv)->chipset >= 0x10 &&
+ nv_device(priv)->chipset <= 0x40) {
+ pvideo = nv_rd32(priv, 0x8100);
+ if (pvideo & ~0x11)
+ nv_info(priv, "PVIDEO intr: %08x\n", pvideo);
+ nv_wr32(priv, 0x8100, pvideo);
+ }
}
static int
nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
- struct nouveau_oclass *oclass, void *data, u32 size,
- struct nouveau_object **pobject)
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
{
struct nv04_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "DISPLAY",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "DISPLAY",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
@@ -75,16 +140,19 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv04_disp_sclass;
nv_subdev(priv)->intr = nv04_disp_intr;
+ priv->base.vblank->priv = priv;
+ priv->base.vblank->enable = nv04_disp_vblank_enable;
+ priv->base.vblank->disable = nv04_disp_vblank_disable;
return 0;
}
-struct nouveau_oclass
-nv04_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x04),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv04_disp_oclass = &(struct nouveau_disp_impl) {
+ .base.handle = NV_ENGINE(DISP, 0x04),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv04_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 0f09af13541..2283c442a10 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -26,19 +26,16 @@
#include <core/parent.h>
#include <core/handle.h>
#include <core/class.h>
-
-#include <engine/software.h>
-#include <engine/disp.h>
+#include <core/enum.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
#include <subdev/bios/disp.h>
#include <subdev/bios/init.h>
#include <subdev/bios/pll.h>
+#include <subdev/devinit.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
-#include <subdev/bar.h>
-#include <subdev/clock.h>
#include "nv50.h"
@@ -229,6 +226,177 @@ nv50_disp_dmac_fini(struct nouveau_object *object, bool suspend)
* EVO master channel object
******************************************************************************/
+static void
+nv50_disp_mthd_list(struct nv50_disp_priv *priv, int debug, u32 base, int c,
+ const struct nv50_disp_mthd_list *list, int inst)
+{
+ struct nouveau_object *disp = nv_object(priv);
+ int i;
+
+ for (i = 0; list->data[i].mthd; i++) {
+ if (list->data[i].addr) {
+ u32 next = nv_rd32(priv, list->data[i].addr + base + 0);
+ u32 prev = nv_rd32(priv, list->data[i].addr + base + c);
+ u32 mthd = list->data[i].mthd + (list->mthd * inst);
+ const char *name = list->data[i].name;
+ char mods[16];
+
+ if (prev != next)
+ snprintf(mods, sizeof(mods), "-> 0x%08x", next);
+ else
+ snprintf(mods, sizeof(mods), "%13c", ' ');
+
+ nv_printk_(disp, debug, "\t0x%04x: 0x%08x %s%s%s\n",
+ mthd, prev, mods, name ? " // " : "",
+ name ? name : "");
+ }
+ }
+}
+
+void
+nv50_disp_mthd_chan(struct nv50_disp_priv *priv, int debug, int head,
+ const struct nv50_disp_mthd_chan *chan)
+{
+ struct nouveau_object *disp = nv_object(priv);
+ const struct nv50_disp_impl *impl = (void *)disp->oclass;
+ const struct nv50_disp_mthd_list *list;
+ int i, j;
+
+ if (debug > nv_subdev(priv)->debug)
+ return;
+
+ for (i = 0; (list = chan->data[i].mthd) != NULL; i++) {
+ u32 base = head * chan->addr;
+ for (j = 0; j < chan->data[i].nr; j++, base += list->addr) {
+ const char *cname = chan->name;
+ const char *sname = "";
+ char cname_[16], sname_[16];
+
+ if (chan->addr) {
+ snprintf(cname_, sizeof(cname_), "%s %d",
+ chan->name, head);
+ cname = cname_;
+ }
+
+ if (chan->data[i].nr > 1) {
+ snprintf(sname_, sizeof(sname_), " - %s %d",
+ chan->data[i].name, j);
+ sname = sname_;
+ }
+
+ nv_printk_(disp, debug, "%s%s:\n", cname, sname);
+ nv50_disp_mthd_list(priv, debug, base, impl->mthd.prev,
+ list, j);
+ }
+ }
+}
+
+const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x000000 },
+ { 0x0084, 0x610bb8 },
+ { 0x0088, 0x610b9c },
+ { 0x008c, 0x000000 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_dac = {
+ .mthd = 0x0080,
+ .addr = 0x000008,
+ .data = {
+ { 0x0400, 0x610b58 },
+ { 0x0404, 0x610bdc },
+ { 0x0420, 0x610828 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_sor = {
+ .mthd = 0x0040,
+ .addr = 0x000008,
+ .data = {
+ { 0x0600, 0x610b70 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_pior = {
+ .mthd = 0x0040,
+ .addr = 0x000008,
+ .data = {
+ { 0x0700, 0x610b80 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_list
+nv50_disp_mast_mthd_head = {
+ .mthd = 0x0400,
+ .addr = 0x000540,
+ .data = {
+ { 0x0800, 0x610ad8 },
+ { 0x0804, 0x610ad0 },
+ { 0x0808, 0x610a48 },
+ { 0x080c, 0x610a78 },
+ { 0x0810, 0x610ac0 },
+ { 0x0814, 0x610af8 },
+ { 0x0818, 0x610b00 },
+ { 0x081c, 0x610ae8 },
+ { 0x0820, 0x610af0 },
+ { 0x0824, 0x610b08 },
+ { 0x0828, 0x610b10 },
+ { 0x082c, 0x610a68 },
+ { 0x0830, 0x610a60 },
+ { 0x0834, 0x000000 },
+ { 0x0838, 0x610a40 },
+ { 0x0840, 0x610a24 },
+ { 0x0844, 0x610a2c },
+ { 0x0848, 0x610aa8 },
+ { 0x084c, 0x610ab0 },
+ { 0x0860, 0x610a84 },
+ { 0x0864, 0x610a90 },
+ { 0x0868, 0x610b18 },
+ { 0x086c, 0x610b20 },
+ { 0x0870, 0x610ac8 },
+ { 0x0874, 0x610a38 },
+ { 0x0880, 0x610a58 },
+ { 0x0884, 0x610a9c },
+ { 0x08a0, 0x610a70 },
+ { 0x08a4, 0x610a50 },
+ { 0x08a8, 0x610ae0 },
+ { 0x08c0, 0x610b28 },
+ { 0x08c4, 0x610b30 },
+ { 0x08c8, 0x610b40 },
+ { 0x08d4, 0x610b38 },
+ { 0x08d8, 0x610b48 },
+ { 0x08dc, 0x610b50 },
+ { 0x0900, 0x610a18 },
+ { 0x0904, 0x610ab8 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_chan
+nv50_disp_mast_mthd_chan = {
+ .name = "Core",
+ .addr = 0x000000,
+ .data = {
+ { "Global", 1, &nv50_disp_mast_mthd_base },
+ { "DAC", 3, &nv50_disp_mast_mthd_dac },
+ { "SOR", 2, &nv50_disp_mast_mthd_sor },
+ { "PIOR", 3, &nv50_disp_mast_mthd_pior },
+ { "HEAD", 2, &nv50_disp_mast_mthd_head },
+ {}
+ }
+};
+
static int
nv50_disp_mast_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -325,6 +493,56 @@ nv50_disp_mast_ofuncs = {
* EVO sync channel objects
******************************************************************************/
+static const struct nv50_disp_mthd_list
+nv50_disp_sync_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x000000 },
+ { 0x0084, 0x0008c4 },
+ { 0x0088, 0x0008d0 },
+ { 0x008c, 0x0008dc },
+ { 0x0090, 0x0008e4 },
+ { 0x0094, 0x610884 },
+ { 0x00a0, 0x6108a0 },
+ { 0x00a4, 0x610878 },
+ { 0x00c0, 0x61086c },
+ { 0x00e0, 0x610858 },
+ { 0x00e4, 0x610860 },
+ { 0x00e8, 0x6108ac },
+ { 0x00ec, 0x6108b4 },
+ { 0x0100, 0x610894 },
+ { 0x0110, 0x6108bc },
+ { 0x0114, 0x61088c },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_list
+nv50_disp_sync_mthd_image = {
+ .mthd = 0x0400,
+ .addr = 0x000000,
+ .data = {
+ { 0x0800, 0x6108f0 },
+ { 0x0804, 0x6108fc },
+ { 0x0808, 0x61090c },
+ { 0x080c, 0x610914 },
+ { 0x0810, 0x610904 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_chan
+nv50_disp_sync_mthd_chan = {
+ .name = "Base",
+ .addr = 0x000540,
+ .data = {
+ { "Global", 1, &nv50_disp_sync_mthd_base },
+ { "Image", 2, &nv50_disp_sync_mthd_image },
+ {}
+ }
+};
+
static int
nv50_disp_sync_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -335,7 +553,7 @@ nv50_disp_sync_ctor(struct nouveau_object *parent,
struct nv50_disp_dmac *dmac;
int ret;
- if (size < sizeof(*data) || args->head > 1)
+ if (size < sizeof(*args) || args->head > 1)
return -EINVAL;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -364,6 +582,44 @@ nv50_disp_sync_ofuncs = {
* EVO overlay channel objects
******************************************************************************/
+const struct nv50_disp_mthd_list
+nv50_disp_ovly_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x000000 },
+ { 0x0084, 0x0009a0 },
+ { 0x0088, 0x0009c0 },
+ { 0x008c, 0x0009c8 },
+ { 0x0090, 0x6109b4 },
+ { 0x0094, 0x610970 },
+ { 0x00a0, 0x610998 },
+ { 0x00a4, 0x610964 },
+ { 0x00c0, 0x610958 },
+ { 0x00e0, 0x6109a8 },
+ { 0x00e4, 0x6109d0 },
+ { 0x00e8, 0x6109d8 },
+ { 0x0100, 0x61094c },
+ { 0x0104, 0x610984 },
+ { 0x0108, 0x61098c },
+ { 0x0800, 0x6109f8 },
+ { 0x0808, 0x610a08 },
+ { 0x080c, 0x610a10 },
+ { 0x0810, 0x610a00 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_chan
+nv50_disp_ovly_mthd_chan = {
+ .name = "Overlay",
+ .addr = 0x000540,
+ .data = {
+ { "Global", 1, &nv50_disp_ovly_mthd_base },
+ {}
+ }
+};
+
static int
nv50_disp_ovly_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -374,7 +630,7 @@ nv50_disp_ovly_ctor(struct nouveau_object *parent,
struct nv50_disp_dmac *dmac;
int ret;
- if (size < sizeof(*data) || args->head > 1)
+ if (size < sizeof(*args) || args->head > 1)
return -EINVAL;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -543,6 +799,47 @@ nv50_disp_curs_ofuncs = {
* Base display object
******************************************************************************/
+int
+nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ struct nv50_disp_priv *priv = (void *)object->engine;
+ struct nv04_display_scanoutpos *args = data;
+ const int head = (mthd & NV50_DISP_MTHD_HEAD);
+ u32 blanke, blanks, total;
+
+ if (size < sizeof(*args) || head >= priv->head.nr)
+ return -EINVAL;
+ blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
+ blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
+ total = nv_rd32(priv, 0x610afc + (head * 0x540));
+
+ args->vblanke = (blanke & 0xffff0000) >> 16;
+ args->hblanke = (blanke & 0x0000ffff);
+ args->vblanks = (blanks & 0xffff0000) >> 16;
+ args->hblanks = (blanks & 0x0000ffff);
+ args->vtotal = ( total & 0xffff0000) >> 16;
+ args->htotal = ( total & 0x0000ffff);
+
+ args->time[0] = ktime_to_ns(ktime_get());
+ args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+ args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
+ args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+ return 0;
+}
+
+static void
+nv50_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
+{
+ nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));
+}
+
+static void
+nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
+{
+ nv_mask(event->priv, 0x61002c, (4 << head), 0);
+}
+
static int
nv50_disp_base_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -559,7 +856,11 @@ nv50_disp_base_ctor(struct nouveau_object *parent,
if (ret)
return ret;
- return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
+ priv->base.vblank->priv = priv;
+ priv->base.vblank->enable = nv50_disp_base_vblank_enable;
+ priv->base.vblank->disable = nv50_disp_base_vblank_disable;
+ return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
+ &base->ramht);
}
static void
@@ -613,8 +914,8 @@ nv50_disp_base_init(struct nouveau_object *object)
nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp);
}
- /* ... EXT caps */
- for (i = 0; i < 3; i++) {
+ /* ... PIOR caps */
+ for (i = 0; i < priv->pior.nr; i++) {
tmp = nv_rd32(priv, 0x61e000 + (i * 0x800));
nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp);
}
@@ -661,10 +962,14 @@ nv50_disp_base_ofuncs = {
static struct nouveau_omthds
nv50_disp_base_omthds[] = {
+ { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
};
@@ -703,7 +1008,7 @@ nv50_disp_data_ctor(struct nouveau_object *parent,
if (nv_mclass(parent) != NV_DEVICE_CLASS) {
atomic_inc(&parent->refcount);
*pobject = parent;
- return 0;
+ return 1;
}
/* allocate display hardware to client */
@@ -735,84 +1040,94 @@ nv50_disp_cclass = {
* Display engine implementation
******************************************************************************/
-static void
-nv50_disp_intr_error(struct nv50_disp_priv *priv)
-{
- u32 channels = (nv_rd32(priv, 0x610020) & 0x001f0000) >> 16;
- u32 addr, data;
- int chid;
-
- for (chid = 0; chid < 5; chid++) {
- if (!(channels & (1 << chid)))
- continue;
-
- nv_wr32(priv, 0x610020, 0x00010000 << chid);
- addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
- data = nv_rd32(priv, 0x610084 + (chid * 0x08));
- nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
+static const struct nouveau_enum
+nv50_disp_intr_error_type[] = {
+ { 3, "ILLEGAL_MTHD" },
+ { 4, "INVALID_VALUE" },
+ { 5, "INVALID_STATE" },
+ { 7, "INVALID_HANDLE" },
+ {}
+};
- nv_error(priv, "chid %d mthd 0x%04x data 0x%08x 0x%08x\n",
- chid, addr & 0xffc, data, addr);
- }
-}
+static const struct nouveau_enum
+nv50_disp_intr_error_code[] = {
+ { 0x00, "" },
+ {}
+};
static void
-nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
+nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
{
- struct nouveau_bar *bar = nouveau_bar(priv);
- struct nouveau_disp *disp = &priv->base;
- struct nouveau_software_chan *chan, *temp;
- unsigned long flags;
-
- spin_lock_irqsave(&disp->vblank.lock, flags);
- list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) {
- if (chan->vblank.crtc != crtc)
- continue;
-
- if (nv_device(priv)->chipset >= 0xc0) {
- nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
- bar->flush(bar);
- nv_wr32(priv, 0x06000c,
- upper_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060010,
- lower_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060014, chan->vblank.value);
- } else {
- nv_wr32(priv, 0x001704, chan->vblank.channel);
- nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
- bar->flush(bar);
- if (nv_device(priv)->chipset == 0x50) {
- nv_wr32(priv, 0x001570, chan->vblank.offset);
- nv_wr32(priv, 0x001574, chan->vblank.value);
- } else {
- nv_wr32(priv, 0x060010, chan->vblank.offset);
- nv_wr32(priv, 0x060014, chan->vblank.value);
- }
+ struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
+ u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08));
+ u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
+ u32 code = (addr & 0x00ff0000) >> 16;
+ u32 type = (addr & 0x00007000) >> 12;
+ u32 mthd = (addr & 0x00000ffc);
+ const struct nouveau_enum *ec, *et;
+ char ecunk[6], etunk[6];
+
+ et = nouveau_enum_find(nv50_disp_intr_error_type, type);
+ if (!et)
+ snprintf(etunk, sizeof(etunk), "UNK%02X", type);
+
+ ec = nouveau_enum_find(nv50_disp_intr_error_code, code);
+ if (!ec)
+ snprintf(ecunk, sizeof(ecunk), "UNK%02X", code);
+
+ nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n",
+ et ? et->name : etunk, ec ? ec->name : ecunk,
+ chid, mthd, data);
+
+ if (chid == 0) {
+ switch (mthd) {
+ case 0x0080:
+ nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
+ impl->mthd.core);
+ break;
+ default:
+ break;
+ }
+ } else
+ if (chid <= 2) {
+ switch (mthd) {
+ case 0x0080:
+ nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
+ impl->mthd.base);
+ break;
+ default:
+ break;
+ }
+ } else
+ if (chid <= 4) {
+ switch (mthd) {
+ case 0x0080:
+ nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3,
+ impl->mthd.ovly);
+ break;
+ default:
+ break;
}
-
- list_del(&chan->vblank.head);
- if (disp->vblank.put)
- disp->vblank.put(disp->vblank.data, crtc);
}
- spin_unlock_irqrestore(&disp->vblank.lock, flags);
- if (disp->vblank.notify)
- disp->vblank.notify(disp->vblank.data, crtc);
+ nv_wr32(priv, 0x610020, 0x00010000 << chid);
+ nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
}
-static u16
-exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
- struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+static struct nvkm_output *
+exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
+ u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_outp *info)
{
struct nouveau_bios *bios = nouveau_bios(priv);
- u16 mask, type, data;
+ struct nvkm_output *outp;
+ u16 mask, type;
- if (outp < 4) {
+ if (or < 4) {
type = DCB_OUTPUT_ANALOG;
mask = 0;
- } else {
- outp -= 4;
+ } else
+ if (or < 8) {
switch (ctrl & 0x00000f00) {
case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
@@ -822,158 +1137,237 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
default:
nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
- return 0x0000;
+ return NULL;
+ }
+ or -= 4;
+ } else {
+ or = or - 8;
+ type = 0x0010;
+ mask = 0;
+ switch (ctrl & 0x00000f00) {
+ case 0x00000000: type |= priv->pior.type[or]; break;
+ default:
+ nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl);
+ return NULL;
}
}
mask = 0x00c0 & (mask << 6);
- mask |= 0x0001 << outp;
+ mask |= 0x0001 << or;
mask |= 0x0100 << head;
- data = dcb_outp_match(bios, type, mask, ver, hdr, dcb);
- if (!data)
- return 0x0000;
+ list_for_each_entry(outp, &priv->base.outp, head) {
+ if ((outp->info.hasht & 0xff) == type &&
+ (outp->info.hashm & mask) == mask) {
+ *data = nvbios_outp_match(bios, outp->info.hasht,
+ outp->info.hashm,
+ ver, hdr, cnt, len, info);
+ if (!*data)
+ return NULL;
+ return outp;
+ }
+ }
- return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info);
+ return NULL;
}
-static bool
+static struct nvkm_output *
exec_script(struct nv50_disp_priv *priv, int head, int id)
{
struct nouveau_bios *bios = nouveau_bios(priv);
+ struct nvkm_output *outp;
struct nvbios_outp info;
- struct dcb_output dcb;
u8 ver, hdr, cnt, len;
- u16 data;
- u32 ctrl = 0x00000000;
+ u32 data, ctrl = 0;
+ u32 reg;
int i;
- for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
+ /* DAC */
+ for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
ctrl = nv_rd32(priv, 0x610b5c + (i * 8));
- if (nv_device(priv)->chipset < 0x90 ||
- nv_device(priv)->chipset == 0x92 ||
- nv_device(priv)->chipset == 0xa0) {
- for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
- ctrl = nv_rd32(priv, 0x610b74 + (i * 8));
- i += 3;
- } else {
- for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
- ctrl = nv_rd32(priv, 0x610798 + (i * 8));
- i += 3;
+ /* SOR */
+ if (!(ctrl & (1 << head))) {
+ if (nv_device(priv)->chipset < 0x90 ||
+ nv_device(priv)->chipset == 0x92 ||
+ nv_device(priv)->chipset == 0xa0) {
+ reg = 0x610b74;
+ } else {
+ reg = 0x610798;
+ }
+ for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
+ ctrl = nv_rd32(priv, reg + (i * 8));
+ i += 4;
+ }
+
+ /* PIOR */
+ if (!(ctrl & (1 << head))) {
+ for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
+ ctrl = nv_rd32(priv, 0x610b84 + (i * 8));
+ i += 8;
}
if (!(ctrl & (1 << head)))
- return false;
+ return NULL;
+ i--;
- data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info);
- if (data) {
+ outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
+ if (outp) {
struct nvbios_init init = {
.subdev = nv_subdev(priv),
.bios = bios,
.offset = info.script[id],
- .outp = &dcb,
+ .outp = &outp->info,
.crtc = head,
.execute = 1,
};
- return nvbios_exec(&init) == 0;
+ nvbios_exec(&init);
}
- return false;
+ return outp;
}
-static u32
-exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
- struct dcb_output *outp)
+static struct nvkm_output *
+exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf)
{
struct nouveau_bios *bios = nouveau_bios(priv);
+ struct nvkm_output *outp;
struct nvbios_outp info1;
struct nvbios_ocfg info2;
u8 ver, hdr, cnt, len;
- u16 data, conf;
- u32 ctrl = 0x00000000;
+ u32 data, ctrl = 0;
+ u32 reg;
int i;
- for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
+ /* DAC */
+ for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
ctrl = nv_rd32(priv, 0x610b58 + (i * 8));
- if (nv_device(priv)->chipset < 0x90 ||
- nv_device(priv)->chipset == 0x92 ||
- nv_device(priv)->chipset == 0xa0) {
- for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
- ctrl = nv_rd32(priv, 0x610b70 + (i * 8));
- i += 3;
- } else {
- for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
- ctrl = nv_rd32(priv, 0x610794 + (i * 8));
- i += 3;
+ /* SOR */
+ if (!(ctrl & (1 << head))) {
+ if (nv_device(priv)->chipset < 0x90 ||
+ nv_device(priv)->chipset == 0x92 ||
+ nv_device(priv)->chipset == 0xa0) {
+ reg = 0x610b70;
+ } else {
+ reg = 0x610794;
+ }
+ for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
+ ctrl = nv_rd32(priv, reg + (i * 8));
+ i += 4;
}
- if (!(ctrl & (1 << head)))
- return 0x0000;
-
- data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1);
- if (!data)
- return 0x0000;
+ /* PIOR */
+ if (!(ctrl & (1 << head))) {
+ for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
+ ctrl = nv_rd32(priv, 0x610b80 + (i * 8));
+ i += 8;
+ }
- switch (outp->type) {
- case DCB_OUTPUT_TMDS:
- conf = (ctrl & 0x00000f00) >> 8;
- if (pclk >= 165000)
- conf |= 0x0100;
- break;
- case DCB_OUTPUT_LVDS:
- conf = priv->sor.lvdsconf;
- break;
- case DCB_OUTPUT_DP:
- conf = (ctrl & 0x00000f00) >> 8;
- break;
- case DCB_OUTPUT_ANALOG:
- default:
- conf = 0x00ff;
- break;
+ if (!(ctrl & (1 << head)))
+ return NULL;
+ i--;
+
+ outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
+ if (!outp)
+ return NULL;
+
+ if (outp->info.location == 0) {
+ switch (outp->info.type) {
+ case DCB_OUTPUT_TMDS:
+ *conf = (ctrl & 0x00000f00) >> 8;
+ if (pclk >= 165000)
+ *conf |= 0x0100;
+ break;
+ case DCB_OUTPUT_LVDS:
+ *conf = priv->sor.lvdsconf;
+ break;
+ case DCB_OUTPUT_DP:
+ *conf = (ctrl & 0x00000f00) >> 8;
+ break;
+ case DCB_OUTPUT_ANALOG:
+ default:
+ *conf = 0x00ff;
+ break;
+ }
+ } else {
+ *conf = (ctrl & 0x00000f00) >> 8;
+ pclk = pclk / 2;
}
- data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
- if (data) {
+ data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+ if (data && id < 0xff) {
data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
if (data) {
struct nvbios_init init = {
.subdev = nv_subdev(priv),
.bios = bios,
.offset = data,
- .outp = outp,
+ .outp = &outp->info,
.crtc = head,
.execute = 1,
};
- if (nvbios_exec(&init))
- return 0x0000;
- return conf;
+ nvbios_exec(&init);
}
}
- return 0x0000;
+ return outp;
}
static void
-nv50_disp_intr_unk10(struct nv50_disp_priv *priv, u32 super)
+nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head)
{
- int head = ffs((super & 0x00000060) >> 5) - 1;
- if (head >= 0) {
- head = ffs((super & 0x00000180) >> 7) - 1;
- if (head >= 0)
- exec_script(priv, head, 1);
+ exec_script(priv, head, 1);
+}
+
+static void
+nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head)
+{
+ struct nvkm_output *outp = exec_script(priv, head, 2);
+
+ /* the binary driver does this outside of the supervisor handling
+ * (after the third supervisor from a detach). we (currently?)
+ * allow both detach/attach to happen in the same set of
+ * supervisor interrupts, so it would make sense to execute this
+ * (full power down?) script after all the detach phases of the
+ * supervisor handling. like with training if needed from the
+ * second supervisor, nvidia doesn't do this, so who knows if it's
+ * entirely safe, but it does appear to work..
+ *
+ * without this script being run, on some configurations i've
+ * seen, switching from DP to TMDS on a DP connector may result
+ * in a blank screen (SOR_PWR off/on can restore it)
+ */
+ if (outp && outp->info.type == DCB_OUTPUT_DP) {
+ struct nvkm_output_dp *outpdp = (void *)outp;
+ struct nvbios_init init = {
+ .subdev = nv_subdev(priv),
+ .bios = nouveau_bios(priv),
+ .outp = &outp->info,
+ .crtc = head,
+ .offset = outpdp->info.script[4],
+ .execute = 1,
+ };
+
+ nvbios_exec(&init);
+ atomic_set(&outpdp->lt.done, 0);
}
+}
- nv_wr32(priv, 0x610024, 0x00000010);
- nv_wr32(priv, 0x610030, 0x80000000);
+static void
+nv50_disp_intr_unk20_1(struct nv50_disp_priv *priv, int head)
+{
+ struct nouveau_devinit *devinit = nouveau_devinit(priv);
+ u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
+ if (pclk)
+ devinit->pll_set(devinit, PLL_VPLL0 + head, pclk);
}
static void
-nv50_disp_intr_unk20_dp(struct nv50_disp_priv *priv,
- struct dcb_output *outp, u32 pclk)
+nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
+ struct dcb_output *outp, u32 pclk)
{
const int link = !(outp->sorconf.link & 1);
const int or = ffs(outp->or) - 1;
@@ -1079,53 +1473,85 @@ nv50_disp_intr_unk20_dp(struct nv50_disp_priv *priv,
}
static void
-nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
+nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)
{
- struct dcb_output outp;
- u32 addr, mask, data;
- int head;
+ struct nvkm_output *outp;
+ u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
+ u32 hval, hreg = 0x614200 + (head * 0x800);
+ u32 oval, oreg;
+ u32 mask, conf;
+
+ outp = exec_clkcmp(priv, head, 0xff, pclk, &conf);
+ if (!outp)
+ return;
+
+ /* we allow both encoder attach and detach operations to occur
+ * within a single supervisor (ie. modeset) sequence. the
+ * encoder detach scripts quite often switch off power to the
+ * lanes, which requires the link to be re-trained.
+ *
+ * this is not generally an issue as the sink "must" (heh)
+ * signal an irq when it's lost sync so the driver can
+ * re-train.
+ *
+ * however, on some boards, if one does not configure at least
+ * the gpu side of the link *before* attaching, then various
+ * things can go horribly wrong (PDISP disappearing from mmio,
+ * third supervisor never happens, etc).
+ *
+ * the solution is simply to retrain here, if necessary. last
+ * i checked, the binary driver userspace does not appear to
+ * trigger this situation (it forces an UPDATE between steps).
+ */
+ if (outp->info.type == DCB_OUTPUT_DP) {
+ u32 soff = (ffs(outp->info.or) - 1) * 0x08;
+ u32 ctrl, datarate;
- /* finish detaching encoder? */
- head = ffs((super & 0x00000180) >> 7) - 1;
- if (head >= 0)
- exec_script(priv, head, 2);
-
- /* check whether a vpll change is required */
- head = ffs((super & 0x00000600) >> 9) - 1;
- if (head >= 0) {
- u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
- if (pclk) {
- struct nouveau_clock *clk = nouveau_clock(priv);
- clk->pll_set(clk, PLL_VPLL0 + head, pclk);
+ if (outp->info.location == 0) {
+ ctrl = nv_rd32(priv, 0x610794 + soff);
+ soff = 1;
+ } else {
+ ctrl = nv_rd32(priv, 0x610b80 + soff);
+ soff = 2;
}
- nv_mask(priv, 0x614200 + head * 0x800, 0x0000000f, 0x00000000);
- }
+ switch ((ctrl & 0x000f0000) >> 16) {
+ case 6: datarate = pclk * 30; break;
+ case 5: datarate = pclk * 24; break;
+ case 2:
+ default:
+ datarate = pclk * 18;
+ break;
+ }
- /* (re)attach the relevant OR to the head */
- head = ffs((super & 0x00000180) >> 7) - 1;
- if (head >= 0) {
- u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
- u32 conf = exec_clkcmp(priv, head, 0, pclk, &outp);
- if (conf) {
- if (outp.type == DCB_OUTPUT_ANALOG) {
- addr = 0x614280 + (ffs(outp.or) - 1) * 0x800;
- mask = 0xffffffff;
- data = 0x00000000;
- } else {
- if (outp.type == DCB_OUTPUT_DP)
- nv50_disp_intr_unk20_dp(priv, &outp, pclk);
- addr = 0x614300 + (ffs(outp.or) - 1) * 0x800;
- mask = 0x00000707;
- data = (conf & 0x0100) ? 0x0101 : 0x0000;
- }
+ if (nvkm_output_dp_train(outp, datarate / soff, true))
+ ERR("link not trained before attach\n");
+ }
- nv_mask(priv, addr, mask, data);
- }
+ exec_clkcmp(priv, head, 0, pclk, &conf);
+
+ if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) {
+ oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800;
+ oval = 0x00000000;
+ hval = 0x00000000;
+ mask = 0xffffffff;
+ } else
+ if (!outp->info.location) {
+ if (outp->info.type == DCB_OUTPUT_DP)
+ nv50_disp_intr_unk20_2_dp(priv, &outp->info, pclk);
+ oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800;
+ oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
+ hval = 0x00000000;
+ mask = 0x00000707;
+ } else {
+ oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800;
+ oval = 0x00000001;
+ hval = 0x00000001;
+ mask = 0x00000707;
}
- nv_wr32(priv, 0x610024, 0x00000020);
- nv_wr32(priv, 0x610030, 0x80000000);
+ nv_mask(priv, hreg, 0x0000000f, hval);
+ nv_mask(priv, oreg, mask, oval);
}
/* If programming a TMDS output on a SOR that can also be configured for
@@ -1137,7 +1563,7 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
* programmed for DisplayPort.
*/
static void
-nv50_disp_intr_unk40_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp)
+nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp)
{
struct nouveau_bios *bios = nouveau_bios(priv);
const int link = !(outp->sorconf.link & 1);
@@ -1151,35 +1577,67 @@ nv50_disp_intr_unk40_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp)
}
static void
-nv50_disp_intr_unk40(struct nv50_disp_priv *priv, u32 super)
+nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head)
{
- int head = ffs((super & 0x00000180) >> 7) - 1;
- if (head >= 0) {
- struct dcb_output outp;
- u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
- if (pclk && exec_clkcmp(priv, head, 1, pclk, &outp)) {
- if (outp.type == DCB_OUTPUT_TMDS)
- nv50_disp_intr_unk40_tmds(priv, &outp);
- }
- }
+ struct nvkm_output *outp;
+ u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
+ u32 conf;
- nv_wr32(priv, 0x610024, 0x00000040);
- nv_wr32(priv, 0x610030, 0x80000000);
+ outp = exec_clkcmp(priv, head, 1, pclk, &conf);
+ if (!outp)
+ return;
+
+ if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS)
+ nv50_disp_intr_unk40_0_tmds(priv, &outp->info);
}
-static void
-nv50_disp_intr_super(struct nv50_disp_priv *priv, u32 intr1)
+void
+nv50_disp_intr_supervisor(struct work_struct *work)
{
+ struct nv50_disp_priv *priv =
+ container_of(work, struct nv50_disp_priv, supervisor);
+ struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
u32 super = nv_rd32(priv, 0x610030);
+ int head;
+
+ nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
- nv_debug(priv, "supervisor 0x%08x 0x%08x\n", intr1, super);
+ if (priv->super & 0x00000010) {
+ nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(super & (0x00000020 << head)))
+ continue;
+ if (!(super & (0x00000080 << head)))
+ continue;
+ nv50_disp_intr_unk10_0(priv, head);
+ }
+ } else
+ if (priv->super & 0x00000020) {
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(super & (0x00000080 << head)))
+ continue;
+ nv50_disp_intr_unk20_0(priv, head);
+ }
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(super & (0x00000200 << head)))
+ continue;
+ nv50_disp_intr_unk20_1(priv, head);
+ }
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(super & (0x00000080 << head)))
+ continue;
+ nv50_disp_intr_unk20_2(priv, head);
+ }
+ } else
+ if (priv->super & 0x00000040) {
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(super & (0x00000080 << head)))
+ continue;
+ nv50_disp_intr_unk40_0(priv, head);
+ }
+ }
- if (intr1 & 0x00000010)
- nv50_disp_intr_unk10(priv, super);
- if (intr1 & 0x00000020)
- nv50_disp_intr_unk20(priv, super);
- if (intr1 & 0x00000040)
- nv50_disp_intr_unk40(priv, super);
+ nv_wr32(priv, 0x610030, 0x80000000);
}
void
@@ -1189,25 +1647,28 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
u32 intr0 = nv_rd32(priv, 0x610020);
u32 intr1 = nv_rd32(priv, 0x610024);
- if (intr0 & 0x001f0000) {
- nv50_disp_intr_error(priv);
- intr0 &= ~0x001f0000;
+ while (intr0 & 0x001f0000) {
+ u32 chid = __ffs(intr0 & 0x001f0000) - 16;
+ nv50_disp_intr_error(priv, chid);
+ intr0 &= ~(0x00010000 << chid);
}
if (intr1 & 0x00000004) {
- nv50_disp_intr_vblank(priv, 0);
+ nouveau_event_trigger(priv->base.vblank, 1, 0);
nv_wr32(priv, 0x610024, 0x00000004);
intr1 &= ~0x00000004;
}
if (intr1 & 0x00000008) {
- nv50_disp_intr_vblank(priv, 1);
+ nouveau_event_trigger(priv->base.vblank, 1, 1);
nv_wr32(priv, 0x610024, 0x00000008);
intr1 &= ~0x00000008;
}
if (intr1 & 0x00000070) {
- nv50_disp_intr_super(priv, intr1);
+ priv->super = (intr1 & 0x00000070);
+ schedule_work(&priv->supervisor);
+ nv_wr32(priv, 0x610024, priv->super);
intr1 &= ~0x00000070;
}
}
@@ -1220,7 +1681,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
@@ -1229,26 +1690,37 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv50_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
+ INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nv50_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
priv->sor.nr = 2;
+ priv->pior.nr = 3;
priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
+ priv->pior.power = nv50_pior_power;
return 0;
}
-struct nouveau_oclass
-nv50_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x50),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv50_disp_outp_sclass[] = {
+ &nv50_pior_dp_impl.base.base,
+ NULL
+};
+
+struct nouveau_oclass *
+nv50_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x50),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv50_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+ .base.outp = nv50_disp_outp_sclass,
+ .mthd.core = &nv50_disp_mast_mthd_chan,
+ .mthd.base = &nv50_disp_sync_mthd_chan,
+ .mthd.ovly = &nv50_disp_ovly_mthd_chan,
+ .mthd.prev = 0x000004,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index a6bb931450f..1a886472b6f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -3,16 +3,34 @@
#include <core/parent.h>
#include <core/namedb.h>
+#include <core/engctx.h>
#include <core/ramht.h>
+#include <core/event.h>
#include <engine/dmaobj.h>
-#include <engine/disp.h>
-struct dcb_output;
+#include "dport.h"
+#include "priv.h"
+#include "outp.h"
+#include "outpdp.h"
+
+struct nv50_disp_impl {
+ struct nouveau_disp_impl base;
+ struct {
+ const struct nv50_disp_mthd_chan *core;
+ const struct nv50_disp_mthd_chan *base;
+ const struct nv50_disp_mthd_chan *ovly;
+ int prev;
+ } mthd;
+};
struct nv50_disp_priv {
struct nouveau_disp base;
struct nouveau_oclass *sclass;
+
+ struct work_struct supervisor;
+ u32 super;
+
struct {
int nr;
} head;
@@ -26,25 +44,19 @@ struct nv50_disp_priv {
int (*power)(struct nv50_disp_priv *, int sor, u32 data);
int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
- int (*dp_train_init)(struct nv50_disp_priv *, int sor, int link,
- int head, u16 type, u16 mask, u32 data,
- struct dcb_output *);
- int (*dp_train_fini)(struct nv50_disp_priv *, int sor, int link,
- int head, u16 type, u16 mask, u32 data,
- struct dcb_output *);
- int (*dp_train)(struct nv50_disp_priv *, int sor, int link,
- u16 type, u16 mask, u32 data,
- struct dcb_output *);
- int (*dp_lnkctl)(struct nv50_disp_priv *, int sor, int link,
- int head, u16 type, u16 mask, u32 data,
- struct dcb_output *);
- int (*dp_drvctl)(struct nv50_disp_priv *, int sor, int link,
- int lane, u16 type, u16 mask, u32 data,
- struct dcb_output *);
u32 lvdsconf;
} sor;
+ struct {
+ int nr;
+ int (*power)(struct nv50_disp_priv *, int ext, u32 data);
+ u8 type[3];
+ } pior;
};
+#define HEAD_MTHD(n) (n), (n) + 0x03
+
+int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
+
#define DAC_MTHD(n) (n), (n) + 0x03
int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
@@ -81,6 +93,11 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
struct dcb_output *);
+#define PIOR_MTHD(n) (n), (n) + 0x03
+
+int nv50_pior_mthd(struct nouveau_object *, u32, void *, u32);
+int nv50_pior_power(struct nv50_disp_priv *, int, u32);
+
struct nv50_disp_base {
struct nouveau_parent base;
struct nouveau_ramht *ramht;
@@ -117,26 +134,79 @@ struct nv50_disp_pioc {
struct nv50_disp_chan base;
};
+struct nv50_disp_mthd_list {
+ u32 mthd;
+ u32 addr;
+ struct {
+ u32 mthd;
+ u32 addr;
+ const char *name;
+ } data[];
+};
+
+struct nv50_disp_mthd_chan {
+ const char *name;
+ u32 addr;
+ struct {
+ const char *name;
+ int nr;
+ const struct nv50_disp_mthd_list *mthd;
+ } data[];
+};
+
extern struct nouveau_ofuncs nv50_disp_mast_ofuncs;
+extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_base;
+extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_sor;
+extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_pior;
extern struct nouveau_ofuncs nv50_disp_sync_ofuncs;
+extern const struct nv50_disp_mthd_list nv50_disp_sync_mthd_image;
extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs;
+extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base;
extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
extern struct nouveau_oclass nv50_disp_cclass;
+void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head,
+ const struct nv50_disp_mthd_chan *);
+void nv50_disp_intr_supervisor(struct work_struct *);
void nv50_disp_intr(struct nouveau_subdev *);
+extern const struct nv50_disp_mthd_chan nv84_disp_mast_mthd_chan;
+extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
+extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
+extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
+extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
extern struct nouveau_omthds nv84_disp_base_omthds[];
-extern struct nouveau_omthds nva3_disp_base_omthds[];
+extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_base;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_dac;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_sor;
+extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_pior;
extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
+extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
+extern struct nouveau_omthds nvd0_disp_base_omthds[];
extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
extern struct nouveau_oclass nvd0_disp_cclass;
+void nvd0_disp_intr_supervisor(struct work_struct *);
void nvd0_disp_intr(struct nouveau_subdev *);
+extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan;
+extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan;
+
+extern struct nvkm_output_dp_impl nv50_pior_dp_impl;
+extern struct nouveau_oclass *nv50_disp_outp_sclass[];
+
+extern struct nvkm_output_dp_impl nv94_sor_dp_impl;
+int nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int);
+extern struct nouveau_oclass *nv94_disp_outp_sclass[];
+
+extern struct nvkm_output_dp_impl nvd0_sor_dp_impl;
+extern struct nouveau_oclass *nvd0_disp_outp_sclass[];
+
#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index fc84eacdfbe..1cc62e43468 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -29,6 +29,179 @@
#include "nv50.h"
+/*******************************************************************************
+ * EVO master channel object
+ ******************************************************************************/
+
+const struct nv50_disp_mthd_list
+nv84_disp_mast_mthd_dac = {
+ .mthd = 0x0080,
+ .addr = 0x000008,
+ .data = {
+ { 0x0400, 0x610b58 },
+ { 0x0404, 0x610bdc },
+ { 0x0420, 0x610bc4 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_list
+nv84_disp_mast_mthd_head = {
+ .mthd = 0x0400,
+ .addr = 0x000540,
+ .data = {
+ { 0x0800, 0x610ad8 },
+ { 0x0804, 0x610ad0 },
+ { 0x0808, 0x610a48 },
+ { 0x080c, 0x610a78 },
+ { 0x0810, 0x610ac0 },
+ { 0x0814, 0x610af8 },
+ { 0x0818, 0x610b00 },
+ { 0x081c, 0x610ae8 },
+ { 0x0820, 0x610af0 },
+ { 0x0824, 0x610b08 },
+ { 0x0828, 0x610b10 },
+ { 0x082c, 0x610a68 },
+ { 0x0830, 0x610a60 },
+ { 0x0834, 0x000000 },
+ { 0x0838, 0x610a40 },
+ { 0x0840, 0x610a24 },
+ { 0x0844, 0x610a2c },
+ { 0x0848, 0x610aa8 },
+ { 0x084c, 0x610ab0 },
+ { 0x085c, 0x610c5c },
+ { 0x0860, 0x610a84 },
+ { 0x0864, 0x610a90 },
+ { 0x0868, 0x610b18 },
+ { 0x086c, 0x610b20 },
+ { 0x0870, 0x610ac8 },
+ { 0x0874, 0x610a38 },
+ { 0x0878, 0x610c50 },
+ { 0x0880, 0x610a58 },
+ { 0x0884, 0x610a9c },
+ { 0x089c, 0x610c68 },
+ { 0x08a0, 0x610a70 },
+ { 0x08a4, 0x610a50 },
+ { 0x08a8, 0x610ae0 },
+ { 0x08c0, 0x610b28 },
+ { 0x08c4, 0x610b30 },
+ { 0x08c8, 0x610b40 },
+ { 0x08d4, 0x610b38 },
+ { 0x08d8, 0x610b48 },
+ { 0x08dc, 0x610b50 },
+ { 0x0900, 0x610a18 },
+ { 0x0904, 0x610ab8 },
+ { 0x0910, 0x610c70 },
+ { 0x0914, 0x610c78 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_chan
+nv84_disp_mast_mthd_chan = {
+ .name = "Core",
+ .addr = 0x000000,
+ .data = {
+ { "Global", 1, &nv50_disp_mast_mthd_base },
+ { "DAC", 3, &nv84_disp_mast_mthd_dac },
+ { "SOR", 2, &nv50_disp_mast_mthd_sor },
+ { "PIOR", 3, &nv50_disp_mast_mthd_pior },
+ { "HEAD", 2, &nv84_disp_mast_mthd_head },
+ {}
+ }
+};
+
+/*******************************************************************************
+ * EVO sync channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nv84_disp_sync_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x000000 },
+ { 0x0084, 0x0008c4 },
+ { 0x0088, 0x0008d0 },
+ { 0x008c, 0x0008dc },
+ { 0x0090, 0x0008e4 },
+ { 0x0094, 0x610884 },
+ { 0x00a0, 0x6108a0 },
+ { 0x00a4, 0x610878 },
+ { 0x00c0, 0x61086c },
+ { 0x00c4, 0x610800 },
+ { 0x00c8, 0x61080c },
+ { 0x00cc, 0x610818 },
+ { 0x00e0, 0x610858 },
+ { 0x00e4, 0x610860 },
+ { 0x00e8, 0x6108ac },
+ { 0x00ec, 0x6108b4 },
+ { 0x00fc, 0x610824 },
+ { 0x0100, 0x610894 },
+ { 0x0104, 0x61082c },
+ { 0x0110, 0x6108bc },
+ { 0x0114, 0x61088c },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_chan
+nv84_disp_sync_mthd_chan = {
+ .name = "Base",
+ .addr = 0x000540,
+ .data = {
+ { "Global", 1, &nv84_disp_sync_mthd_base },
+ { "Image", 2, &nv50_disp_sync_mthd_image },
+ {}
+ }
+};
+
+/*******************************************************************************
+ * EVO overlay channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nv84_disp_ovly_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x000000 },
+ { 0x0084, 0x6109a0 },
+ { 0x0088, 0x6109c0 },
+ { 0x008c, 0x6109c8 },
+ { 0x0090, 0x6109b4 },
+ { 0x0094, 0x610970 },
+ { 0x00a0, 0x610998 },
+ { 0x00a4, 0x610964 },
+ { 0x00c0, 0x610958 },
+ { 0x00e0, 0x6109a8 },
+ { 0x00e4, 0x6109d0 },
+ { 0x00e8, 0x6109d8 },
+ { 0x0100, 0x61094c },
+ { 0x0104, 0x610984 },
+ { 0x0108, 0x61098c },
+ { 0x0800, 0x6109f8 },
+ { 0x0808, 0x610a08 },
+ { 0x080c, 0x610a10 },
+ { 0x0810, 0x610a00 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_chan
+nv84_disp_ovly_mthd_chan = {
+ .name = "Overlay",
+ .addr = 0x000540,
+ .data = {
+ { "Global", 1, &nv84_disp_ovly_mthd_base },
+ {}
+ }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
static struct nouveau_oclass
nv84_disp_sclass[] = {
{ NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -41,11 +214,15 @@ nv84_disp_sclass[] = {
struct nouveau_omthds
nv84_disp_base_omthds[] = {
+ { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
};
@@ -55,6 +232,10 @@ nv84_disp_base_oclass[] = {
{}
};
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
static int
nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -63,7 +244,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
@@ -72,27 +253,32 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv84_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
+ INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nv84_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
priv->sor.nr = 2;
+ priv->pior.nr = 3;
priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
priv->sor.hdmi = nv84_hdmi_ctrl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
+ priv->pior.power = nv50_pior_power;
return 0;
}
-struct nouveau_oclass
-nv84_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x82),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv84_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x82),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv84_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+ .base.outp = nv50_disp_outp_sclass,
+ .mthd.core = &nv84_disp_mast_mthd_chan,
+ .mthd.base = &nv84_disp_sync_mthd_chan,
+ .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+ .mthd.prev = 0x000004,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index ba9dfd4669a..4f718a9f5ae 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -29,6 +29,38 @@
#include "nv50.h"
+/*******************************************************************************
+ * EVO master channel object
+ ******************************************************************************/
+
+const struct nv50_disp_mthd_list
+nv94_disp_mast_mthd_sor = {
+ .mthd = 0x0040,
+ .addr = 0x000008,
+ .data = {
+ { 0x0600, 0x610794 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_chan
+nv94_disp_mast_mthd_chan = {
+ .name = "Core",
+ .addr = 0x000000,
+ .data = {
+ { "Global", 1, &nv50_disp_mast_mthd_base },
+ { "DAC", 3, &nv84_disp_mast_mthd_dac },
+ { "SOR", 4, &nv94_disp_mast_mthd_sor },
+ { "PIOR", 3, &nv50_disp_mast_mthd_pior },
+ { "HEAD", 2, &nv84_disp_mast_mthd_head },
+ {}
+ }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
static struct nouveau_oclass
nv94_disp_sclass[] = {
{ NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -41,17 +73,16 @@ nv94_disp_sclass[] = {
static struct nouveau_omthds
nv94_disp_base_omthds[] = {
+ { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd },
+ { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
};
@@ -61,6 +92,10 @@ nv94_disp_base_oclass[] = {
{}
};
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
static int
nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -69,7 +104,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
@@ -78,32 +113,39 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv94_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
+ INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nv94_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
priv->sor.nr = 4;
+ priv->pior.nr = 3;
priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
priv->sor.hdmi = nv84_hdmi_ctrl;
- priv->sor.dp_train = nv94_sor_dp_train;
- priv->sor.dp_train_init = nv94_sor_dp_train_init;
- priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
- priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
- priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
+ priv->pior.power = nv50_pior_power;
return 0;
}
-struct nouveau_oclass
-nv94_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x88),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nv94_disp_outp_sclass[] = {
+ &nv50_pior_dp_impl.base.base,
+ &nv94_sor_dp_impl.base.base,
+ NULL
+};
+
+struct nouveau_oclass *
+nv94_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x88),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv94_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+ .base.outp = nv94_disp_outp_sclass,
+ .mthd.core = &nv94_disp_mast_mthd_chan,
+ .mthd.base = &nv84_disp_sync_mthd_chan,
+ .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+ .mthd.prev = 0x000004,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
index 5d63902cded..6237a9a36f7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
@@ -29,6 +29,55 @@
#include "nv50.h"
+/*******************************************************************************
+ * EVO overlay channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nva0_disp_ovly_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x000000 },
+ { 0x0084, 0x6109a0 },
+ { 0x0088, 0x6109c0 },
+ { 0x008c, 0x6109c8 },
+ { 0x0090, 0x6109b4 },
+ { 0x0094, 0x610970 },
+ { 0x00a0, 0x610998 },
+ { 0x00a4, 0x610964 },
+ { 0x00b0, 0x610c98 },
+ { 0x00b4, 0x610ca4 },
+ { 0x00b8, 0x610cac },
+ { 0x00c0, 0x610958 },
+ { 0x00e0, 0x6109a8 },
+ { 0x00e4, 0x6109d0 },
+ { 0x00e8, 0x6109d8 },
+ { 0x0100, 0x61094c },
+ { 0x0104, 0x610984 },
+ { 0x0108, 0x61098c },
+ { 0x0800, 0x6109f8 },
+ { 0x0808, 0x610a08 },
+ { 0x080c, 0x610a10 },
+ { 0x0810, 0x610a00 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_chan
+nva0_disp_ovly_mthd_chan = {
+ .name = "Overlay",
+ .addr = 0x000540,
+ .data = {
+ { "Global", 1, &nva0_disp_ovly_mthd_base },
+ {}
+ }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
static struct nouveau_oclass
nva0_disp_sclass[] = {
{ NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -45,6 +94,10 @@ nva0_disp_base_oclass[] = {
{}
};
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
static int
nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -53,7 +106,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
@@ -62,27 +115,32 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nva0_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
+ INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nva0_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
priv->sor.nr = 2;
+ priv->pior.nr = 3;
priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
priv->sor.hdmi = nv84_hdmi_ctrl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
+ priv->pior.power = nv50_pior_power;
return 0;
}
-struct nouveau_oclass
-nva0_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x83),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nva0_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x83),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nva0_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+ .base.outp = nv50_disp_outp_sclass,
+ .mthd.core = &nv84_disp_mast_mthd_chan,
+ .mthd.base = &nv84_disp_sync_mthd_chan,
+ .mthd.ovly = &nva0_disp_ovly_mthd_chan,
+ .mthd.prev = 0x000004,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index e9192ca389f..019124d4782 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -29,6 +29,10 @@
#include "nv50.h"
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
static struct nouveau_oclass
nva3_disp_sclass[] = {
{ NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
@@ -39,20 +43,19 @@ nva3_disp_sclass[] = {
{}
};
-struct nouveau_omthds
+static struct nouveau_omthds
nva3_disp_base_omthds[] = {
+ { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd },
- { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd },
+ { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
};
@@ -62,6 +65,10 @@ nva3_disp_base_oclass[] = {
{}
};
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
static int
nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -70,7 +77,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nv50_disp_priv *priv;
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
+ ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP",
"display", &priv);
*pobject = nv_object(priv);
if (ret)
@@ -79,33 +86,33 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nva3_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nv50_disp_intr;
+ INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
priv->sclass = nva3_disp_sclass;
priv->head.nr = 2;
priv->dac.nr = 3;
priv->sor.nr = 4;
+ priv->pior.nr = 3;
priv->dac.power = nv50_dac_power;
priv->dac.sense = nv50_dac_sense;
priv->sor.power = nv50_sor_power;
priv->sor.hda_eld = nva3_hda_eld;
priv->sor.hdmi = nva3_hdmi_ctrl;
- priv->sor.dp_train = nv94_sor_dp_train;
- priv->sor.dp_train_init = nv94_sor_dp_train_init;
- priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
- priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl;
- priv->sor.dp_drvctl = nv94_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
+ priv->pior.power = nv50_pior_power;
return 0;
}
-struct nouveau_oclass
-nva3_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x85),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nva3_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x85),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nva3_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+ .base.outp = nv94_disp_outp_sclass,
+ .mthd.core = &nv94_disp_mast_mthd_chan,
+ .mthd.base = &nv84_disp_sync_mthd_chan,
+ .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+ .mthd.prev = 0x000004,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 9e38ebff5fb..fa30d8196f3 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -27,19 +27,16 @@
#include <core/handle.h>
#include <core/class.h>
-#include <engine/software.h>
#include <engine/disp.h>
-#include <subdev/timer.h>
-#include <subdev/fb.h>
-#include <subdev/bar.h>
-#include <subdev/clock.h>
-
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
#include <subdev/bios/disp.h>
#include <subdev/bios/init.h>
#include <subdev/bios/pll.h>
+#include <subdev/devinit.h>
+#include <subdev/fb.h>
+#include <subdev/timer.h>
#include "nv50.h"
@@ -127,6 +124,146 @@ nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend)
* EVO master channel object
******************************************************************************/
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x660080 },
+ { 0x0084, 0x660084 },
+ { 0x0088, 0x660088 },
+ { 0x008c, 0x000000 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_dac = {
+ .mthd = 0x0020,
+ .addr = 0x000020,
+ .data = {
+ { 0x0180, 0x660180 },
+ { 0x0184, 0x660184 },
+ { 0x0188, 0x660188 },
+ { 0x0190, 0x660190 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_sor = {
+ .mthd = 0x0020,
+ .addr = 0x000020,
+ .data = {
+ { 0x0200, 0x660200 },
+ { 0x0204, 0x660204 },
+ { 0x0208, 0x660208 },
+ { 0x0210, 0x660210 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_pior = {
+ .mthd = 0x0020,
+ .addr = 0x000020,
+ .data = {
+ { 0x0300, 0x660300 },
+ { 0x0304, 0x660304 },
+ { 0x0308, 0x660308 },
+ { 0x0310, 0x660310 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_list
+nvd0_disp_mast_mthd_head = {
+ .mthd = 0x0300,
+ .addr = 0x000300,
+ .data = {
+ { 0x0400, 0x660400 },
+ { 0x0404, 0x660404 },
+ { 0x0408, 0x660408 },
+ { 0x040c, 0x66040c },
+ { 0x0410, 0x660410 },
+ { 0x0414, 0x660414 },
+ { 0x0418, 0x660418 },
+ { 0x041c, 0x66041c },
+ { 0x0420, 0x660420 },
+ { 0x0424, 0x660424 },
+ { 0x0428, 0x660428 },
+ { 0x042c, 0x66042c },
+ { 0x0430, 0x660430 },
+ { 0x0434, 0x660434 },
+ { 0x0438, 0x660438 },
+ { 0x0440, 0x660440 },
+ { 0x0444, 0x660444 },
+ { 0x0448, 0x660448 },
+ { 0x044c, 0x66044c },
+ { 0x0450, 0x660450 },
+ { 0x0454, 0x660454 },
+ { 0x0458, 0x660458 },
+ { 0x045c, 0x66045c },
+ { 0x0460, 0x660460 },
+ { 0x0468, 0x660468 },
+ { 0x046c, 0x66046c },
+ { 0x0470, 0x660470 },
+ { 0x0474, 0x660474 },
+ { 0x0480, 0x660480 },
+ { 0x0484, 0x660484 },
+ { 0x048c, 0x66048c },
+ { 0x0490, 0x660490 },
+ { 0x0494, 0x660494 },
+ { 0x0498, 0x660498 },
+ { 0x04b0, 0x6604b0 },
+ { 0x04b8, 0x6604b8 },
+ { 0x04bc, 0x6604bc },
+ { 0x04c0, 0x6604c0 },
+ { 0x04c4, 0x6604c4 },
+ { 0x04c8, 0x6604c8 },
+ { 0x04d0, 0x6604d0 },
+ { 0x04d4, 0x6604d4 },
+ { 0x04e0, 0x6604e0 },
+ { 0x04e4, 0x6604e4 },
+ { 0x04e8, 0x6604e8 },
+ { 0x04ec, 0x6604ec },
+ { 0x04f0, 0x6604f0 },
+ { 0x04f4, 0x6604f4 },
+ { 0x04f8, 0x6604f8 },
+ { 0x04fc, 0x6604fc },
+ { 0x0500, 0x660500 },
+ { 0x0504, 0x660504 },
+ { 0x0508, 0x660508 },
+ { 0x050c, 0x66050c },
+ { 0x0510, 0x660510 },
+ { 0x0514, 0x660514 },
+ { 0x0518, 0x660518 },
+ { 0x051c, 0x66051c },
+ { 0x052c, 0x66052c },
+ { 0x0530, 0x660530 },
+ { 0x054c, 0x66054c },
+ { 0x0550, 0x660550 },
+ { 0x0554, 0x660554 },
+ { 0x0558, 0x660558 },
+ { 0x055c, 0x66055c },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_chan
+nvd0_disp_mast_mthd_chan = {
+ .name = "Core",
+ .addr = 0x000000,
+ .data = {
+ { "Global", 1, &nvd0_disp_mast_mthd_base },
+ { "DAC", 3, &nvd0_disp_mast_mthd_dac },
+ { "SOR", 8, &nvd0_disp_mast_mthd_sor },
+ { "PIOR", 4, &nvd0_disp_mast_mthd_pior },
+ { "HEAD", 4, &nvd0_disp_mast_mthd_head },
+ {}
+ }
+};
+
static int
nvd0_disp_mast_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -219,6 +356,81 @@ nvd0_disp_mast_ofuncs = {
* EVO sync channel objects
******************************************************************************/
+static const struct nv50_disp_mthd_list
+nvd0_disp_sync_mthd_base = {
+ .mthd = 0x0000,
+ .addr = 0x000000,
+ .data = {
+ { 0x0080, 0x661080 },
+ { 0x0084, 0x661084 },
+ { 0x0088, 0x661088 },
+ { 0x008c, 0x66108c },
+ { 0x0090, 0x661090 },
+ { 0x0094, 0x661094 },
+ { 0x00a0, 0x6610a0 },
+ { 0x00a4, 0x6610a4 },
+ { 0x00c0, 0x6610c0 },
+ { 0x00c4, 0x6610c4 },
+ { 0x00c8, 0x6610c8 },
+ { 0x00cc, 0x6610cc },
+ { 0x00e0, 0x6610e0 },
+ { 0x00e4, 0x6610e4 },
+ { 0x00e8, 0x6610e8 },
+ { 0x00ec, 0x6610ec },
+ { 0x00fc, 0x6610fc },
+ { 0x0100, 0x661100 },
+ { 0x0104, 0x661104 },
+ { 0x0108, 0x661108 },
+ { 0x010c, 0x66110c },
+ { 0x0110, 0x661110 },
+ { 0x0114, 0x661114 },
+ { 0x0118, 0x661118 },
+ { 0x011c, 0x66111c },
+ { 0x0130, 0x661130 },
+ { 0x0134, 0x661134 },
+ { 0x0138, 0x661138 },
+ { 0x013c, 0x66113c },
+ { 0x0140, 0x661140 },
+ { 0x0144, 0x661144 },
+ { 0x0148, 0x661148 },
+ { 0x014c, 0x66114c },
+ { 0x0150, 0x661150 },
+ { 0x0154, 0x661154 },
+ { 0x0158, 0x661158 },
+ { 0x015c, 0x66115c },
+ { 0x0160, 0x661160 },
+ { 0x0164, 0x661164 },
+ { 0x0168, 0x661168 },
+ { 0x016c, 0x66116c },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_list
+nvd0_disp_sync_mthd_image = {
+ .mthd = 0x0400,
+ .addr = 0x000400,
+ .data = {
+ { 0x0400, 0x661400 },
+ { 0x0404, 0x661404 },
+ { 0x0408, 0x661408 },
+ { 0x040c, 0x66140c },
+ { 0x0410, 0x661410 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_chan
+nvd0_disp_sync_mthd_chan = {
+ .name = "Base",
+ .addr = 0x001000,
+ .data = {
+ { "Global", 1, &nvd0_disp_sync_mthd_base },
+ { "Image", 2, &nvd0_disp_sync_mthd_image },
+ {}
+ }
+};
+
static int
nvd0_disp_sync_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -230,7 +442,7 @@ nvd0_disp_sync_ctor(struct nouveau_object *parent,
struct nv50_disp_dmac *dmac;
int ret;
- if (size < sizeof(*data) || args->head >= priv->head.nr)
+ if (size < sizeof(*args) || args->head >= priv->head.nr)
return -EINVAL;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -259,6 +471,68 @@ nvd0_disp_sync_ofuncs = {
* EVO overlay channel objects
******************************************************************************/
+static const struct nv50_disp_mthd_list
+nvd0_disp_ovly_mthd_base = {
+ .mthd = 0x0000,
+ .data = {
+ { 0x0080, 0x665080 },
+ { 0x0084, 0x665084 },
+ { 0x0088, 0x665088 },
+ { 0x008c, 0x66508c },
+ { 0x0090, 0x665090 },
+ { 0x0094, 0x665094 },
+ { 0x00a0, 0x6650a0 },
+ { 0x00a4, 0x6650a4 },
+ { 0x00b0, 0x6650b0 },
+ { 0x00b4, 0x6650b4 },
+ { 0x00b8, 0x6650b8 },
+ { 0x00c0, 0x6650c0 },
+ { 0x00e0, 0x6650e0 },
+ { 0x00e4, 0x6650e4 },
+ { 0x00e8, 0x6650e8 },
+ { 0x0100, 0x665100 },
+ { 0x0104, 0x665104 },
+ { 0x0108, 0x665108 },
+ { 0x010c, 0x66510c },
+ { 0x0110, 0x665110 },
+ { 0x0118, 0x665118 },
+ { 0x011c, 0x66511c },
+ { 0x0120, 0x665120 },
+ { 0x0124, 0x665124 },
+ { 0x0130, 0x665130 },
+ { 0x0134, 0x665134 },
+ { 0x0138, 0x665138 },
+ { 0x013c, 0x66513c },
+ { 0x0140, 0x665140 },
+ { 0x0144, 0x665144 },
+ { 0x0148, 0x665148 },
+ { 0x014c, 0x66514c },
+ { 0x0150, 0x665150 },
+ { 0x0154, 0x665154 },
+ { 0x0158, 0x665158 },
+ { 0x015c, 0x66515c },
+ { 0x0160, 0x665160 },
+ { 0x0164, 0x665164 },
+ { 0x0168, 0x665168 },
+ { 0x016c, 0x66516c },
+ { 0x0400, 0x665400 },
+ { 0x0408, 0x665408 },
+ { 0x040c, 0x66540c },
+ { 0x0410, 0x665410 },
+ {}
+ }
+};
+
+static const struct nv50_disp_mthd_chan
+nvd0_disp_ovly_mthd_chan = {
+ .name = "Overlay",
+ .addr = 0x001000,
+ .data = {
+ { "Global", 1, &nvd0_disp_ovly_mthd_base },
+ {}
+ }
+};
+
static int
nvd0_disp_ovly_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
@@ -270,7 +544,7 @@ nvd0_disp_ovly_ctor(struct nouveau_object *parent,
struct nv50_disp_dmac *dmac;
int ret;
- if (size < sizeof(*data) || args->head >= priv->head.nr)
+ if (size < sizeof(*args) || args->head >= priv->head.nr)
return -EINVAL;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
@@ -444,6 +718,48 @@ nvd0_disp_curs_ofuncs = {
******************************************************************************/
static int
+nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
+ void *data, u32 size)
+{
+ struct nv50_disp_priv *priv = (void *)object->engine;
+ struct nv04_display_scanoutpos *args = data;
+ const int head = (mthd & NV50_DISP_MTHD_HEAD);
+ u32 blanke, blanks, total;
+
+ if (size < sizeof(*args) || head >= priv->head.nr)
+ return -EINVAL;
+
+ total = nv_rd32(priv, 0x640414 + (head * 0x300));
+ blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
+ blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
+
+ args->vblanke = (blanke & 0xffff0000) >> 16;
+ args->hblanke = (blanke & 0x0000ffff);
+ args->vblanks = (blanks & 0xffff0000) >> 16;
+ args->hblanks = (blanks & 0x0000ffff);
+ args->vtotal = ( total & 0xffff0000) >> 16;
+ args->htotal = ( total & 0x0000ffff);
+
+ args->time[0] = ktime_to_ns(ktime_get());
+ args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
+ args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
+ args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
+ return 0;
+}
+
+static void
+nvd0_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
+{
+ nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
+}
+
+static void
+nvd0_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
+{
+ nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
+}
+
+static int
nvd0_disp_base_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@@ -459,7 +775,12 @@ nvd0_disp_base_ctor(struct nouveau_object *parent,
if (ret)
return ret;
- return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht);
+ priv->base.vblank->priv = priv;
+ priv->base.vblank->enable = nvd0_disp_base_vblank_enable;
+ priv->base.vblank->disable = nvd0_disp_base_vblank_disable;
+
+ return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
+ &base->ramht);
}
static void
@@ -527,6 +848,15 @@ nvd0_disp_base_init(struct nouveau_object *object)
nv_wr32(priv, 0x6100a0, 0x00000000);
nv_wr32(priv, 0x6100b0, 0x00000307);
+ /* disable underflow reporting, preventing an intermittent issue
+ * on some nve4 boards where the production vbios left this
+ * setting enabled by default.
+ *
+ * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt
+ */
+ for (i = 0; i < priv->head.nr; i++)
+ nv_mask(priv, 0x616308 + (i * 0x800), 0x00000111, 0x00000010);
+
return 0;
}
@@ -550,9 +880,25 @@ nvd0_disp_base_ofuncs = {
.fini = nvd0_disp_base_fini,
};
+struct nouveau_omthds
+nvd0_disp_base_omthds[] = {
+ { HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
+ { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
+ { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
+ { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
+ { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
+ { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
+ { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
+ { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
+ { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
+ {},
+};
+
static struct nouveau_oclass
nvd0_disp_base_oclass[] = {
- { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
+ { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
{}
};
@@ -570,19 +916,20 @@ nvd0_disp_sclass[] = {
* Display engine implementation
******************************************************************************/
-static u16
-exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
- struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+static struct nvkm_output *
+exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
+ u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_outp *info)
{
struct nouveau_bios *bios = nouveau_bios(priv);
- u16 mask, type, data;
+ struct nvkm_output *outp;
+ u16 mask, type;
- if (outp < 4) {
+ if (or < 4) {
type = DCB_OUTPUT_ANALOG;
mask = 0;
} else {
- outp -= 4;
+ or -= 4;
switch (ctrl & 0x00000f00) {
case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
@@ -594,120 +941,168 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
return 0x0000;
}
- dcb->sorconf.link = mask;
}
mask = 0x00c0 & (mask << 6);
- mask |= 0x0001 << outp;
+ mask |= 0x0001 << or;
mask |= 0x0100 << head;
- data = dcb_outp_match(bios, type, mask, ver, hdr, dcb);
- if (!data)
- return 0x0000;
+ list_for_each_entry(outp, &priv->base.outp, head) {
+ if ((outp->info.hasht & 0xff) == type &&
+ (outp->info.hashm & mask) == mask) {
+ *data = nvbios_outp_match(bios, outp->info.hasht,
+ outp->info.hashm,
+ ver, hdr, cnt, len, info);
+ if (!*data)
+ return NULL;
+ return outp;
+ }
+ }
- return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info);
+ return NULL;
}
-static bool
-exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id)
+static struct nvkm_output *
+exec_script(struct nv50_disp_priv *priv, int head, int id)
{
struct nouveau_bios *bios = nouveau_bios(priv);
+ struct nvkm_output *outp;
struct nvbios_outp info;
- struct dcb_output dcb;
u8 ver, hdr, cnt, len;
- u16 data;
+ u32 data, ctrl = 0;
+ int or;
+
+ for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
+ ctrl = nv_rd32(priv, 0x640180 + (or * 0x20));
+ if (ctrl & (1 << head))
+ break;
+ }
+
+ if (or == 8)
+ return NULL;
- data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info);
- if (data) {
+ outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
+ if (outp) {
struct nvbios_init init = {
.subdev = nv_subdev(priv),
.bios = bios,
.offset = info.script[id],
- .outp = &dcb,
+ .outp = &outp->info,
.crtc = head,
.execute = 1,
};
- return nvbios_exec(&init) == 0;
+ nvbios_exec(&init);
}
- return false;
+ return outp;
}
-static u32
-exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp,
- u32 ctrl, int id, u32 pclk)
+static struct nvkm_output *
+exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf)
{
struct nouveau_bios *bios = nouveau_bios(priv);
+ struct nvkm_output *outp;
struct nvbios_outp info1;
struct nvbios_ocfg info2;
- struct dcb_output dcb;
u8 ver, hdr, cnt, len;
- u16 data, conf;
+ u32 data, ctrl = 0;
+ int or;
- data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info1);
- if (data == 0x0000)
- return false;
+ for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
+ ctrl = nv_rd32(priv, 0x660180 + (or * 0x20));
+ if (ctrl & (1 << head))
+ break;
+ }
+
+ if (or == 8)
+ return NULL;
- switch (dcb.type) {
+ outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
+ if (!outp)
+ return NULL;
+
+ switch (outp->info.type) {
case DCB_OUTPUT_TMDS:
- conf = (ctrl & 0x00000f00) >> 8;
+ *conf = (ctrl & 0x00000f00) >> 8;
if (pclk >= 165000)
- conf |= 0x0100;
+ *conf |= 0x0100;
break;
case DCB_OUTPUT_LVDS:
- conf = priv->sor.lvdsconf;
+ *conf = priv->sor.lvdsconf;
break;
case DCB_OUTPUT_DP:
- conf = (ctrl & 0x00000f00) >> 8;
+ *conf = (ctrl & 0x00000f00) >> 8;
break;
case DCB_OUTPUT_ANALOG:
default:
- conf = 0x00ff;
+ *conf = 0x00ff;
break;
}
- data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
- if (data) {
+ data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+ if (data && id < 0xff) {
data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
if (data) {
struct nvbios_init init = {
.subdev = nv_subdev(priv),
.bios = bios,
.offset = data,
- .outp = &dcb,
+ .outp = &outp->info,
.crtc = head,
.execute = 1,
};
- if (nvbios_exec(&init))
- return 0x0000;
- return conf;
+ nvbios_exec(&init);
}
}
- return 0x0000;
+ return outp;
}
static void
-nvd0_display_unk1_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
+nvd0_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head)
{
- int i;
+ exec_script(priv, head, 1);
+}
+
+static void
+nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head)
+{
+ struct nvkm_output *outp = exec_script(priv, head, 2);
- for (i = 0; mask && i < 8; i++) {
- u32 mcc = nv_rd32(priv, 0x640180 + (i * 0x20));
- if (mcc & (1 << head))
- exec_script(priv, head, i, mcc, 1);
+ /* see note in nv50_disp_intr_unk20_0() */
+ if (outp && outp->info.type == DCB_OUTPUT_DP) {
+ struct nvkm_output_dp *outpdp = (void *)outp;
+ struct nvbios_init init = {
+ .subdev = nv_subdev(priv),
+ .bios = nouveau_bios(priv),
+ .outp = &outp->info,
+ .crtc = head,
+ .offset = outpdp->info.script[4],
+ .execute = 1,
+ };
+
+ nvbios_exec(&init);
+ atomic_set(&outpdp->lt.done, 0);
}
+}
- nv_wr32(priv, 0x6101d4, 0x00000000);
- nv_wr32(priv, 0x6109d4, 0x00000000);
- nv_wr32(priv, 0x6101d0, 0x80000000);
+static void
+nvd0_disp_intr_unk2_1(struct nv50_disp_priv *priv, int head)
+{
+ struct nouveau_devinit *devinit = nouveau_devinit(priv);
+ u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
+ if (pclk)
+ devinit->pll_set(devinit, PLL_VPLL0 + head, pclk);
+ nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000);
}
static void
-nvd0_display_unk2_calc_tu(struct nv50_disp_priv *priv, int head, int or)
+nvd0_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head,
+ struct dcb_output *outp)
{
+ const int or = ffs(outp->or) - 1;
const u32 ctrl = nv_rd32(priv, 0x660200 + (or * 0x020));
const u32 conf = nv_rd32(priv, 0x660404 + (head * 0x300));
const u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
@@ -750,105 +1145,159 @@ nvd0_display_unk2_calc_tu(struct nv50_disp_priv *priv, int head, int or)
}
static void
-nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
+nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head)
{
- u32 pclk;
- int i;
+ struct nvkm_output *outp;
+ u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
+ u32 conf, addr, data;
+
+ outp = exec_clkcmp(priv, head, 0xff, pclk, &conf);
+ if (!outp)
+ return;
+
+ /* see note in nv50_disp_intr_unk20_2() */
+ if (outp->info.type == DCB_OUTPUT_DP) {
+ u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300));
+ switch ((sync & 0x000003c0) >> 6) {
+ case 6: pclk = pclk * 30; break;
+ case 5: pclk = pclk * 24; break;
+ case 2:
+ default:
+ pclk = pclk * 18;
+ break;
+ }
- for (i = 0; mask && i < 8; i++) {
- u32 mcc = nv_rd32(priv, 0x640180 + (i * 0x20));
- if (mcc & (1 << head))
- exec_script(priv, head, i, mcc, 2);
+ if (nvkm_output_dp_train(outp, pclk, true))
+ ERR("link not trained before attach\n");
}
- pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
- nv_debug(priv, "head %d pclk %d mask 0x%08x\n", head, pclk, mask);
- if (pclk && (mask & 0x00010000)) {
- struct nouveau_clock *clk = nouveau_clock(priv);
- clk->pll_set(clk, PLL_VPLL0 + head, pclk);
- }
+ exec_clkcmp(priv, head, 0, pclk, &conf);
- nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000);
-
- for (i = 0; mask && i < 8; i++) {
- u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)), cfg;
- if (mcp & (1 << head)) {
- if ((cfg = exec_clkcmp(priv, head, i, mcp, 0, pclk))) {
- u32 addr, mask, data = 0x00000000;
- if (i < 4) {
- addr = 0x612280 + ((i - 0) * 0x800);
- mask = 0xffffffff;
- } else {
- switch (mcp & 0x00000f00) {
- case 0x00000800:
- case 0x00000900:
- nvd0_display_unk2_calc_tu(priv, head, i - 4);
- break;
- default:
- break;
- }
-
- addr = 0x612300 + ((i - 4) * 0x800);
- mask = 0x00000707;
- if (cfg & 0x00000100)
- data = 0x00000101;
- }
- nv_mask(priv, addr, mask, data);
- }
- break;
- }
+ if (outp->info.type == DCB_OUTPUT_ANALOG) {
+ addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800;
+ data = 0x00000000;
+ } else {
+ if (outp->info.type == DCB_OUTPUT_DP)
+ nvd0_disp_intr_unk2_2_tu(priv, head, &outp->info);
+ addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800;
+ data = (conf & 0x0100) ? 0x00000101 : 0x00000000;
}
- nv_wr32(priv, 0x6101d4, 0x00000000);
- nv_wr32(priv, 0x6109d4, 0x00000000);
- nv_wr32(priv, 0x6101d0, 0x80000000);
+ nv_mask(priv, addr, 0x00000707, data);
}
static void
-nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
+nvd0_disp_intr_unk4_0(struct nv50_disp_priv *priv, int head)
{
- int pclk, i;
+ u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
+ u32 conf;
- pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
+ exec_clkcmp(priv, head, 1, pclk, &conf);
+}
- for (i = 0; mask && i < 8; i++) {
- u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20));
- if (mcp & (1 << head))
- exec_clkcmp(priv, head, i, mcp, 1, pclk);
+void
+nvd0_disp_intr_supervisor(struct work_struct *work)
+{
+ struct nv50_disp_priv *priv =
+ container_of(work, struct nv50_disp_priv, supervisor);
+ struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
+ u32 mask[4];
+ int head;
+
+ nv_debug(priv, "supervisor %d\n", ffs(priv->super));
+ for (head = 0; head < priv->head.nr; head++) {
+ mask[head] = nv_rd32(priv, 0x6101d4 + (head * 0x800));
+ nv_debug(priv, "head %d: 0x%08x\n", head, mask[head]);
}
- nv_wr32(priv, 0x6101d4, 0x00000000);
- nv_wr32(priv, 0x6109d4, 0x00000000);
+ if (priv->super & 0x00000001) {
+ nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(mask[head] & 0x00001000))
+ continue;
+ nv_debug(priv, "supervisor 1.0 - head %d\n", head);
+ nvd0_disp_intr_unk1_0(priv, head);
+ }
+ } else
+ if (priv->super & 0x00000002) {
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(mask[head] & 0x00001000))
+ continue;
+ nv_debug(priv, "supervisor 2.0 - head %d\n", head);
+ nvd0_disp_intr_unk2_0(priv, head);
+ }
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(mask[head] & 0x00010000))
+ continue;
+ nv_debug(priv, "supervisor 2.1 - head %d\n", head);
+ nvd0_disp_intr_unk2_1(priv, head);
+ }
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(mask[head] & 0x00001000))
+ continue;
+ nv_debug(priv, "supervisor 2.2 - head %d\n", head);
+ nvd0_disp_intr_unk2_2(priv, head);
+ }
+ } else
+ if (priv->super & 0x00000004) {
+ for (head = 0; head < priv->head.nr; head++) {
+ if (!(mask[head] & 0x00001000))
+ continue;
+ nv_debug(priv, "supervisor 3.0 - head %d\n", head);
+ nvd0_disp_intr_unk4_0(priv, head);
+ }
+ }
+
+ for (head = 0; head < priv->head.nr; head++)
+ nv_wr32(priv, 0x6101d4 + (head * 0x800), 0x00000000);
nv_wr32(priv, 0x6101d0, 0x80000000);
}
static void
-nvd0_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
+nvd0_disp_intr_error(struct nv50_disp_priv *priv, int chid)
{
- struct nouveau_bar *bar = nouveau_bar(priv);
- struct nouveau_disp *disp = &priv->base;
- struct nouveau_software_chan *chan, *temp;
- unsigned long flags;
-
- spin_lock_irqsave(&disp->vblank.lock, flags);
- list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) {
- if (chan->vblank.crtc != crtc)
- continue;
-
- nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
- bar->flush(bar);
- nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset));
- nv_wr32(priv, 0x060014, chan->vblank.value);
-
- list_del(&chan->vblank.head);
- if (disp->vblank.put)
- disp->vblank.put(disp->vblank.data, crtc);
+ const struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
+ u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
+ u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
+ u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
+
+ nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
+ "0x%08x 0x%08x\n",
+ chid, (mthd & 0x0000ffc), data, mthd, unkn);
+
+ if (chid == 0) {
+ switch (mthd & 0xffc) {
+ case 0x0080:
+ nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
+ impl->mthd.core);
+ break;
+ default:
+ break;
+ }
+ } else
+ if (chid <= 4) {
+ switch (mthd & 0xffc) {
+ case 0x0080:
+ nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
+ impl->mthd.base);
+ break;
+ default:
+ break;
+ }
+ } else
+ if (chid <= 8) {
+ switch (mthd & 0xffc) {
+ case 0x0080:
+ nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 5,
+ impl->mthd.ovly);
+ break;
+ default:
+ break;
+ }
}
- spin_unlock_irqrestore(&disp->vblank.lock, flags);
- if (disp->vblank.notify)
- disp->vblank.notify(disp->vblank.data, crtc);
+ nv_wr32(priv, 0x61009c, (1 << chid));
+ nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
}
void
@@ -867,44 +1316,18 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
if (intr & 0x00000002) {
u32 stat = nv_rd32(priv, 0x61009c);
int chid = ffs(stat) - 1;
- if (chid >= 0) {
- u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12));
- u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12));
- u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12));
-
- nv_error(priv, "chid %d mthd 0x%04x data 0x%08x "
- "0x%08x 0x%08x\n",
- chid, (mthd & 0x0000ffc), data, mthd, unkn);
- nv_wr32(priv, 0x61009c, (1 << chid));
- nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000);
- }
-
+ if (chid >= 0)
+ nvd0_disp_intr_error(priv, chid);
intr &= ~0x00000002;
}
if (intr & 0x00100000) {
u32 stat = nv_rd32(priv, 0x6100ac);
- u32 mask = 0, crtc = ~0;
-
- while (!mask && ++crtc < priv->head.nr)
- mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800));
-
- if (stat & 0x00000001) {
- nv_wr32(priv, 0x6100ac, 0x00000001);
- nvd0_display_unk1_handler(priv, crtc, mask);
- stat &= ~0x00000001;
- }
-
- if (stat & 0x00000002) {
- nv_wr32(priv, 0x6100ac, 0x00000002);
- nvd0_display_unk2_handler(priv, crtc, mask);
- stat &= ~0x00000002;
- }
-
- if (stat & 0x00000004) {
- nv_wr32(priv, 0x6100ac, 0x00000004);
- nvd0_display_unk4_handler(priv, crtc, mask);
- stat &= ~0x00000004;
+ if (stat & 0x00000007) {
+ priv->super = (stat & 0x00000007);
+ schedule_work(&priv->supervisor);
+ nv_wr32(priv, 0x6100ac, priv->super);
+ stat &= ~0x00000007;
}
if (stat) {
@@ -920,7 +1343,7 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
if (mask & intr) {
u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
if (stat & 0x00000001)
- nvd0_disp_intr_vblank(priv, i);
+ nouveau_event_trigger(priv->base.vblank, 1, i);
nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
nv_rd32(priv, 0x6100c0 + (i * 0x800));
}
@@ -933,10 +1356,11 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_object **pobject)
{
struct nv50_disp_priv *priv;
+ int heads = nv_rd32(parent, 0x022448);
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
- "display", &priv);
+ ret = nouveau_disp_create(parent, engine, oclass, heads,
+ "PDISP", "display", &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
@@ -944,8 +1368,9 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nvd0_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nvd0_disp_intr;
+ INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
priv->sclass = nvd0_disp_sclass;
- priv->head.nr = nv_rd32(priv, 0x022448);
+ priv->head.nr = heads;
priv->dac.nr = 3;
priv->sor.nr = 4;
priv->dac.power = nv50_dac_power;
@@ -953,24 +1378,27 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->sor.power = nv50_sor_power;
priv->sor.hda_eld = nvd0_hda_eld;
priv->sor.hdmi = nvd0_hdmi_ctrl;
- priv->sor.dp_train = nvd0_sor_dp_train;
- priv->sor.dp_train_init = nv94_sor_dp_train_init;
- priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
- priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
- priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
-struct nouveau_oclass
-nvd0_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x90),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nvd0_disp_outp_sclass[] = {
+ &nvd0_sor_dp_impl.base.base,
+ NULL
+};
+
+struct nouveau_oclass *
+nvd0_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x90),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvd0_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+ .base.outp = nvd0_disp_outp_sclass,
+ .mthd.core = &nvd0_disp_mast_mthd_chan,
+ .mthd.base = &nvd0_disp_sync_mthd_chan,
+ .mthd.ovly = &nvd0_disp_ovly_mthd_chan,
+ .mthd.prev = -0x020000,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index 259537c4587..11328e3f5df 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -29,6 +29,175 @@
#include "nv50.h"
+/*******************************************************************************
+ * EVO master channel object
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nve0_disp_mast_mthd_head = {
+ .mthd = 0x0300,
+ .addr = 0x000300,
+ .data = {
+ { 0x0400, 0x660400 },
+ { 0x0404, 0x660404 },
+ { 0x0408, 0x660408 },
+ { 0x040c, 0x66040c },
+ { 0x0410, 0x660410 },
+ { 0x0414, 0x660414 },
+ { 0x0418, 0x660418 },
+ { 0x041c, 0x66041c },
+ { 0x0420, 0x660420 },
+ { 0x0424, 0x660424 },
+ { 0x0428, 0x660428 },
+ { 0x042c, 0x66042c },
+ { 0x0430, 0x660430 },
+ { 0x0434, 0x660434 },
+ { 0x0438, 0x660438 },
+ { 0x0440, 0x660440 },
+ { 0x0444, 0x660444 },
+ { 0x0448, 0x660448 },
+ { 0x044c, 0x66044c },
+ { 0x0450, 0x660450 },
+ { 0x0454, 0x660454 },
+ { 0x0458, 0x660458 },
+ { 0x045c, 0x66045c },
+ { 0x0460, 0x660460 },
+ { 0x0468, 0x660468 },
+ { 0x046c, 0x66046c },
+ { 0x0470, 0x660470 },
+ { 0x0474, 0x660474 },
+ { 0x047c, 0x66047c },
+ { 0x0480, 0x660480 },
+ { 0x0484, 0x660484 },
+ { 0x0488, 0x660488 },
+ { 0x048c, 0x66048c },
+ { 0x0490, 0x660490 },
+ { 0x0494, 0x660494 },
+ { 0x0498, 0x660498 },
+ { 0x04a0, 0x6604a0 },
+ { 0x04b0, 0x6604b0 },
+ { 0x04b8, 0x6604b8 },
+ { 0x04bc, 0x6604bc },
+ { 0x04c0, 0x6604c0 },
+ { 0x04c4, 0x6604c4 },
+ { 0x04c8, 0x6604c8 },
+ { 0x04d0, 0x6604d0 },
+ { 0x04d4, 0x6604d4 },
+ { 0x04e0, 0x6604e0 },
+ { 0x04e4, 0x6604e4 },
+ { 0x04e8, 0x6604e8 },
+ { 0x04ec, 0x6604ec },
+ { 0x04f0, 0x6604f0 },
+ { 0x04f4, 0x6604f4 },
+ { 0x04f8, 0x6604f8 },
+ { 0x04fc, 0x6604fc },
+ { 0x0500, 0x660500 },
+ { 0x0504, 0x660504 },
+ { 0x0508, 0x660508 },
+ { 0x050c, 0x66050c },
+ { 0x0510, 0x660510 },
+ { 0x0514, 0x660514 },
+ { 0x0518, 0x660518 },
+ { 0x051c, 0x66051c },
+ { 0x0520, 0x660520 },
+ { 0x0524, 0x660524 },
+ { 0x052c, 0x66052c },
+ { 0x0530, 0x660530 },
+ { 0x054c, 0x66054c },
+ { 0x0550, 0x660550 },
+ { 0x0554, 0x660554 },
+ { 0x0558, 0x660558 },
+ { 0x055c, 0x66055c },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_chan
+nve0_disp_mast_mthd_chan = {
+ .name = "Core",
+ .addr = 0x000000,
+ .data = {
+ { "Global", 1, &nvd0_disp_mast_mthd_base },
+ { "DAC", 3, &nvd0_disp_mast_mthd_dac },
+ { "SOR", 8, &nvd0_disp_mast_mthd_sor },
+ { "PIOR", 4, &nvd0_disp_mast_mthd_pior },
+ { "HEAD", 4, &nve0_disp_mast_mthd_head },
+ {}
+ }
+};
+
+/*******************************************************************************
+ * EVO overlay channel objects
+ ******************************************************************************/
+
+static const struct nv50_disp_mthd_list
+nve0_disp_ovly_mthd_base = {
+ .mthd = 0x0000,
+ .data = {
+ { 0x0080, 0x665080 },
+ { 0x0084, 0x665084 },
+ { 0x0088, 0x665088 },
+ { 0x008c, 0x66508c },
+ { 0x0090, 0x665090 },
+ { 0x0094, 0x665094 },
+ { 0x00a0, 0x6650a0 },
+ { 0x00a4, 0x6650a4 },
+ { 0x00b0, 0x6650b0 },
+ { 0x00b4, 0x6650b4 },
+ { 0x00b8, 0x6650b8 },
+ { 0x00c0, 0x6650c0 },
+ { 0x00c4, 0x6650c4 },
+ { 0x00e0, 0x6650e0 },
+ { 0x00e4, 0x6650e4 },
+ { 0x00e8, 0x6650e8 },
+ { 0x0100, 0x665100 },
+ { 0x0104, 0x665104 },
+ { 0x0108, 0x665108 },
+ { 0x010c, 0x66510c },
+ { 0x0110, 0x665110 },
+ { 0x0118, 0x665118 },
+ { 0x011c, 0x66511c },
+ { 0x0120, 0x665120 },
+ { 0x0124, 0x665124 },
+ { 0x0130, 0x665130 },
+ { 0x0134, 0x665134 },
+ { 0x0138, 0x665138 },
+ { 0x013c, 0x66513c },
+ { 0x0140, 0x665140 },
+ { 0x0144, 0x665144 },
+ { 0x0148, 0x665148 },
+ { 0x014c, 0x66514c },
+ { 0x0150, 0x665150 },
+ { 0x0154, 0x665154 },
+ { 0x0158, 0x665158 },
+ { 0x015c, 0x66515c },
+ { 0x0160, 0x665160 },
+ { 0x0164, 0x665164 },
+ { 0x0168, 0x665168 },
+ { 0x016c, 0x66516c },
+ { 0x0400, 0x665400 },
+ { 0x0404, 0x665404 },
+ { 0x0408, 0x665408 },
+ { 0x040c, 0x66540c },
+ { 0x0410, 0x665410 },
+ {}
+ }
+};
+
+const struct nv50_disp_mthd_chan
+nve0_disp_ovly_mthd_chan = {
+ .name = "Overlay",
+ .addr = 0x001000,
+ .data = {
+ { "Global", 1, &nve0_disp_ovly_mthd_base },
+ {}
+ }
+};
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
static struct nouveau_oclass
nve0_disp_sclass[] = {
{ NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
@@ -41,20 +210,25 @@ nve0_disp_sclass[] = {
static struct nouveau_oclass
nve0_disp_base_oclass[] = {
- { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
+ { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
{}
};
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
static int
nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_disp_priv *priv;
+ int heads = nv_rd32(parent, 0x022448);
int ret;
- ret = nouveau_disp_create(parent, engine, oclass, "PDISP",
- "display", &priv);
+ ret = nouveau_disp_create(parent, engine, oclass, heads,
+ "PDISP", "display", &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
@@ -62,8 +236,9 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nve0_disp_base_oclass;
nv_engine(priv)->cclass = &nv50_disp_cclass;
nv_subdev(priv)->intr = nvd0_disp_intr;
+ INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
priv->sclass = nve0_disp_sclass;
- priv->head.nr = nv_rd32(priv, 0x022448);
+ priv->head.nr = heads;
priv->dac.nr = 3;
priv->sor.nr = 4;
priv->dac.power = nv50_dac_power;
@@ -71,24 +246,21 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv->sor.power = nv50_sor_power;
priv->sor.hda_eld = nvd0_hda_eld;
priv->sor.hdmi = nvd0_hdmi_ctrl;
- priv->sor.dp_train = nvd0_sor_dp_train;
- priv->sor.dp_train_init = nv94_sor_dp_train_init;
- priv->sor.dp_train_fini = nv94_sor_dp_train_fini;
- priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl;
- priv->sor.dp_drvctl = nvd0_sor_dp_drvctl;
-
- INIT_LIST_HEAD(&priv->base.vblank.list);
- spin_lock_init(&priv->base.vblank.lock);
return 0;
}
-struct nouveau_oclass
-nve0_disp_oclass = {
- .handle = NV_ENGINE(DISP, 0x91),
- .ofuncs = &(struct nouveau_ofuncs) {
+struct nouveau_oclass *
+nve0_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x91),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nve0_disp_ctor,
.dtor = _nouveau_disp_dtor,
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
-};
+ .base.outp = nvd0_disp_outp_sclass,
+ .mthd.core = &nve0_disp_mast_mthd_chan,
+ .mthd.base = &nvd0_disp_sync_mthd_chan,
+ .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+ .mthd.prev = -0x020000,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
new file mode 100644
index 00000000000..104388081d7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <engine/software.h>
+#include <engine/disp.h>
+
+#include <core/class.h>
+
+#include "nv50.h"
+
+/*******************************************************************************
+ * Base display object
+ ******************************************************************************/
+
+static struct nouveau_oclass
+nvf0_disp_sclass[] = {
+ { NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
+ { NVF0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
+ { NVF0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
+ { NVF0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
+ { NVF0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+ {}
+};
+
+static struct nouveau_oclass
+nvf0_disp_base_oclass[] = {
+ { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
+ {}
+};
+
+/*******************************************************************************
+ * Display engine implementation
+ ******************************************************************************/
+
+static int
+nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nv50_disp_priv *priv;
+ int heads = nv_rd32(parent, 0x022448);
+ int ret;
+
+ ret = nouveau_disp_create(parent, engine, oclass, heads,
+ "PDISP", "display", &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ nv_engine(priv)->sclass = nvf0_disp_base_oclass;
+ nv_engine(priv)->cclass = &nv50_disp_cclass;
+ nv_subdev(priv)->intr = nvd0_disp_intr;
+ INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
+ priv->sclass = nvf0_disp_sclass;
+ priv->head.nr = heads;
+ priv->dac.nr = 3;
+ priv->sor.nr = 4;
+ priv->dac.power = nv50_dac_power;
+ priv->dac.sense = nv50_dac_sense;
+ priv->sor.power = nv50_sor_power;
+ priv->sor.hda_eld = nvd0_hda_eld;
+ priv->sor.hdmi = nvd0_hdmi_ctrl;
+ return 0;
+}
+
+struct nouveau_oclass *
+nvf0_disp_oclass = &(struct nv50_disp_impl) {
+ .base.base.handle = NV_ENGINE(DISP, 0x92),
+ .base.base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nvf0_disp_ctor,
+ .dtor = _nouveau_disp_dtor,
+ .init = _nouveau_disp_init,
+ .fini = _nouveau_disp_fini,
+ },
+ .base.outp = nvd0_disp_outp_sclass,
+ .mthd.core = &nve0_disp_mast_mthd_chan,
+ .mthd.base = &nvd0_disp_sync_mthd_chan,
+ .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+ .mthd.prev = -0x020000,
+}.base.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.c b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
new file mode 100644
index 00000000000..ad9ba7ccec7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2014 Red Hat Inc.
+ *
+ * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <subdev/i2c.h>
+#include <subdev/bios.h>
+#include <subdev/bios/conn.h>
+
+#include "outp.h"
+
+int
+_nvkm_output_fini(struct nouveau_object *object, bool suspend)
+{
+ struct nvkm_output *outp = (void *)object;
+ nv_ofuncs(outp->conn)->fini(nv_object(outp->conn), suspend);
+ return nouveau_object_fini(&outp->base, suspend);
+}
+
+int
+_nvkm_output_init(struct nouveau_object *object)
+{
+ struct nvkm_output *outp = (void *)object;
+ int ret = nouveau_object_init(&outp->base);
+ if (ret == 0)
+ nv_ofuncs(outp->conn)->init(nv_object(outp->conn));
+ return 0;
+}
+
+void
+_nvkm_output_dtor(struct nouveau_object *object)
+{
+ struct nvkm_output *outp = (void *)object;
+ list_del(&outp->head);
+ nouveau_object_ref(NULL, (void *)&outp->conn);
+ nouveau_object_destroy(&outp->base);
+}
+
+int
+nvkm_output_create_(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass,
+ struct dcb_output *dcbE, int index,
+ int length, void **pobject)
+{
+ struct nouveau_bios *bios = nouveau_bios(engine);
+ struct nouveau_i2c *i2c = nouveau_i2c(parent);
+ struct nouveau_disp *disp = (void *)engine;
+ struct nvbios_connE connE;
+ struct nvkm_output *outp;
+ u8 ver, hdr;
+ u32 data;
+ int ret;
+
+ ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
+ outp = *pobject;
+ if (ret)
+ return ret;
+
+ outp->info = *dcbE;
+ outp->index = index;
+
+ DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n",
+ dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ?
+ dcbE->sorconf.link : 0, dcbE->connector, dcbE->i2c_index,
+ dcbE->bus, dcbE->heads);
+
+ outp->port = i2c->find(i2c, outp->info.i2c_index);
+ outp->edid = outp->port;
+
+ data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, &connE);
+ if (!data) {
+ DBG("vbios connector data not found\n");
+ memset(&connE, 0x00, sizeof(connE));
+ connE.type = DCB_CONNECTOR_NONE;
+ }
+
+ ret = nouveau_object_ctor(parent, engine, nvkm_connector_oclass,
+ &connE, outp->info.connector,
+ (struct nouveau_object **)&outp->conn);
+ if (ret < 0) {
+ ERR("error %d creating connector, disabling\n", ret);
+ return ret;
+ }
+
+ list_add_tail(&outp->head, &disp->outp);
+ return 0;
+}
+
+int
+_nvkm_output_ctor(struct nouveau_object *parent,
+ struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *dcbE, u32 index,
+ struct nouveau_object **pobject)
+{
+ struct nvkm_output *outp;
+ int ret;
+
+ ret = nvkm_output_create(parent, engine, oclass, dcbE, index, &outp);
+ *pobject = nv_object(outp);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct nouveau_oclass *
+nvkm_output_oclass = &(struct nvkm_output_impl) {
+ .base = {
+ .handle = 0,
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = _nvkm_output_ctor,
+ .dtor = _nvkm_output_dtor,
+ .init = _nvkm_output_init,
+ .fini = _nvkm_output_fini,
+ },
+ },
+}.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.h b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
new file mode 100644
index 00000000000..bc76fbf8571
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h
@@ -0,0 +1,59 @@
+#ifndef __NVKM_DISP_OUTP_H__
+#define __NVKM_DISP_OUTP_H__
+
+#include "priv.h"
+
+struct nvkm_output {
+ struct nouveau_object base;
+ struct list_head head;
+
+ struct dcb_output info;
+ int index;
+
+ struct nouveau_i2c_port *port;
+ struct nouveau_i2c_port *edid;
+
+ struct nvkm_connector *conn;
+};
+
+#define nvkm_output_create(p,e,c,b,i,d) \
+ nvkm_output_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d)
+#define nvkm_output_destroy(d) ({ \
+ struct nvkm_output *_outp = (d); \
+ _nvkm_output_dtor(nv_object(_outp)); \
+})
+#define nvkm_output_init(d) ({ \
+ struct nvkm_output *_outp = (d); \
+ _nvkm_output_init(nv_object(_outp)); \
+})
+#define nvkm_output_fini(d,s) ({ \
+ struct nvkm_output *_outp = (d); \
+ _nvkm_output_fini(nv_object(_outp), (s)); \
+})
+
+int nvkm_output_create_(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, struct dcb_output *,
+ int, int, void **);
+
+int _nvkm_output_ctor(struct nouveau_object *, struct nouveau_object *,
+ struct nouveau_oclass *, void *, u32,
+ struct nouveau_object **);
+void _nvkm_output_dtor(struct nouveau_object *);
+int _nvkm_output_init(struct nouveau_object *);
+int _nvkm_output_fini(struct nouveau_object *, bool);
+
+struct nvkm_output_impl {
+ struct nouveau_oclass base;
+};
+
+#ifndef MSG
+#define MSG(l,f,a...) do { \
+ struct nvkm_output *_outp = (void *)outp; \
+ nv_##l(nv_object(outp)->engine, "%02x:%04x:%04x: "f, _outp->index, \
+ _outp->info.hasht, _outp->info.hashm, ##a); \
+} while(0)
+#define DBG(f,a...) MSG(debug, f, ##a)
+#define ERR(f,a...) MSG(error, f, ##a)
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c
new file mode 100644