static int nouveau_card_init_channel(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *gpuobj; int ret; ret = nouveau_channel_alloc(dev, &dev_priv->channel, (struct drm_file *)-2, NvDmaFB, NvDmaTT); if (ret) return ret; gpuobj = NULL; ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, 0, nouveau_mem_fb_amount(dev), NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, &gpuobj); if (ret) goto out_err; ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, gpuobj, NULL); if (ret) goto out_err; gpuobj = NULL; ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, dev_priv->gart_info.aper_size, NV_DMA_ACCESS_RW, &gpuobj, NULL); if (ret) goto out_err; ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, gpuobj, NULL); if (ret) goto out_err; return 0; out_err: nouveau_gpuobj_del(dev, &gpuobj); nouveau_channel_free(dev_priv->channel); dev_priv->channel = NULL; return ret; }
static int nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_bo *pb = chan->pushbuf_bo; struct nouveau_gpuobj *pushbuf = NULL; uint32_t start = pb->bo.mem.mm_node->start << PAGE_SHIFT; int ret; if (pb->bo.mem.mem_type == TTM_PL_TT) { ret = nouveau_gpuobj_gart_dma_new(chan, 0, dev_priv->gart_info.aper_size, NV_DMA_ACCESS_RO, &pushbuf, NULL); chan->pushbuf_base = start; } else if (dev_priv->card_type != NV_04) { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, dev_priv->fb_available_size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM, &pushbuf); chan->pushbuf_base = start; } else { /* NV04 cmdbuf hack, from original ddx.. not sure of it's * exact reason for existing :) PCI access to cmdbuf in * VRAM. */ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, drm_get_resource_start(dev, 1), dev_priv->fb_available_size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI, &pushbuf); chan->pushbuf_base = start; } ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf); if (ret) { NV_ERROR(dev, "Error referencing pushbuf ctxdma: %d\n", ret); if (pushbuf != dev_priv->gart_info.sg_ctxdma) nouveau_gpuobj_del(dev, &pushbuf); return ret; } return 0; }
int nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, int size, uint32_t *b_offset) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *nobj = NULL; struct mem_block *mem; uint32_t offset; int target, ret; if (!chan->notifier_heap) { NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n", chan->id); return -EINVAL; } mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0, (struct drm_file *)-2, 0); if (!mem) { NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); return -ENOMEM; } offset = chan->notifier_bo->bo.mem.mm_node->start << PAGE_SHIFT; if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { target = NV_DMA_TARGET_VIDMEM; } else if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_TT) { if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA && dev_priv->card_type < NV_50) { ret = nouveau_sgdma_get_page(dev, offset, &offset); if (ret) return ret; target = NV_DMA_TARGET_PCI; } else { target = NV_DMA_TARGET_AGP; if (dev_priv->card_type >= NV_50) offset += dev_priv->vm_gart_base; } } else { NV_ERROR(dev, "Bad DMA target, mem_type %d!\n", chan->notifier_bo->bo.mem.mem_type); return -EINVAL; } offset += mem->start; ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, mem->size, NV_DMA_ACCESS_RW, target, &nobj); if (ret) { nouveau_mem_free_block(mem); NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); return ret; } nobj->dtor = nouveau_notifier_gpuobj_dtor; nobj->priv = mem; ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); if (ret) { nouveau_gpuobj_del(dev, &nobj); nouveau_mem_free_block(mem); NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); return ret; } *b_offset = mem->start; return 0; }
int nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; struct nouveau_gpuobj *gpuobj; int ret; NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) return 0; /* Determine exact chipset we're running on */ if (dev_priv->card_type < NV_10) dev_priv->chipset = dev_priv->card_type; else dev_priv->chipset = (nv_rd32(dev, NV03_PMC_BOOT_0) & 0x0ff00000) >> 20; /* Initialise internal driver API hooks */ ret = nouveau_init_engine_ptrs(dev); if (ret) return ret; engine = &dev_priv->engine; dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; /* Parse BIOS tables / Run init tables if card not POSTed */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = nouveau_bios_init(dev); if (ret) return ret; } ret = nouveau_gpuobj_early_init(dev); if (ret) return ret; /* Initialise instance memory, must happen before mem_init so we * know exactly how much VRAM we're able to use for "normal" * purposes. */ ret = engine->instmem.init(dev); if (ret) return ret; /* Setup the memory manager */ ret = nouveau_mem_init(dev); if (ret) return ret; ret = nouveau_gpuobj_init(dev); if (ret) return ret; /* PMC */ ret = engine->mc.init(dev); if (ret) return ret; /* PTIMER */ ret = engine->timer.init(dev); if (ret) return ret; /* PFB */ ret = engine->fb.init(dev); if (ret) return ret; /* PGRAPH */ ret = engine->graph.init(dev); if (ret) return ret; /* PFIFO */ ret = engine->fifo.init(dev); if (ret) return ret; /* this call irq_preinstall, register irq handler and * call irq_postinstall */ ret = drm_irq_install(dev); if (ret) return ret; ret = drm_vblank_init(dev, 0); if (ret) return ret; /* what about PVIDEO/PCRTC/PRAMDAC etc? */ ret = nouveau_channel_alloc(dev, &dev_priv->channel, (struct drm_file *)-2, NvDmaFB, NvDmaTT); if (ret) return ret; gpuobj = NULL; ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, 0, nouveau_mem_fb_amount(dev), NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, &gpuobj); if (ret) return ret; ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, gpuobj, NULL); if (ret) { nouveau_gpuobj_del(dev, &gpuobj); return ret; } gpuobj = NULL; ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, dev_priv->gart_info.aper_size, NV_DMA_ACCESS_RW, &gpuobj, NULL); if (ret) return ret; ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, gpuobj, NULL); if (ret) { nouveau_gpuobj_del(dev, &gpuobj); return ret; } if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (dev_priv->card_type >= NV_50) { ret = nv50_display_create(dev); if (ret) return ret; } else { ret = nv04_display_create(dev); if (ret) return ret; } } ret = nouveau_backlight_init(dev); if (ret) NV_ERROR(dev, "Error %d registering backlight\n", ret); dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_helper_initial_config(dev); return 0; }