Loading drivers/gpu/drm/nouveau/nouveau_drv.h +1 −8 Original line number Diff line number Diff line Loading @@ -1177,14 +1177,7 @@ extern int nv30_graph_init(struct drm_device *); extern void nv20_graph_set_tile_region(struct drm_device *dev, int i); /* nv40_graph.c */ extern int nv40_graph_init(struct drm_device *); extern void nv40_graph_takedown(struct drm_device *); extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); extern int nv40_graph_create_context(struct nouveau_channel *); extern void nv40_graph_destroy_context(struct nouveau_channel *); extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_unload_context(struct drm_device *); extern int nv40_graph_object_new(struct nouveau_channel *, u32, u16); extern int nv40_graph_create(struct drm_device *); extern void nv40_grctx_init(struct nouveau_grctx *); extern void nv40_graph_set_tile_region(struct drm_device *dev, int i); Loading drivers/gpu/drm/nouveau/nouveau_state.c +13 −12 Original line number Diff line number Diff line Loading @@ -299,15 +299,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fb.init_tile_region = nv30_fb_init_tile_region; engine->fb.set_tile_region = nv40_fb_set_tile_region; engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->graph.init = nv40_graph_init; engine->graph.takedown = nv40_graph_takedown; engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.channel = nv40_graph_channel; engine->graph.create_context = nv40_graph_create_context; engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.load_context = nv40_graph_load_context; engine->graph.unload_context = nv40_graph_unload_context; engine->graph.object_new = nv40_graph_object_new; engine->graph.init = nouveau_stub_init; engine->graph.takedown = nouveau_stub_takedown; engine->graph.fifo_access = nvc0_graph_fifo_access; engine->graph.channel = nvc0_graph_channel; engine->graph.set_tile_region = nv40_graph_set_tile_region; engine->fifo.channels = 32; engine->fifo.init = nv40_fifo_init; Loading Loading @@ -618,11 +613,17 @@ nouveau_card_init(struct drm_device *dev) if (ret) goto out_timer; if (dev_priv->card_type == NV_50) switch (dev_priv->card_type) { case NV_40: nv40_graph_create(dev); break; case NV_50: nv50_graph_create(dev); else if (dev_priv->card_type == NV_C0) break; case NV_C0: nvc0_graph_create(dev); break; } switch (dev_priv->chipset) { case 0x84: Loading drivers/gpu/drm/nouveau/nv40_graph.c +144 −151 Original line number Diff line number Diff line Loading @@ -30,13 +30,16 @@ #include "nouveau_grctx.h" #include "nouveau_ramht.h" static int nv40_graph_register(struct drm_device *); static void nv40_graph_isr(struct drm_device *); struct nv40_graph_engine { struct nouveau_exec_engine base; u32 grctx_size; }; struct nouveau_channel * static struct nouveau_channel * nv40_graph_channel(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *grctx; uint32_t inst; int i; Loading @@ -46,74 +49,17 @@ nv40_graph_channel(struct drm_device *dev) inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (!dev_priv->channels.ptr[i]) continue; if (chan && chan->ramin_grctx && chan->ramin_grctx->pinst == inst) return chan; grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; if (grctx && grctx->pinst == inst) return dev_priv->channels.ptr[i]; } return NULL; } int nv40_graph_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nouveau_grctx ctx = {}; unsigned long flags; int ret; ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx); if (ret) return ret; /* Initialise default context values */ ctx.dev = chan->dev; ctx.mode = NOUVEAU_GRCTX_VALS; ctx.data = chan->ramin_grctx; nv40_grctx_init(&ctx); nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst); /* init grctx pointer in ramfc, and on PFIFO if channel is * already active there */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wo32(chan->ramfc, 0x38, chan->ramin_grctx->pinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) nv_wr32(dev, 0x0032e0, chan->ramin_grctx->pinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); return 0; } void nv40_graph_destroy_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; unsigned long flags; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); pgraph->fifo_access(dev, false); /* Unload the context if it's the currently active one */ if (pgraph->channel(dev) == chan) pgraph->unload_context(dev); pgraph->fifo_access(dev, true); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); /* Free the context resources */ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } static int nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) { Loading Loading @@ -155,58 +101,88 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) return 0; } /* Restore the context for a specific channel into PGRAPH */ int nv40_graph_load_context(struct nouveau_channel *chan) static int nv40_graph_unload_context(struct drm_device *dev) { struct drm_device *dev = chan->dev; uint32_t inst; int ret; if (!chan->ramin_grctx) return -EINVAL; inst = chan->ramin_grctx->pinst >> 4; inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) return 0; inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; ret = nv40_graph_transfer_context(dev, inst, 1); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); return ret; } ret = nv40_graph_transfer_context(dev, inst, 0); static int nv40_graph_context_new(struct nouveau_channel *chan, int engine) { struct nv40_graph_engine *pgraph = nv_engine(chan->dev, engine); struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *grctx = NULL; struct nouveau_grctx ctx = {}; unsigned long flags; int ret; ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &grctx); if (ret) return ret; /* 0x40032C, no idea of it's exact function. Could simply be a * record of the currently active PGRAPH context. It's currently * unknown as to what bit 24 does. The nv ddx has it set, so we will * set it here too. */ nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) | NV40_PGRAPH_CTXCTL_CUR_LOADED); /* 0x32E0 records the instance address of the active FIFO's PGRAPH * context. If at any time this doesn't match 0x40032C, you will * receive PGRAPH_INTR_CONTEXT_SWITCH /* Initialise default context values */ ctx.dev = chan->dev; ctx.mode = NOUVEAU_GRCTX_VALS; ctx.data = grctx; nv40_grctx_init(&ctx); nv_wo32(grctx, 0, grctx->vinst); /* init grctx pointer in ramfc, and on PFIFO if channel is * already active there */ nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wo32(chan->ramfc, 0x38, grctx->vinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) nv_wr32(dev, 0x0032e0, grctx->vinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); chan->engctx[engine] = grctx; return 0; } int nv40_graph_unload_context(struct drm_device *dev) static void nv40_graph_context_del(struct nouveau_channel *chan, int engine) { uint32_t inst; int ret; struct nouveau_gpuobj *grctx = chan->engctx[engine]; struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; unsigned long flags; inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) return 0; inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv04_graph_fifo_access(dev, false); ret = nv40_graph_transfer_context(dev, inst, 1); /* Unload the context if it's the currently active one */ if (nv40_graph_channel(dev) == chan) nv40_graph_unload_context(dev); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); return ret; nv04_graph_fifo_access(dev, true); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); /* Free the context resources */ nouveau_gpuobj_ref(NULL, &grctx); chan->engctx[engine] = NULL; } int nv40_graph_object_new(struct nouveau_channel *chan, u32 handle, u16 class) nv40_graph_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; struct nouveau_gpuobj *obj = NULL; Loading Loading @@ -284,14 +260,14 @@ nv40_graph_set_tile_region(struct drm_device *dev, int i) * C51 0x4e */ int nv40_graph_init(struct drm_device *dev) nv40_graph_init(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = (struct drm_nouveau_private *)dev->dev_private; struct nv40_graph_engine *pgraph = nv_engine(dev, engine); struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; struct nouveau_grctx ctx = {}; uint32_t vramsz, *cp; int ret, i, j; int i, j; nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); Loading @@ -307,7 +283,7 @@ nv40_graph_init(struct drm_device *dev) ctx.data = cp; ctx.ctxprog_max = 256; nv40_grctx_init(&ctx); dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; pgraph->grctx_size = ctx.ctxvals_pos * 4; nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); for (i = 0; i < ctx.ctxprog_len; i++) Loading @@ -315,14 +291,9 @@ nv40_graph_init(struct drm_device *dev) kfree(cp); ret = nv40_graph_register(dev); if (ret) return ret; /* No context present currently */ nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); nouveau_irq_register(dev, 12, nv40_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); Loading Loading @@ -455,47 +426,10 @@ nv40_graph_init(struct drm_device *dev) return 0; } void nv40_graph_takedown(struct drm_device *dev) { nouveau_irq_unregister(dev, 12); } static int nv40_graph_register(struct drm_device *dev) nv40_graph_fini(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = dev->dev_private; if (dev_priv->engine.graph.registered) return 0; NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ /* curie */ if (nv44_graph_class(dev)) NVOBJ_CLASS(dev, 0x4497, GR); else NVOBJ_CLASS(dev, 0x4097, GR); /* nvsw */ NVOBJ_CLASS(dev, 0x506e, SW); NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); dev_priv->engine.graph.registered = true; nv40_graph_unload_context(dev); return 0; } Loading @@ -503,17 +437,17 @@ static int nv40_graph_isr_chid(struct drm_device *dev, u32 inst) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan; struct nouveau_gpuobj *grctx; unsigned long flags; int i; spin_lock_irqsave(&dev_priv->channels.lock, flags); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { chan = dev_priv->channels.ptr[i]; if (!chan || !chan->ramin_grctx) if (!dev_priv->channels.ptr[i]) continue; grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; if (inst == chan->ramin_grctx->pinst) if (grctx && grctx->pinst == inst) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); Loading Loading @@ -564,3 +498,62 @@ nv40_graph_isr(struct drm_device *dev) } } } static void nv40_graph_destroy(struct drm_device *dev, int engine) { struct nv40_graph_engine *pgraph = nv_engine(dev, engine); nouveau_irq_unregister(dev, 12); NVOBJ_ENGINE_DEL(dev, GR); kfree(pgraph); } int nv40_graph_create(struct drm_device *dev) { struct nv40_graph_engine *pgraph; pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); if (!pgraph) return -ENOMEM; pgraph->base.destroy = nv40_graph_destroy; pgraph->base.init = nv40_graph_init; pgraph->base.fini = nv40_graph_fini; pgraph->base.context_new = nv40_graph_context_new; pgraph->base.context_del = nv40_graph_context_del; pgraph->base.object_new = nv40_graph_object_new; NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); nouveau_irq_register(dev, 12, nv40_graph_isr); NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ /* curie */ if (nv44_graph_class(dev)) NVOBJ_CLASS(dev, 0x4497, GR); else NVOBJ_CLASS(dev, 0x4097, GR); /* nvsw */ NVOBJ_CLASS(dev, 0x506e, SW); NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); return 0; } Loading
drivers/gpu/drm/nouveau/nouveau_drv.h +1 −8 Original line number Diff line number Diff line Loading @@ -1177,14 +1177,7 @@ extern int nv30_graph_init(struct drm_device *); extern void nv20_graph_set_tile_region(struct drm_device *dev, int i); /* nv40_graph.c */ extern int nv40_graph_init(struct drm_device *); extern void nv40_graph_takedown(struct drm_device *); extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); extern int nv40_graph_create_context(struct nouveau_channel *); extern void nv40_graph_destroy_context(struct nouveau_channel *); extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_unload_context(struct drm_device *); extern int nv40_graph_object_new(struct nouveau_channel *, u32, u16); extern int nv40_graph_create(struct drm_device *); extern void nv40_grctx_init(struct nouveau_grctx *); extern void nv40_graph_set_tile_region(struct drm_device *dev, int i); Loading
drivers/gpu/drm/nouveau/nouveau_state.c +13 −12 Original line number Diff line number Diff line Loading @@ -299,15 +299,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fb.init_tile_region = nv30_fb_init_tile_region; engine->fb.set_tile_region = nv40_fb_set_tile_region; engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->graph.init = nv40_graph_init; engine->graph.takedown = nv40_graph_takedown; engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.channel = nv40_graph_channel; engine->graph.create_context = nv40_graph_create_context; engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.load_context = nv40_graph_load_context; engine->graph.unload_context = nv40_graph_unload_context; engine->graph.object_new = nv40_graph_object_new; engine->graph.init = nouveau_stub_init; engine->graph.takedown = nouveau_stub_takedown; engine->graph.fifo_access = nvc0_graph_fifo_access; engine->graph.channel = nvc0_graph_channel; engine->graph.set_tile_region = nv40_graph_set_tile_region; engine->fifo.channels = 32; engine->fifo.init = nv40_fifo_init; Loading Loading @@ -618,11 +613,17 @@ nouveau_card_init(struct drm_device *dev) if (ret) goto out_timer; if (dev_priv->card_type == NV_50) switch (dev_priv->card_type) { case NV_40: nv40_graph_create(dev); break; case NV_50: nv50_graph_create(dev); else if (dev_priv->card_type == NV_C0) break; case NV_C0: nvc0_graph_create(dev); break; } switch (dev_priv->chipset) { case 0x84: Loading
drivers/gpu/drm/nouveau/nv40_graph.c +144 −151 Original line number Diff line number Diff line Loading @@ -30,13 +30,16 @@ #include "nouveau_grctx.h" #include "nouveau_ramht.h" static int nv40_graph_register(struct drm_device *); static void nv40_graph_isr(struct drm_device *); struct nv40_graph_engine { struct nouveau_exec_engine base; u32 grctx_size; }; struct nouveau_channel * static struct nouveau_channel * nv40_graph_channel(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *grctx; uint32_t inst; int i; Loading @@ -46,74 +49,17 @@ nv40_graph_channel(struct drm_device *dev) inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (!dev_priv->channels.ptr[i]) continue; if (chan && chan->ramin_grctx && chan->ramin_grctx->pinst == inst) return chan; grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; if (grctx && grctx->pinst == inst) return dev_priv->channels.ptr[i]; } return NULL; } int nv40_graph_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nouveau_grctx ctx = {}; unsigned long flags; int ret; ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx); if (ret) return ret; /* Initialise default context values */ ctx.dev = chan->dev; ctx.mode = NOUVEAU_GRCTX_VALS; ctx.data = chan->ramin_grctx; nv40_grctx_init(&ctx); nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst); /* init grctx pointer in ramfc, and on PFIFO if channel is * already active there */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wo32(chan->ramfc, 0x38, chan->ramin_grctx->pinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) nv_wr32(dev, 0x0032e0, chan->ramin_grctx->pinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); return 0; } void nv40_graph_destroy_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; unsigned long flags; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); pgraph->fifo_access(dev, false); /* Unload the context if it's the currently active one */ if (pgraph->channel(dev) == chan) pgraph->unload_context(dev); pgraph->fifo_access(dev, true); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); /* Free the context resources */ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } static int nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) { Loading Loading @@ -155,58 +101,88 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) return 0; } /* Restore the context for a specific channel into PGRAPH */ int nv40_graph_load_context(struct nouveau_channel *chan) static int nv40_graph_unload_context(struct drm_device *dev) { struct drm_device *dev = chan->dev; uint32_t inst; int ret; if (!chan->ramin_grctx) return -EINVAL; inst = chan->ramin_grctx->pinst >> 4; inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) return 0; inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; ret = nv40_graph_transfer_context(dev, inst, 1); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); return ret; } ret = nv40_graph_transfer_context(dev, inst, 0); static int nv40_graph_context_new(struct nouveau_channel *chan, int engine) { struct nv40_graph_engine *pgraph = nv_engine(chan->dev, engine); struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *grctx = NULL; struct nouveau_grctx ctx = {}; unsigned long flags; int ret; ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &grctx); if (ret) return ret; /* 0x40032C, no idea of it's exact function. Could simply be a * record of the currently active PGRAPH context. It's currently * unknown as to what bit 24 does. The nv ddx has it set, so we will * set it here too. */ nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) | NV40_PGRAPH_CTXCTL_CUR_LOADED); /* 0x32E0 records the instance address of the active FIFO's PGRAPH * context. If at any time this doesn't match 0x40032C, you will * receive PGRAPH_INTR_CONTEXT_SWITCH /* Initialise default context values */ ctx.dev = chan->dev; ctx.mode = NOUVEAU_GRCTX_VALS; ctx.data = grctx; nv40_grctx_init(&ctx); nv_wo32(grctx, 0, grctx->vinst); /* init grctx pointer in ramfc, and on PFIFO if channel is * already active there */ nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst); spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wo32(chan->ramfc, 0x38, grctx->vinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000000); if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id) nv_wr32(dev, 0x0032e0, grctx->vinst >> 4); nv_mask(dev, 0x002500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); chan->engctx[engine] = grctx; return 0; } int nv40_graph_unload_context(struct drm_device *dev) static void nv40_graph_context_del(struct nouveau_channel *chan, int engine) { uint32_t inst; int ret; struct nouveau_gpuobj *grctx = chan->engctx[engine]; struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; unsigned long flags; inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) return 0; inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv04_graph_fifo_access(dev, false); ret = nv40_graph_transfer_context(dev, inst, 1); /* Unload the context if it's the currently active one */ if (nv40_graph_channel(dev) == chan) nv40_graph_unload_context(dev); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); return ret; nv04_graph_fifo_access(dev, true); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); /* Free the context resources */ nouveau_gpuobj_ref(NULL, &grctx); chan->engctx[engine] = NULL; } int nv40_graph_object_new(struct nouveau_channel *chan, u32 handle, u16 class) nv40_graph_object_new(struct nouveau_channel *chan, int engine, u32 handle, u16 class) { struct drm_device *dev = chan->dev; struct nouveau_gpuobj *obj = NULL; Loading Loading @@ -284,14 +260,14 @@ nv40_graph_set_tile_region(struct drm_device *dev, int i) * C51 0x4e */ int nv40_graph_init(struct drm_device *dev) nv40_graph_init(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = (struct drm_nouveau_private *)dev->dev_private; struct nv40_graph_engine *pgraph = nv_engine(dev, engine); struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; struct nouveau_grctx ctx = {}; uint32_t vramsz, *cp; int ret, i, j; int i, j; nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); Loading @@ -307,7 +283,7 @@ nv40_graph_init(struct drm_device *dev) ctx.data = cp; ctx.ctxprog_max = 256; nv40_grctx_init(&ctx); dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; pgraph->grctx_size = ctx.ctxvals_pos * 4; nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); for (i = 0; i < ctx.ctxprog_len; i++) Loading @@ -315,14 +291,9 @@ nv40_graph_init(struct drm_device *dev) kfree(cp); ret = nv40_graph_register(dev); if (ret) return ret; /* No context present currently */ nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); nouveau_irq_register(dev, 12, nv40_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); Loading Loading @@ -455,47 +426,10 @@ nv40_graph_init(struct drm_device *dev) return 0; } void nv40_graph_takedown(struct drm_device *dev) { nouveau_irq_unregister(dev, 12); } static int nv40_graph_register(struct drm_device *dev) nv40_graph_fini(struct drm_device *dev, int engine) { struct drm_nouveau_private *dev_priv = dev->dev_private; if (dev_priv->engine.graph.registered) return 0; NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ /* curie */ if (nv44_graph_class(dev)) NVOBJ_CLASS(dev, 0x4497, GR); else NVOBJ_CLASS(dev, 0x4097, GR); /* nvsw */ NVOBJ_CLASS(dev, 0x506e, SW); NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); dev_priv->engine.graph.registered = true; nv40_graph_unload_context(dev); return 0; } Loading @@ -503,17 +437,17 @@ static int nv40_graph_isr_chid(struct drm_device *dev, u32 inst) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan; struct nouveau_gpuobj *grctx; unsigned long flags; int i; spin_lock_irqsave(&dev_priv->channels.lock, flags); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { chan = dev_priv->channels.ptr[i]; if (!chan || !chan->ramin_grctx) if (!dev_priv->channels.ptr[i]) continue; grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; if (inst == chan->ramin_grctx->pinst) if (grctx && grctx->pinst == inst) break; } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); Loading Loading @@ -564,3 +498,62 @@ nv40_graph_isr(struct drm_device *dev) } } } static void nv40_graph_destroy(struct drm_device *dev, int engine) { struct nv40_graph_engine *pgraph = nv_engine(dev, engine); nouveau_irq_unregister(dev, 12); NVOBJ_ENGINE_DEL(dev, GR); kfree(pgraph); } int nv40_graph_create(struct drm_device *dev) { struct nv40_graph_engine *pgraph; pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL); if (!pgraph) return -ENOMEM; pgraph->base.destroy = nv40_graph_destroy; pgraph->base.init = nv40_graph_init; pgraph->base.fini = nv40_graph_fini; pgraph->base.context_new = nv40_graph_context_new; pgraph->base.context_del = nv40_graph_context_del; pgraph->base.object_new = nv40_graph_object_new; NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base); nouveau_irq_register(dev, 12, nv40_graph_isr); NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ NVOBJ_CLASS(dev, 0x0030, GR); /* null */ NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ /* curie */ if (nv44_graph_class(dev)) NVOBJ_CLASS(dev, 0x4497, GR); else NVOBJ_CLASS(dev, 0x4097, GR); /* nvsw */ NVOBJ_CLASS(dev, 0x506e, SW); NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); return 0; }