Example #1
0
static void nouveau_card_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine = &dev_priv->engine;
	int e;

	if (dev->mode_config.num_crtc) {
		nouveau_fbcon_fini(dev);
		nouveau_display_fini(dev);
	}

	if (dev_priv->channel) {
		nouveau_channel_put_unlocked(&dev_priv->channel);
		nouveau_fence_fini(dev);
	}

	nouveau_backlight_exit(dev);
	nouveau_display_destroy(dev);

	if (!dev_priv->noaccel) {
		engine->fifo.takedown(dev);
		for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
			if (dev_priv->eng[e]) {
				dev_priv->eng[e]->fini(dev, e, false);
				dev_priv->eng[e]->destroy(dev,e );
			}
		}
	}
	engine->fb.takedown(dev);
	engine->timer.takedown(dev);
	nouveau_gpio_destroy(dev);
	engine->mc.takedown(dev);
	engine->display.late_takedown(dev);

	if (dev_priv->vga_ram) {
		nouveau_bo_unpin(dev_priv->vga_ram);
		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
	}

	mutex_lock(&dev->struct_mutex);
	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
	mutex_unlock(&dev->struct_mutex);
	nouveau_mem_gart_fini(dev);
	nouveau_mem_vram_fini(dev);

	engine->instmem.takedown(dev);
	nouveau_gpuobj_takedown(dev);
	engine->vram.takedown(dev);

	nouveau_irq_fini(dev);

	nouveau_pm_fini(dev);
	nouveau_bios_takedown(dev);

	vga_client_register(dev->pdev, NULL, NULL, NULL);
}
Example #2
0
static void nouveau_card_takedown(struct drm_device *dev)
{
    struct drm_nouveau_private *dev_priv = dev->dev_private;
    struct nouveau_engine *engine = &dev_priv->engine;

    if (!engine->graph.accel_blocked) {
        nouveau_fence_fini(dev);
        nouveau_channel_put_unlocked(&dev_priv->channel);
    }

    if (!nouveau_noaccel) {
        engine->fifo.takedown(dev);
        engine->crypt.takedown(dev);
        engine->graph.takedown(dev);
    }
    engine->fb.takedown(dev);
    engine->timer.takedown(dev);
    engine->gpio.takedown(dev);
    engine->mc.takedown(dev);
    engine->display.late_takedown(dev);

    if (dev_priv->vga_ram) {
        nouveau_bo_unpin(dev_priv->vga_ram);
        nouveau_bo_ref(NULL, &dev_priv->vga_ram);
    }

    mutex_lock(&dev->struct_mutex);
    ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
    ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
    mutex_unlock(&dev->struct_mutex);
    nouveau_mem_gart_fini(dev);

    engine->instmem.takedown(dev);
    nouveau_gpuobj_takedown(dev);
    nouveau_mem_vram_fini(dev);

    nouveau_irq_fini(dev);
    drm_vblank_cleanup(dev);

    nouveau_pm_fini(dev);
    nouveau_bios_takedown(dev);

    vga_client_register(dev->pdev, NULL, NULL, NULL);
}
Example #3
0
int
nouveau_card_init(struct drm_device *dev)
{
    struct drm_nouveau_private *dev_priv = dev->dev_private;
    struct nouveau_engine *engine;
    int ret;

    vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
    vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
                                   nouveau_switcheroo_reprobe,
                                   nouveau_switcheroo_can_switch);

    /* Initialise internal driver API hooks */
    ret = nouveau_init_engine_ptrs(dev);
    if (ret)
        goto out;
    engine = &dev_priv->engine;
    spin_lock_init(&dev_priv->channels.lock);
    spin_lock_init(&dev_priv->tile.lock);
    spin_lock_init(&dev_priv->context_switch_lock);
    spin_lock_init(&dev_priv->vm_lock);

    /* Make the CRTCs and I2C buses accessible */
    ret = engine->display.early_init(dev);
    if (ret)
        goto out;

    /* Parse BIOS tables / Run init tables if card not POSTed */
    ret = nouveau_bios_init(dev);
    if (ret)
        goto out_display_early;

    nouveau_pm_init(dev);

    ret = nouveau_mem_vram_init(dev);
    if (ret)
        goto out_bios;

    ret = nouveau_gpuobj_init(dev);
    if (ret)
        goto out_vram;

    ret = engine->instmem.init(dev);
    if (ret)
        goto out_gpuobj;

    ret = nouveau_mem_gart_init(dev);
    if (ret)
        goto out_instmem;

    /* PMC */
    ret = engine->mc.init(dev);
    if (ret)
        goto out_gart;

    /* PGPIO */
    ret = engine->gpio.init(dev);
    if (ret)
        goto out_mc;

    /* PTIMER */
    ret = engine->timer.init(dev);
    if (ret)
        goto out_gpio;

    /* PFB */
    ret = engine->fb.init(dev);
    if (ret)
        goto out_timer;

    if (nouveau_noaccel)
        engine->graph.accel_blocked = true;
    else {
        /* PGRAPH */
        ret = engine->graph.init(dev);
        if (ret)
            goto out_fb;

        /* PCRYPT */
        ret = engine->crypt.init(dev);
        if (ret)
            goto out_graph;

        /* PFIFO */
        ret = engine->fifo.init(dev);
        if (ret)
            goto out_crypt;
    }

    ret = engine->display.create(dev);
    if (ret)
        goto out_fifo;

    ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
    if (ret)
        goto out_vblank;

    ret = nouveau_irq_init(dev);
    if (ret)
        goto out_vblank;

    /* what about PVIDEO/PCRTC/PRAMDAC etc? */

    if (!engine->graph.accel_blocked) {
        ret = nouveau_fence_init(dev);
        if (ret)
            goto out_irq;

        ret = nouveau_card_init_channel(dev);
        if (ret)
            goto out_fence;
    }

    nouveau_fbcon_init(dev);
    drm_kms_helper_poll_init(dev);
    return 0;

