linux/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Red Hat Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Ben Skeggs
  23 */
  24
  25#include "nv04.h"
  26
  27static inline int
  28nv44_graph_class(struct nv04_instmem_priv *priv)
  29{
  30        if ((nv_device(priv)->chipset & 0xf0) == 0x60)
  31                return 1;
  32        return !(0x0baf & (1 << (nv_device(priv)->chipset & 0x0f)));
  33}
  34
  35static int
  36nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
  37                  struct nouveau_oclass *oclass, void *data, u32 size,
  38                  struct nouveau_object **pobject)
  39{
  40        struct nouveau_device *device = nv_device(parent);
  41        struct pci_dev *pdev = device->pdev;
  42        struct nv04_instmem_priv *priv;
  43        int ret, bar, vs;
  44
  45        ret = nouveau_instmem_create(parent, engine, oclass, &priv);
  46        *pobject = nv_object(priv);
  47        if (ret)
  48                return ret;
  49
  50        /* map bar */
  51        if (pci_resource_len(pdev, 2))
  52                bar = 2;
  53        else
  54                bar = 3;
  55
  56        priv->iomem = ioremap(pci_resource_start(pdev, bar),
  57                              pci_resource_len(pdev, bar));
  58        if (!priv->iomem) {
  59                nv_error(priv, "unable to map PRAMIN BAR\n");
  60                return -EFAULT;
  61        }
  62
  63        /* PRAMIN aperture maps over the end of vram, reserve enough space
  64         * to fit graphics contexts for every channel, the magics come
  65         * from engine/graph/nv40.c
  66         */
  67        vs = hweight8((nv_rd32(priv, 0x001540) & 0x0000ff00) >> 8);
  68        if      (device->chipset == 0x40) priv->base.reserved = 0x6aa0 * vs;
  69        else if (device->chipset  < 0x43) priv->base.reserved = 0x4f00 * vs;
  70        else if (nv44_graph_class(priv))  priv->base.reserved = 0x4980 * vs;
  71        else                              priv->base.reserved = 0x4a40 * vs;
  72        priv->base.reserved += 16 * 1024;
  73        priv->base.reserved *= 32;              /* per-channel */
  74        priv->base.reserved += 512 * 1024;      /* pci(e)gart table */
  75        priv->base.reserved += 512 * 1024;      /* object storage */
  76
  77        priv->base.reserved = round_up(priv->base.reserved, 4096);
  78        priv->base.alloc    = nv04_instmem_alloc;
  79
  80        ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);
  81        if (ret)
  82                return ret;
  83
  84        /* 0x00000-0x10000: reserve for probable vbios image */
  85        ret = nouveau_gpuobj_new(parent, NULL, 0x10000, 0, 0, &priv->vbios);
  86        if (ret)
  87                return ret;
  88
  89        /* 0x10000-0x18000: reserve for RAMHT */
  90        ret = nouveau_ramht_new(parent, NULL, 0x08000, 0, &priv->ramht);
  91        if (ret)
  92                return ret;
  93
  94        /* 0x18000-0x18200: reserve for RAMRO
  95         * 0x18200-0x20000: padding
  96         */
  97        ret = nouveau_gpuobj_new(parent, NULL, 0x08000, 0, 0, &priv->ramro);
  98        if (ret)
  99                return ret;
 100
 101        /* 0x20000-0x21000: reserve for RAMFC
 102         * 0x21000-0x40000: padding and some unknown crap
 103         */
 104        ret = nouveau_gpuobj_new(parent, NULL, 0x20000, 0,
 105                                 NVOBJ_FLAG_ZERO_ALLOC, &priv->ramfc);
 106        if (ret)
 107                return ret;
 108
 109        priv->created = true;
 110        return 0;
 111}
 112
 113static u32
 114nv40_instmem_rd32(struct nouveau_object *object, u32 addr)
 115{
 116        struct nv04_instmem_priv *priv = (void *)object;
 117        return ioread32_native(priv->iomem + addr);
 118}
 119
 120static void
 121nv40_instmem_wr32(struct nouveau_object *object, u32 addr, u32 data)
 122{
 123        struct nv04_instmem_priv *priv = (void *)object;
 124        iowrite32_native(data, priv->iomem + addr);
 125}
 126
 127struct nouveau_oclass
 128nv40_instmem_oclass = {
 129        .handle = NV_SUBDEV(INSTMEM, 0x40),
 130        .ofuncs = &(struct nouveau_ofuncs) {
 131                .ctor = nv40_instmem_ctor,
 132                .dtor = nv04_instmem_dtor,
 133                .init = _nouveau_instmem_init,
 134                .fini = _nouveau_instmem_fini,
 135                .rd32 = nv40_instmem_rd32,
 136                .wr32 = nv40_instmem_wr32,
 137        },
 138};
 139