diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_object.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_object.c | 118 |
1 files changed, 16 insertions, 102 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 67a16e01ffa..8f97016f5b2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c | |||
| @@ -361,20 +361,6 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst, | |||
| 361 | return 0; | 361 | return 0; |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | |||
| 365 | static uint32_t | ||
| 366 | nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class) | ||
| 367 | { | ||
| 368 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 369 | |||
| 370 | /*XXX: dodgy hack for now */ | ||
| 371 | if (dev_priv->card_type >= NV_50) | ||
| 372 | return 24; | ||
| 373 | if (dev_priv->card_type >= NV_40) | ||
| 374 | return 32; | ||
| 375 | return 16; | ||
| 376 | } | ||
| 377 | |||
| 378 | /* | 364 | /* |
| 379 | DMA objects are used to reference a piece of memory in the | 365 | DMA objects are used to reference a piece of memory in the |
| 380 | framebuffer, PCI or AGP address space. Each object is 16 bytes big | 366 | framebuffer, PCI or AGP address space. Each object is 16 bytes big |
| @@ -606,11 +592,11 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, | |||
| 606 | set to 0? | 592 | set to 0? |
| 607 | */ | 593 | */ |
| 608 | static int | 594 | static int |
| 609 | nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, | 595 | nouveau_gpuobj_sw_new(struct nouveau_channel *chan, u32 handle, u16 class) |
| 610 | struct nouveau_gpuobj **gpuobj_ret) | ||
| 611 | { | 596 | { |
| 612 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 597 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
| 613 | struct nouveau_gpuobj *gpuobj; | 598 | struct nouveau_gpuobj *gpuobj; |
| 599 | int ret; | ||
| 614 | 600 | ||
| 615 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); | 601 | gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); |
| 616 | if (!gpuobj) | 602 | if (!gpuobj) |
| @@ -624,8 +610,10 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, | |||
| 624 | spin_lock(&dev_priv->ramin_lock); | 610 | spin_lock(&dev_priv->ramin_lock); |
| 625 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); | 611 | list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); |
| 626 | spin_unlock(&dev_priv->ramin_lock); | 612 | spin_unlock(&dev_priv->ramin_lock); |
| 627 | *gpuobj_ret = gpuobj; | 613 | |
| 628 | return 0; | 614 | ret = nouveau_ramht_insert(chan, handle, gpuobj); |
| 615 | nouveau_gpuobj_ref(NULL, &gpuobj); | ||
| 616 | return ret; | ||
| 629 | } | 617 | } |
| 630 | 618 | ||
| 631 | int | 619 | int |
| @@ -634,101 +622,30 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class) | |||
| 634 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 622 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
| 635 | struct drm_device *dev = chan->dev; | 623 | struct drm_device *dev = chan->dev; |
| 636 | struct nouveau_gpuobj_class *oc; | 624 | struct nouveau_gpuobj_class *oc; |
| 637 | struct nouveau_gpuobj *gpuobj; | ||
| 638 | int ret; | 625 | int ret; |
| 639 | 626 | ||
| 640 | NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); | 627 | NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); |
| 641 | 628 | ||
| 642 | list_for_each_entry(oc, &dev_priv->classes, head) { | 629 | list_for_each_entry(oc, &dev_priv->classes, head) { |
| 643 | if (oc->id == class) | 630 | struct nouveau_exec_engine *eng = dev_priv->eng[oc->engine]; |
| 644 | goto found; | ||
| 645 | } | ||
| 646 | |||
| 647 | NV_ERROR(dev, "illegal object class: 0x%x\n", class); | ||
| 648 | return -EINVAL; | ||
| 649 | 631 | ||
| 650 | found: | 632 | if (oc->id != class) |
| 651 | switch (oc->engine) { | 633 | continue; |
| 652 | case NVOBJ_ENGINE_SW: | ||
| 653 | if (dev_priv->card_type < NV_C0) { | ||
| 654 | ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj); | ||
| 655 | if (ret) | ||
| 656 | return ret; | ||
| 657 | goto insert; | ||
| 658 | } | ||
| 659 | break; | ||
| 660 | case NVOBJ_ENGINE_GR: | ||
| 661 | if ((dev_priv->card_type >= NV_20 && !chan->ramin_grctx) || | ||
| 662 | (dev_priv->card_type < NV_20 && !chan->pgraph_ctx)) { | ||
| 663 | struct nouveau_pgraph_engine *pgraph = | ||
| 664 | &dev_priv->engine.graph; | ||
| 665 | 634 | ||
| 666 | ret = pgraph->create_context(chan); | 635 | if (oc->engine == NVOBJ_ENGINE_SW) |
| 667 | if (ret) | 636 | return nouveau_gpuobj_sw_new(chan, handle, class); |
| 668 | return ret; | ||
| 669 | } | ||
| 670 | break; | ||
| 671 | case NVOBJ_ENGINE_CRYPT: | ||
| 672 | if (!chan->crypt_ctx) { | ||
| 673 | struct nouveau_crypt_engine *pcrypt = | ||
| 674 | &dev_priv->engine.crypt; | ||
| 675 | 637 | ||
| 676 | ret = pcrypt->create_context(chan); | 638 | if (!chan->engctx[oc->engine]) { |
| 639 | ret = eng->context_new(chan, oc->engine); | ||
| 677 | if (ret) | 640 | if (ret) |
| 678 | return ret; | 641 | return ret; |
| 679 | } | 642 | } |
| 680 | break; | ||
| 681 | } | ||
| 682 | |||
| 683 | /* we're done if this is fermi */ | ||
| 684 | if (dev_priv->card_type >= NV_C0) | ||
| 685 | return 0; | ||
| 686 | |||
| 687 | ret = nouveau_gpuobj_new(dev, chan, | ||
| 688 | nouveau_gpuobj_class_instmem_size(dev, class), | ||
| 689 | 16, | ||
| 690 | NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, | ||
| 691 | &gpuobj); | ||
| 692 | if (ret) { | ||
| 693 | NV_ERROR(dev, "error creating gpuobj: %d\n", ret); | ||
| 694 | return ret; | ||
| 695 | } | ||
| 696 | 643 | ||
| 697 | if (dev_priv->card_type >= NV_50) { | 644 | return eng->object_new(chan, oc->engine, handle, class); |
| 698 | nv_wo32(gpuobj, 0, class); | ||
| 699 | nv_wo32(gpuobj, 20, 0x00010000); | ||
| 700 | } else { | ||
| 701 | switch (class) { | ||
| 702 | case NV_CLASS_NULL: | ||
| 703 | nv_wo32(gpuobj, 0, 0x00001030); | ||
| 704 | nv_wo32(gpuobj, 4, 0xFFFFFFFF); | ||
| 705 | break; | ||
| 706 | default: | ||
| 707 | if (dev_priv->card_type >= NV_40) { | ||
| 708 | nv_wo32(gpuobj, 0, class); | ||
| 709 | #ifdef __BIG_ENDIAN | ||
| 710 | nv_wo32(gpuobj, 8, 0x01000000); | ||
| 711 | #endif | ||
| 712 | } else { | ||
| 713 | #ifdef __BIG_ENDIAN | ||
| 714 | nv_wo32(gpuobj, 0, class | 0x00080000); | ||
| 715 | #else | ||
| 716 | nv_wo32(gpuobj, 0, class); | ||
| 717 | #endif | ||
| 718 | } | ||
| 719 | } | ||
| 720 | } | 645 | } |
| 721 | dev_priv->engine.instmem.flush(dev); | ||
| 722 | |||
| 723 | gpuobj->engine = oc->engine; | ||
| 724 | gpuobj->class = oc->id; | ||
| 725 | 646 | ||
| 726 | insert: | 647 | NV_ERROR(dev, "illegal object class: 0x%x\n", class); |
| 727 | ret = nouveau_ramht_insert(chan, handle, gpuobj); | 648 | return -EINVAL; |
| 728 | if (ret) | ||
| 729 | NV_ERROR(dev, "error adding gpuobj to RAMHT: %d\n", ret); | ||
| 730 | nouveau_gpuobj_ref(NULL, &gpuobj); | ||
| 731 | return ret; | ||
| 732 | } | 649 | } |
| 733 | 650 | ||
| 734 | static int | 651 | static int |
| @@ -746,9 +663,6 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) | |||
| 746 | size = 0x2000; | 663 | size = 0x2000; |
| 747 | base = 0; | 664 | base = 0; |
| 748 | 665 | ||
| 749 | /* PGRAPH context */ | ||
| 750 | size += dev_priv->engine.graph.grctx_size; | ||
| 751 | |||
| 752 | if (dev_priv->card_type == NV_50) { | 666 | if (dev_priv->card_type == NV_50) { |
| 753 | /* Various fixed table thingos */ | 667 | /* Various fixed table thingos */ |
| 754 | size += 0x1400; /* mostly unknown stuff */ | 668 | size += 0x1400; /* mostly unknown stuff */ |