out_fence:
    nouveau_fence_fini(dev);
out_irq:
    nouveau_irq_fini(dev);
out_vblank:
    drm_vblank_cleanup(dev);
    engine->display.destroy(dev);
out_fifo:
    if (!nouveau_noaccel)
        engine->fifo.takedown(dev);
out_crypt:
    if (!nouveau_noaccel)
        engine->crypt.takedown(dev);
out_graph:
    if (!nouveau_noaccel)
        engine->graph.takedown(dev);
out_fb:
    engine->fb.takedown(dev);
out_timer:
    engine->timer.takedown(dev);
out_gpio:
    engine->gpio.takedown(dev);
out_mc:
    engine->mc.takedown(dev);
out_gart:
    nouveau_mem_gart_fini(dev);
out_instmem:
    engine->instmem.takedown(dev);
out_gpuobj:
    nouveau_gpuobj_takedown(dev);
out_vram:
    nouveau_mem_vram_fini(dev);
out_bios:
    nouveau_pm_fini(dev);
    nouveau_bios_takedown(dev);
out_display_early:
    engine->display.late_takedown(dev);
out:
    vga_client_register(dev->pdev, NULL, NULL, NULL);
    return ret;
}
Example #4
0
int
nouveau_card_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_engine *engine;
	int ret, e = 0;

	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
	vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
				       nouveau_switcheroo_reprobe,
				       nouveau_switcheroo_can_switch);

	/* Initialise internal driver API hooks */
	ret = nouveau_init_engine_ptrs(dev);
	if (ret)
		goto out;
	engine = &dev_priv->engine;
	spin_lock_init(&dev_priv->channels.lock);
	spin_lock_init(&dev_priv->tile.lock);
	spin_lock_init(&dev_priv->context_switch_lock);
	spin_lock_init(&dev_priv->vm_lock);

	/* Make the CRTCs and I2C buses accessible */
	ret = engine->display.early_init(dev);
	if (ret)
		goto out;

	/* Parse BIOS tables / Run init tables if card not POSTed */
	ret = nouveau_bios_init(dev);
	if (ret)
		goto out_display_early;

	/* workaround an odd issue on nvc1 by disabling the device's
	 * nosnoop capability.  hopefully won't cause issues until a
	 * better fix is found - assuming there is one...
	 */
	if (dev_priv->chipset == 0xc1) {
		nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
	}

	/* PMC */
	ret = engine->mc.init(dev);
	if (ret)
		goto out_bios;

	/* PTIMER */
	ret = engine->timer.init(dev);
	if (ret)
		goto out_mc;

	/* PFB */
	ret = engine->fb.init(dev);
	if (ret)
		goto out_timer;

	ret = engine->vram.init(dev);
	if (ret)
		goto out_fb;

	/* PGPIO */
	ret = nouveau_gpio_create(dev);
	if (ret)
		goto out_vram;

	ret = nouveau_gpuobj_init(dev);
	if (ret)
		goto out_gpio;

	ret = engine->instmem.init(dev);
	if (ret)
		goto out_gpuobj;

	ret = nouveau_mem_vram_init(dev);
	if (ret)
		goto out_instmem;

	ret = nouveau_mem_gart_init(dev);
	if (ret)
		goto out_ttmvram;

	if (!dev_priv->noaccel) {
		switch (dev_priv->card_type) {
		case NV_04:
			nv04_graph_create(dev);
			break;
		case NV_10:
			nv10_graph_create(dev);
			break;
		case NV_20:
		case NV_30:
			nv20_graph_create(dev);
			break;
		case NV_40:
			nv40_graph_create(dev);
			break;
		case NV_50:
			nv50_graph_create(dev);
			break;
		case NV_C0:
		case NV_D0:
			nvc0_graph_create(dev);
			break;
		default:
			break;
		}

		switch (dev_priv->chipset) {
		case 0x84:
		case 0x86:
		case 0x92:
		case 0x94:
		case 0x96:
		case 0xa0:
			nv84_crypt_create(dev);
			break;
		case 0x98:
		case 0xaa:
		case 0xac:
			nv98_crypt_create(dev);
			break;
		}

		switch (dev_priv->card_type) {
		case NV_50:
			switch (dev_priv->chipset) {
			case 0xa3:
			case 0xa5:
			case 0xa8:
			case 0xaf:
				nva3_copy_create(dev);
				break;
			}
			break;
		case NV_C0:
			nvc0_copy_create(dev, 0);
			nvc0_copy_create(dev, 1);
			break;
		default:
			break;
		}

		if (dev_priv->chipset >= 0xa3 || dev_priv->chipset == 0x98) {
			nv84_bsp_create(dev);
			nv84_vp_create(dev);
			nv98_ppp_create(dev);
		} else
		if (dev_priv->chipset >= 0x84) {
			nv50_mpeg_create(dev);
			nv84_bsp_create(dev);
			nv84_vp_create(dev);
		} else
		if (dev_priv->chipset >= 0x50) {
			nv50_mpeg_create(dev);
		} else
		if (dev_priv->card_type == NV_40 ||
		    dev_priv->chipset == 0x31 ||
		    dev_priv->chipset == 0x34 ||
		    dev_priv->chipset == 0x36) {
			nv31_mpeg_create(dev);
		}

		for (e = 0; e < NVOBJ_ENGINE_NR; e++) {
			if (dev_priv->eng[e]) {
				ret = dev_priv->eng[e]->init(dev, e);
				if (ret)
					goto out_engine;
			}
		}

		/* PFIFO */
		ret = engine->fifo.init(dev);
		if (ret)
			goto out_engine;
	}

	ret = nouveau_irq_init(dev);
	if (ret)
		goto out_fifo;

	ret = nouveau_display_create(dev);
	if (ret)
		goto out_irq;

	nouveau_backlight_init(dev);
	nouveau_pm_init(dev);

	ret = nouveau_fence_init(dev);
	if (ret)
		goto out_pm;

	if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
		ret = nouveau_card_channel_init(dev);
		if (ret)
			goto out_fence;
	}

	if (dev->mode_config.num_crtc) {
		ret = nouveau_display_init(dev);
		if (ret)
			goto out_chan;

		nouveau_fbcon_init(dev);
	}

	return 0;

