Loading drivers/gpu/drm/nouveau/nouveau_drv.h +1 −7 Original line number Diff line number Diff line Loading @@ -1194,15 +1194,9 @@ extern int nv50_grctx_init(struct nouveau_grctx *); extern struct nouveau_enum nv50_data_error_names[]; /* nvc0_graph.c */ extern int nvc0_graph_init(struct drm_device *); extern void nvc0_graph_takedown(struct drm_device *); extern int nvc0_graph_create(struct drm_device *); extern void nvc0_graph_fifo_access(struct drm_device *, bool); extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); extern int nvc0_graph_create_context(struct nouveau_channel *); extern void nvc0_graph_destroy_context(struct nouveau_channel *); extern int nvc0_graph_load_context(struct nouveau_channel *); extern int nvc0_graph_unload_context(struct drm_device *); extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16); /* nv84_crypt.c */ extern int nv84_crypt_create(struct drm_device *); Loading drivers/gpu/drm/nouveau/nouveau_state.c +3 −7 Original line number Diff line number Diff line Loading @@ -440,15 +440,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nvc0_fb_init; engine->fb.takedown = nvc0_fb_takedown; engine->graph.init = nvc0_graph_init; engine->graph.takedown = nvc0_graph_takedown; engine->graph.fifo_access = nvc0_graph_fifo_access; engine->graph.channel = nvc0_graph_channel; engine->graph.create_context = nvc0_graph_create_context; engine->graph.destroy_context = nvc0_graph_destroy_context; engine->graph.load_context = nvc0_graph_load_context; engine->graph.unload_context = nvc0_graph_unload_context; engine->graph.object_new = nvc0_graph_object_new; engine->fifo.channels = 128; engine->fifo.init = nvc0_fifo_init; engine->fifo.takedown = nvc0_fifo_takedown; Loading Loading @@ -627,6 +620,9 @@ nouveau_card_init(struct drm_device *dev) if (dev_priv->card_type == NV_50) nv50_graph_create(dev); else if (dev_priv->card_type == NV_C0) nvc0_graph_create(dev); switch (dev_priv->chipset) { case 0x84: Loading drivers/gpu/drm/nouveau/nvc0_graph.c +192 −214 Original line number Diff line number Diff line Loading @@ -30,10 +30,6 @@ #include "nouveau_mm.h" #include "nvc0_graph.h" static void nvc0_graph_isr(struct drm_device *); static void nvc0_runk140_isr(struct drm_device *); static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan); void nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) { Loading @@ -45,12 +41,40 @@ nvc0_graph_channel(struct drm_device *dev) return NULL; } static int nvc0_graph_load_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); return 0; } static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) { nv_wr32(dev, 0x409840, 0x00000003); nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); nv_wr32(dev, 0x409504, 0x00000009); if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); return -EBUSY; } return 0; } static int nvc0_graph_construct_context(struct nouveau_channel *chan) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_chan *grch = chan->pgraph_ctx; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; int ret, i; u32 *ctx; Loading Loading @@ -89,9 +113,8 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) static int nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_chan *grch = chan->pgraph_ctx; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; int i = 0, gpc, tp, ret; u32 magic; Loading Loading @@ -158,29 +181,27 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) return 0; } int nvc0_graph_create_context(struct nouveau_channel *chan) static int nvc0_graph_context_new(struct nouveau_channel *chan, int engine) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv = pgraph->priv; struct nvc0_graph_priv *priv = nv_engine(dev, engine); struct nvc0_graph_chan *grch; struct drm_device *dev = chan->dev; struct nouveau_gpuobj *grctx; int ret, i; chan->pgraph_ctx = kzalloc(sizeof(*grch), GFP_KERNEL); if (!chan->pgraph_ctx) grch = kzalloc(sizeof(*grch), GFP_KERNEL); if (!grch) return -ENOMEM; grch = chan->pgraph_ctx; chan->engctx[NVOBJ_ENGINE_GR] = grch; ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, &grch->grctx); if (ret) goto error; chan->ramin_grctx = grch->grctx; grctx = grch->grctx; ret = nvc0_graph_create_context_mmio_list(chan); Loading Loading @@ -213,97 +234,42 @@ nvc0_graph_create_context(struct nouveau_channel *chan) return 0; error: pgraph->destroy_context(chan); priv->base.context_del(chan, engine); return ret; } void nvc0_graph_destroy_context(struct nouveau_channel *chan) static void nvc0_graph_context_del(struct nouveau_channel *chan, int engine) { struct nvc0_graph_chan *grch; grch = chan->pgraph_ctx; chan->pgraph_ctx = NULL; if (!grch) return; struct nvc0_graph_chan *grch = chan->engctx[engine]; nouveau_gpuobj_ref(NULL, &grch->mmio); nouveau_gpuobj_ref(NULL, &grch->unk418810); nouveau_gpuobj_ref(NULL, &grch->unk40800c); nouveau_gpuobj_ref(NULL, &grch->unk408004); nouveau_gpuobj_ref(NULL, &grch->grctx); chan->ramin_grctx = NULL; } int nvc0_graph_load_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); return 0; chan->engctx[engine] = NULL; } static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) nvc0_graph_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { nv_wr32(dev, 0x409840, 0x00000003); nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); nv_wr32(dev, 0x409504, 0x00000009); if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); return -EBUSY; } return 0; } int nvc0_graph_unload_context(struct drm_device *dev) static int nvc0_graph_fini(struct drm_device *dev, int engine) { u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; return nvc0_graph_unload_context_to(dev, inst); u32 inst = nv_rd32(dev, 0x409b00); if (inst & 0x80000000) { inst &= 0x0fffffff; nvc0_graph_unload_context_to(dev, (u64)inst << 12); } int nvc0_graph_object_new(struct nouveau_channel *chan, u32 handle, u16 class) { return 0; } static void nvc0_graph_destroy(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv; priv = pgraph->priv; if (!priv) return; nouveau_irq_unregister(dev, 12); nouveau_irq_unregister(dev, 25); nouveau_gpuobj_ref(NULL, &priv->unk4188b8); nouveau_gpuobj_ref(NULL, &priv->unk4188b4); if (priv->grctx_vals) kfree(priv->grctx_vals); kfree(priv); } void nvc0_graph_takedown(struct drm_device *dev) { nvc0_graph_destroy(dev); } static int nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) Loading @@ -312,119 +278,10 @@ nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, return 0; } static int nvc0_graph_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv; int ret, gpc, i; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; pgraph->priv = priv; ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); if (ret) goto error; ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); if (ret) goto error; for (i = 0; i < 0x1000; i += 4) { nv_wo32(priv->unk4188b4, i, 0x00000010); nv_wo32(priv->unk4188b8, i, 0x00000010); } priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); priv->tp_total += priv->tp_nr[gpc]; } /*XXX: these need figuring out... */ switch (dev_priv->chipset) { case 0xc0: if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ priv->magic_not_rop_nr = 0x07; /* filled values up to tp_total, the rest 0 */ priv->magicgpc980[0] = 0x22111000; priv->magicgpc980[1] = 0x00000233; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x000ba2e9; } else if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ priv->magic_not_rop_nr = 0x05; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x00233222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00092493; } else if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ priv->magic_not_rop_nr = 0x06; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x03332222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00088889; } break; case 0xc3: /* 450, 4/0/0/0, 2 */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; break; case 0xc4: /* 460, 3/4/0/0, 4 */ priv->magic_not_rop_nr = 0x01; priv->magicgpc980[0] = 0x02321100; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00124925; break; } if (!priv->magic_not_rop_nr) { NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], priv->tp_nr[3], priv->rop_nr); /* use 0xc3's values... */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; } nouveau_irq_register(dev, 12, nvc0_graph_isr); nouveau_irq_register(dev, 25, nvc0_runk140_isr); NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ return 0; error: nvc0_graph_destroy(dev); return ret; } static void nvc0_graph_init_obj418880(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv = pgraph->priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int i; nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); Loading Loading @@ -455,8 +312,7 @@ nvc0_graph_init_regs(struct drm_device *dev) static void nvc0_graph_init_gpc_0(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int gpc; /* Loading Loading @@ -517,8 +373,7 @@ nvc0_graph_init_units(struct drm_device *dev) static void nvc0_graph_init_gpc_1(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int gpc, tp; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { Loading @@ -543,8 +398,7 @@ nvc0_graph_init_gpc_1(struct drm_device *dev) static void nvc0_graph_init_rop(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int rop; for (rop = 0; rop < priv->rop_nr; rop++) { Loading Loading @@ -596,8 +450,7 @@ nvc0_fuc_load_fw(struct drm_device *dev, u32 fuc_base, static int nvc0_graph_init_ctxctl(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 r000260; int ret; Loading Loading @@ -652,11 +505,10 @@ nvc0_graph_init_ctxctl(struct drm_device *dev) return 0; } int nvc0_graph_init(struct drm_device *dev) static int nvc0_graph_init(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; int ret; dev_priv->engine.graph.accel_blocked = true; Loading @@ -676,12 +528,6 @@ nvc0_graph_init(struct drm_device *dev) nv_mask(dev, 0x000200, 0x18001000, 0x00000000); nv_mask(dev, 0x000200, 0x18001000, 0x18001000); if (!pgraph->priv) { ret = nvc0_graph_create(dev); if (ret) return ret; } nvc0_graph_init_obj418880(dev); nvc0_graph_init_regs(dev); /*nvc0_graph_init_unitplemented_magics(dev);*/ Loading Loading @@ -814,3 +660,135 @@ nvc0_runk140_isr(struct drm_device *dev) units &= ~(1 << unit); } } static void nvc0_graph_destroy(struct drm_device *dev, int engine) { struct nvc0_graph_priv *priv = nv_engine(dev, engine); nouveau_irq_unregister(dev, 12); nouveau_irq_unregister(dev, 25); nouveau_gpuobj_ref(NULL, &priv->unk4188b8); nouveau_gpuobj_ref(NULL, &priv->unk4188b4); if (priv->grctx_vals) kfree(priv->grctx_vals); NVOBJ_ENGINE_DEL(dev, GR); kfree(priv); } int nvc0_graph_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv; int ret, gpc, i; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->base.destroy = nvc0_graph_destroy; priv->base.init = nvc0_graph_init; priv->base.fini = nvc0_graph_fini; priv->base.context_new = nvc0_graph_context_new; priv->base.context_del = nvc0_graph_context_del; priv->base.object_new = nvc0_graph_object_new; NVOBJ_ENGINE_ADD(dev, GR, &priv->base); nouveau_irq_register(dev, 12, nvc0_graph_isr); nouveau_irq_register(dev, 25, nvc0_runk140_isr); ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); if (ret) goto error; ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); if (ret) goto error; for (i = 0; i < 0x1000; i += 4) { nv_wo32(priv->unk4188b4, i, 0x00000010); nv_wo32(priv->unk4188b8, i, 0x00000010); } priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); priv->tp_total += priv->tp_nr[gpc]; } /*XXX: these need figuring out... */ switch (dev_priv->chipset) { case 0xc0: if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ priv->magic_not_rop_nr = 0x07; /* filled values up to tp_total, the rest 0 */ priv->magicgpc980[0] = 0x22111000; priv->magicgpc980[1] = 0x00000233; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x000ba2e9; } else if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ priv->magic_not_rop_nr = 0x05; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x00233222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00092493; } else if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ priv->magic_not_rop_nr = 0x06; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x03332222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00088889; } break; case 0xc3: /* 450, 4/0/0/0, 2 */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; break; case 0xc4: /* 460, 3/4/0/0, 4 */ priv->magic_not_rop_nr = 0x01; priv->magicgpc980[0] = 0x02321100; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00124925; break; } if (!priv->magic_not_rop_nr) { NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], priv->tp_nr[3], priv->rop_nr); /* use 0xc3's values... */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; } NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ return 0; error: nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); return ret; } drivers/gpu/drm/nouveau/nvc0_graph.h +2 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ #define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) struct nvc0_graph_priv { struct nouveau_exec_engine base; u8 gpc_nr; u8 rop_nr; u8 tp_nr[GPC_MAX]; Loading drivers/gpu/drm/nouveau/nvc0_grctx.c +2 −2 Original line number Diff line number Diff line Loading @@ -1797,8 +1797,8 @@ int nvc0_grctx_generate(struct nouveau_channel *chan) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_chan *grch = chan->pgraph_ctx; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; int i, gpc, tp, id; u32 r000260, tmp; Loading Loading
drivers/gpu/drm/nouveau/nouveau_drv.h +1 −7 Original line number Diff line number Diff line Loading @@ -1194,15 +1194,9 @@ extern int nv50_grctx_init(struct nouveau_grctx *); extern struct nouveau_enum nv50_data_error_names[]; /* nvc0_graph.c */ extern int nvc0_graph_init(struct drm_device *); extern void nvc0_graph_takedown(struct drm_device *); extern int nvc0_graph_create(struct drm_device *); extern void nvc0_graph_fifo_access(struct drm_device *, bool); extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); extern int nvc0_graph_create_context(struct nouveau_channel *); extern void nvc0_graph_destroy_context(struct nouveau_channel *); extern int nvc0_graph_load_context(struct nouveau_channel *); extern int nvc0_graph_unload_context(struct drm_device *); extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16); /* nv84_crypt.c */ extern int nv84_crypt_create(struct drm_device *); Loading
drivers/gpu/drm/nouveau/nouveau_state.c +3 −7 Original line number Diff line number Diff line Loading @@ -440,15 +440,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nvc0_fb_init; engine->fb.takedown = nvc0_fb_takedown; engine->graph.init = nvc0_graph_init; engine->graph.takedown = nvc0_graph_takedown; engine->graph.fifo_access = nvc0_graph_fifo_access; engine->graph.channel = nvc0_graph_channel; engine->graph.create_context = nvc0_graph_create_context; engine->graph.destroy_context = nvc0_graph_destroy_context; engine->graph.load_context = nvc0_graph_load_context; engine->graph.unload_context = nvc0_graph_unload_context; engine->graph.object_new = nvc0_graph_object_new; engine->fifo.channels = 128; engine->fifo.init = nvc0_fifo_init; engine->fifo.takedown = nvc0_fifo_takedown; Loading Loading @@ -627,6 +620,9 @@ nouveau_card_init(struct drm_device *dev) if (dev_priv->card_type == NV_50) nv50_graph_create(dev); else if (dev_priv->card_type == NV_C0) nvc0_graph_create(dev); switch (dev_priv->chipset) { case 0x84: Loading
drivers/gpu/drm/nouveau/nvc0_graph.c +192 −214 Original line number Diff line number Diff line Loading @@ -30,10 +30,6 @@ #include "nouveau_mm.h" #include "nvc0_graph.h" static void nvc0_graph_isr(struct drm_device *); static void nvc0_runk140_isr(struct drm_device *); static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan); void nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) { Loading @@ -45,12 +41,40 @@ nvc0_graph_channel(struct drm_device *dev) return NULL; } static int nvc0_graph_load_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); return 0; } static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) { nv_wr32(dev, 0x409840, 0x00000003); nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); nv_wr32(dev, 0x409504, 0x00000009); if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); return -EBUSY; } return 0; } static int nvc0_graph_construct_context(struct nouveau_channel *chan) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_chan *grch = chan->pgraph_ctx; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; int ret, i; u32 *ctx; Loading Loading @@ -89,9 +113,8 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) static int nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_chan *grch = chan->pgraph_ctx; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; int i = 0, gpc, tp, ret; u32 magic; Loading Loading @@ -158,29 +181,27 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) return 0; } int nvc0_graph_create_context(struct nouveau_channel *chan) static int nvc0_graph_context_new(struct nouveau_channel *chan, int engine) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv = pgraph->priv; struct nvc0_graph_priv *priv = nv_engine(dev, engine); struct nvc0_graph_chan *grch; struct drm_device *dev = chan->dev; struct nouveau_gpuobj *grctx; int ret, i; chan->pgraph_ctx = kzalloc(sizeof(*grch), GFP_KERNEL); if (!chan->pgraph_ctx) grch = kzalloc(sizeof(*grch), GFP_KERNEL); if (!grch) return -ENOMEM; grch = chan->pgraph_ctx; chan->engctx[NVOBJ_ENGINE_GR] = grch; ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, &grch->grctx); if (ret) goto error; chan->ramin_grctx = grch->grctx; grctx = grch->grctx; ret = nvc0_graph_create_context_mmio_list(chan); Loading Loading @@ -213,97 +234,42 @@ nvc0_graph_create_context(struct nouveau_channel *chan) return 0; error: pgraph->destroy_context(chan); priv->base.context_del(chan, engine); return ret; } void nvc0_graph_destroy_context(struct nouveau_channel *chan) static void nvc0_graph_context_del(struct nouveau_channel *chan, int engine) { struct nvc0_graph_chan *grch; grch = chan->pgraph_ctx; chan->pgraph_ctx = NULL; if (!grch) return; struct nvc0_graph_chan *grch = chan->engctx[engine]; nouveau_gpuobj_ref(NULL, &grch->mmio); nouveau_gpuobj_ref(NULL, &grch->unk418810); nouveau_gpuobj_ref(NULL, &grch->unk40800c); nouveau_gpuobj_ref(NULL, &grch->unk408004); nouveau_gpuobj_ref(NULL, &grch->grctx); chan->ramin_grctx = NULL; } int nvc0_graph_load_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; nv_wr32(dev, 0x409840, 0x00000030); nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); nv_wr32(dev, 0x409504, 0x00000003); if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); return 0; chan->engctx[engine] = NULL; } static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) nvc0_graph_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { nv_wr32(dev, 0x409840, 0x00000003); nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); nv_wr32(dev, 0x409504, 0x00000009); if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); return -EBUSY; } return 0; } int nvc0_graph_unload_context(struct drm_device *dev) static int nvc0_graph_fini(struct drm_device *dev, int engine) { u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; return nvc0_graph_unload_context_to(dev, inst); u32 inst = nv_rd32(dev, 0x409b00); if (inst & 0x80000000) { inst &= 0x0fffffff; nvc0_graph_unload_context_to(dev, (u64)inst << 12); } int nvc0_graph_object_new(struct nouveau_channel *chan, u32 handle, u16 class) { return 0; } static void nvc0_graph_destroy(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv; priv = pgraph->priv; if (!priv) return; nouveau_irq_unregister(dev, 12); nouveau_irq_unregister(dev, 25); nouveau_gpuobj_ref(NULL, &priv->unk4188b8); nouveau_gpuobj_ref(NULL, &priv->unk4188b4); if (priv->grctx_vals) kfree(priv->grctx_vals); kfree(priv); } void nvc0_graph_takedown(struct drm_device *dev) { nvc0_graph_destroy(dev); } static int nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) Loading @@ -312,119 +278,10 @@ nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, return 0; } static int nvc0_graph_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv; int ret, gpc, i; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; pgraph->priv = priv; ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); if (ret) goto error; ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); if (ret) goto error; for (i = 0; i < 0x1000; i += 4) { nv_wo32(priv->unk4188b4, i, 0x00000010); nv_wo32(priv->unk4188b8, i, 0x00000010); } priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); priv->tp_total += priv->tp_nr[gpc]; } /*XXX: these need figuring out... */ switch (dev_priv->chipset) { case 0xc0: if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ priv->magic_not_rop_nr = 0x07; /* filled values up to tp_total, the rest 0 */ priv->magicgpc980[0] = 0x22111000; priv->magicgpc980[1] = 0x00000233; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x000ba2e9; } else if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ priv->magic_not_rop_nr = 0x05; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x00233222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00092493; } else if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ priv->magic_not_rop_nr = 0x06; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x03332222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00088889; } break; case 0xc3: /* 450, 4/0/0/0, 2 */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; break; case 0xc4: /* 460, 3/4/0/0, 4 */ priv->magic_not_rop_nr = 0x01; priv->magicgpc980[0] = 0x02321100; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00124925; break; } if (!priv->magic_not_rop_nr) { NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], priv->tp_nr[3], priv->rop_nr); /* use 0xc3's values... */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; } nouveau_irq_register(dev, 12, nvc0_graph_isr); nouveau_irq_register(dev, 25, nvc0_runk140_isr); NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ return 0; error: nvc0_graph_destroy(dev); return ret; } static void nvc0_graph_init_obj418880(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nvc0_graph_priv *priv = pgraph->priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int i; nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); Loading Loading @@ -455,8 +312,7 @@ nvc0_graph_init_regs(struct drm_device *dev) static void nvc0_graph_init_gpc_0(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int gpc; /* Loading Loading @@ -517,8 +373,7 @@ nvc0_graph_init_units(struct drm_device *dev) static void nvc0_graph_init_gpc_1(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int gpc, tp; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { Loading @@ -543,8 +398,7 @@ nvc0_graph_init_gpc_1(struct drm_device *dev) static void nvc0_graph_init_rop(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); int rop; for (rop = 0; rop < priv->rop_nr; rop++) { Loading Loading @@ -596,8 +450,7 @@ nvc0_fuc_load_fw(struct drm_device *dev, u32 fuc_base, static int nvc0_graph_init_ctxctl(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); u32 r000260; int ret; Loading Loading @@ -652,11 +505,10 @@ nvc0_graph_init_ctxctl(struct drm_device *dev) return 0; } int nvc0_graph_init(struct drm_device *dev) static int nvc0_graph_init(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; int ret; dev_priv->engine.graph.accel_blocked = true; Loading @@ -676,12 +528,6 @@ nvc0_graph_init(struct drm_device *dev) nv_mask(dev, 0x000200, 0x18001000, 0x00000000); nv_mask(dev, 0x000200, 0x18001000, 0x18001000); if (!pgraph->priv) { ret = nvc0_graph_create(dev); if (ret) return ret; } nvc0_graph_init_obj418880(dev); nvc0_graph_init_regs(dev); /*nvc0_graph_init_unitplemented_magics(dev);*/ Loading Loading @@ -814,3 +660,135 @@ nvc0_runk140_isr(struct drm_device *dev) units &= ~(1 << unit); } } static void nvc0_graph_destroy(struct drm_device *dev, int engine) { struct nvc0_graph_priv *priv = nv_engine(dev, engine); nouveau_irq_unregister(dev, 12); nouveau_irq_unregister(dev, 25); nouveau_gpuobj_ref(NULL, &priv->unk4188b8); nouveau_gpuobj_ref(NULL, &priv->unk4188b4); if (priv->grctx_vals) kfree(priv->grctx_vals); NVOBJ_ENGINE_DEL(dev, GR); kfree(priv); } int nvc0_graph_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvc0_graph_priv *priv; int ret, gpc, i; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->base.destroy = nvc0_graph_destroy; priv->base.init = nvc0_graph_init; priv->base.fini = nvc0_graph_fini; priv->base.context_new = nvc0_graph_context_new; priv->base.context_del = nvc0_graph_context_del; priv->base.object_new = nvc0_graph_object_new; NVOBJ_ENGINE_ADD(dev, GR, &priv->base); nouveau_irq_register(dev, 12, nvc0_graph_isr); nouveau_irq_register(dev, 25, nvc0_runk140_isr); ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); if (ret) goto error; ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); if (ret) goto error; for (i = 0; i < 0x1000; i += 4) { nv_wo32(priv->unk4188b4, i, 0x00000010); nv_wo32(priv->unk4188b8, i, 0x00000010); } priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; for (gpc = 0; gpc < priv->gpc_nr; gpc++) { priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); priv->tp_total += priv->tp_nr[gpc]; } /*XXX: these need figuring out... */ switch (dev_priv->chipset) { case 0xc0: if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ priv->magic_not_rop_nr = 0x07; /* filled values up to tp_total, the rest 0 */ priv->magicgpc980[0] = 0x22111000; priv->magicgpc980[1] = 0x00000233; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x000ba2e9; } else if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ priv->magic_not_rop_nr = 0x05; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x00233222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00092493; } else if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ priv->magic_not_rop_nr = 0x06; priv->magicgpc980[0] = 0x11110000; priv->magicgpc980[1] = 0x03332222; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00088889; } break; case 0xc3: /* 450, 4/0/0/0, 2 */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; break; case 0xc4: /* 460, 3/4/0/0, 4 */ priv->magic_not_rop_nr = 0x01; priv->magicgpc980[0] = 0x02321100; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00124925; break; } if (!priv->magic_not_rop_nr) { NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], priv->tp_nr[3], priv->rop_nr); /* use 0xc3's values... */ priv->magic_not_rop_nr = 0x03; priv->magicgpc980[0] = 0x00003210; priv->magicgpc980[1] = 0x00000000; priv->magicgpc980[2] = 0x00000000; priv->magicgpc980[3] = 0x00000000; priv->magicgpc918 = 0x00200000; } NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ return 0; error: nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); return ret; }
drivers/gpu/drm/nouveau/nvc0_graph.h +2 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ #define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) struct nvc0_graph_priv { struct nouveau_exec_engine base; u8 gpc_nr; u8 rop_nr; u8 tp_nr[GPC_MAX]; Loading
drivers/gpu/drm/nouveau/nvc0_grctx.c +2 −2 Original line number Diff line number Diff line Loading @@ -1797,8 +1797,8 @@ int nvc0_grctx_generate(struct nouveau_channel *chan) { struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; struct nvc0_graph_chan *grch = chan->pgraph_ctx; struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; struct drm_device *dev = chan->dev; int i, gpc, tp, id; u32 r000260, tmp; Loading