out_chan:
	nouveau_card_channel_fini(dev);
out_fence:
	nouveau_fence_fini(dev);
out_pm:
	nouveau_pm_fini(dev);
	nouveau_backlight_exit(dev);
	nouveau_display_destroy(dev);
out_irq:
	nouveau_irq_fini(dev);
out_fifo:
	if (!dev_priv->noaccel)
		engine->fifo.takedown(dev);
out_engine:
	if (!dev_priv->noaccel) {
		for (e = e - 1; e >= 0; e--) {
			if (!dev_priv->eng[e])
				continue;
			dev_priv->eng[e]->fini(dev, e, false);
			dev_priv->eng[e]->destroy(dev,e );
		}
	}
	nouveau_mem_gart_fini(dev);
out_ttmvram:
	nouveau_mem_vram_fini(dev);
out_instmem:
	engine->instmem.takedown(dev);
out_gpuobj:
	nouveau_gpuobj_takedown(dev);
out_gpio:
	nouveau_gpio_destroy(dev);
out_vram:
	engine->vram.takedown(dev);
out_fb:
	engine->fb.takedown(dev);
out_timer:
	engine->timer.takedown(dev);
out_mc:
	engine->mc.takedown(dev);
out_bios:
	nouveau_bios_takedown(dev);
out_display_early:
	engine->display.late_takedown(dev);
out:
	vga_client_register(dev->pdev, NULL, NULL, NULL);
	return ret;
}
/* stops a fifo */
void
nouveau_channel_free(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_fifo_engine *pfifo = &dev_priv->engine.fifo;
	unsigned long flags;
	int ret;

	NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id);

	nouveau_debugfs_channel_fini(chan);

	/* Give outstanding push buffers a chance to complete */
	spin_lock_irqsave(&chan->fence.lock, flags);
	nouveau_fence_update(chan);
	spin_unlock_irqrestore(&chan->fence.lock, flags);
	if (chan->fence.sequence != chan->fence.sequence_ack) {
		struct nouveau_fence *fence = NULL;

		ret = nouveau_fence_new(chan, &fence, true);
		if (ret == 0) {
			ret = nouveau_fence_wait(fence, NULL, false, false);
			nouveau_fence_unref((void *)&fence);
		}

		if (ret)
			NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id);
	}

	/* Ensure all outstanding fences are signaled.  They should be if the
	 * above attempts at idling were OK, but if we failed this'll tell TTM
	 * we're done with the buffers.
	 */
	nouveau_fence_fini(chan);

	/* Ensure the channel is no longer active on the GPU */
	pfifo->reassign(dev, false);

	pgraph->fifo_access(dev, false);
	if (pgraph->channel(dev) == chan)
		pgraph->unload_context(dev);
	pgraph->destroy_context(chan);
	pgraph->fifo_access(dev, true);

	if (pfifo->channel_id(dev) == chan->id) {
		pfifo->disable(dev);
		pfifo->unload_context(dev);
		pfifo->enable(dev);
	}
	pfifo->destroy_context(chan);

	pfifo->reassign(dev, true);

	/* Release the channel's resources */
	nouveau_gpuobj_ref_del(dev, &chan->pushbuf);
	if (chan->pushbuf_bo) {
		nouveau_bo_unpin(chan->pushbuf_bo);
		nouveau_bo_ref(NULL, &chan->pushbuf_bo);
	}
	nouveau_gpuobj_channel_takedown(chan);
	nouveau_notifier_takedown_channel(chan);
	if (chan->user)
		iounmap(chan->user);

	dev_priv->fifos[chan->id] = NULL;
	dev_priv->fifo_alloc_count--;
	kfree(chan);
}