linux/drivers/gpu/drm/nouveau/core/engine/device/base.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 <core/object.h>
  26#include <core/device.h>
  27#include <core/client.h>
  28#include <core/option.h>
  29
  30#include <core/class.h>
  31
  32#include <engine/device.h>
  33
  34static DEFINE_MUTEX(nv_devices_mutex);
  35static LIST_HEAD(nv_devices);
  36
  37struct nouveau_device *
  38nouveau_device_find(u64 name)
  39{
  40        struct nouveau_device *device, *match = NULL;
  41        mutex_lock(&nv_devices_mutex);
  42        list_for_each_entry(device, &nv_devices, head) {
  43                if (device->handle == name) {
  44                        match = device;
  45                        break;
  46                }
  47        }
  48        mutex_unlock(&nv_devices_mutex);
  49        return match;
  50}
  51
  52/******************************************************************************
  53 * nouveau_devobj (0x0080): class implementation
  54 *****************************************************************************/
  55struct nouveau_devobj {
  56        struct nouveau_parent base;
  57        struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
  58};
  59
  60static const u64 disable_map[] = {
  61        [NVDEV_SUBDEV_VBIOS]    = NV_DEVICE_DISABLE_VBIOS,
  62        [NVDEV_SUBDEV_DEVINIT]  = NV_DEVICE_DISABLE_CORE,
  63        [NVDEV_SUBDEV_GPIO]     = NV_DEVICE_DISABLE_CORE,
  64        [NVDEV_SUBDEV_I2C]      = NV_DEVICE_DISABLE_CORE,
  65        [NVDEV_SUBDEV_CLOCK]    = NV_DEVICE_DISABLE_CORE,
  66        [NVDEV_SUBDEV_MXM]      = NV_DEVICE_DISABLE_CORE,
  67        [NVDEV_SUBDEV_MC]       = NV_DEVICE_DISABLE_CORE,
  68        [NVDEV_SUBDEV_BUS]      = NV_DEVICE_DISABLE_CORE,
  69        [NVDEV_SUBDEV_TIMER]    = NV_DEVICE_DISABLE_CORE,
  70        [NVDEV_SUBDEV_FB]       = NV_DEVICE_DISABLE_CORE,
  71        [NVDEV_SUBDEV_LTCG]     = NV_DEVICE_DISABLE_CORE,
  72        [NVDEV_SUBDEV_IBUS]     = NV_DEVICE_DISABLE_CORE,
  73        [NVDEV_SUBDEV_INSTMEM]  = NV_DEVICE_DISABLE_CORE,
  74        [NVDEV_SUBDEV_VM]       = NV_DEVICE_DISABLE_CORE,
  75        [NVDEV_SUBDEV_BAR]      = NV_DEVICE_DISABLE_CORE,
  76        [NVDEV_SUBDEV_VOLT]     = NV_DEVICE_DISABLE_CORE,
  77        [NVDEV_SUBDEV_THERM]    = NV_DEVICE_DISABLE_CORE,
  78        [NVDEV_ENGINE_DMAOBJ]   = NV_DEVICE_DISABLE_CORE,
  79        [NVDEV_ENGINE_FIFO]     = NV_DEVICE_DISABLE_FIFO,
  80        [NVDEV_ENGINE_SW]       = NV_DEVICE_DISABLE_FIFO,
  81        [NVDEV_ENGINE_GR]       = NV_DEVICE_DISABLE_GRAPH,
  82        [NVDEV_ENGINE_MPEG]     = NV_DEVICE_DISABLE_MPEG,
  83        [NVDEV_ENGINE_ME]       = NV_DEVICE_DISABLE_ME,
  84        [NVDEV_ENGINE_VP]       = NV_DEVICE_DISABLE_VP,
  85        [NVDEV_ENGINE_CRYPT]    = NV_DEVICE_DISABLE_CRYPT,
  86        [NVDEV_ENGINE_BSP]      = NV_DEVICE_DISABLE_BSP,
  87        [NVDEV_ENGINE_PPP]      = NV_DEVICE_DISABLE_PPP,
  88        [NVDEV_ENGINE_COPY0]    = NV_DEVICE_DISABLE_COPY0,
  89        [NVDEV_ENGINE_COPY1]    = NV_DEVICE_DISABLE_COPY1,
  90        [NVDEV_ENGINE_UNK1C1]   = NV_DEVICE_DISABLE_UNK1C1,
  91        [NVDEV_ENGINE_VENC]     = NV_DEVICE_DISABLE_VENC,
  92        [NVDEV_ENGINE_DISP]     = NV_DEVICE_DISABLE_DISP,
  93        [NVDEV_SUBDEV_NR]       = 0,
  94};
  95
  96static int
  97nouveau_devobj_ctor(struct nouveau_object *parent,
  98                    struct nouveau_object *engine,
  99                    struct nouveau_oclass *oclass, void *data, u32 size,
 100                    struct nouveau_object **pobject)
 101{
 102        struct nouveau_client *client = nv_client(parent);
 103        struct nouveau_device *device;
 104        struct nouveau_devobj *devobj;
 105        struct nv_device_class *args = data;
 106        u32 boot0, strap;
 107        u64 disable, mmio_base, mmio_size;
 108        void __iomem *map;
 109        int ret, i, c;
 110
 111        if (size < sizeof(struct nv_device_class))
 112                return -EINVAL;
 113
 114        /* find the device subdev that matches what the client requested */
 115        device = nv_device(client->device);
 116        if (args->device != ~0) {
 117                device = nouveau_device_find(args->device);
 118                if (!device)
 119                        return -ENODEV;
 120        }
 121
 122        ret = nouveau_parent_create(parent, nv_object(device), oclass, 0, NULL,
 123                                    (1ULL << NVDEV_ENGINE_DMAOBJ) |
 124                                    (1ULL << NVDEV_ENGINE_FIFO) |
 125                                    (1ULL << NVDEV_ENGINE_DISP), &devobj);
 126        *pobject = nv_object(devobj);
 127        if (ret)
 128                return ret;
 129
 130        mmio_base = pci_resource_start(device->pdev, 0);
 131        mmio_size = pci_resource_len(device->pdev, 0);
 132
 133        /* translate api disable mask into internal mapping */
 134        disable = args->debug0;
 135        for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
 136                if (args->disable & disable_map[i])
 137                        disable |= (1ULL << i);
 138        }
 139
 140        /* identify the chipset, and determine classes of subdev/engines */
 141        if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) &&
 142            !device->card_type) {
 143                map = ioremap(mmio_base, 0x102000);
 144                if (map == NULL)
 145                        return -ENOMEM;
 146
 147                /* switch mmio to cpu's native endianness */
 148#ifndef __BIG_ENDIAN
 149                if (ioread32_native(map + 0x000004) != 0x00000000)
 150#else
 151                if (ioread32_native(map + 0x000004) == 0x00000000)
 152#endif
 153                        iowrite32_native(0x01000001, map + 0x000004);
 154
 155                /* read boot0 and strapping information */
 156                boot0 = ioread32_native(map + 0x000000);
 157                strap = ioread32_native(map + 0x101000);
 158                iounmap(map);
 159
 160                /* determine chipset and derive architecture from it */
 161                if ((boot0 & 0x0f000000) > 0) {
 162                        device->chipset = (boot0 & 0xff00000) >> 20;
 163                        switch (device->chipset & 0xf0) {
 164                        case 0x10: device->card_type = NV_10; break;
 165                        case 0x20: device->card_type = NV_20; break;
 166                        case 0x30: device->card_type = NV_30; break;
 167                        case 0x40:
 168                        case 0x60: device->card_type = NV_40; break;
 169                        case 0x50:
 170                        case 0x80:
 171                        case 0x90:
 172                        case 0xa0: device->card_type = NV_50; break;
 173                        case 0xc0: device->card_type = NV_C0; break;
 174                        case 0xd0: device->card_type = NV_D0; break;
 175                        case 0xe0:
 176                        case 0xf0: device->card_type = NV_E0; break;
 177                        default:
 178                                break;
 179                        }
 180                } else
 181                if ((boot0 & 0xff00fff0) == 0x20004000) {
 182                        if (boot0 & 0x00f00000)
 183                                device->chipset = 0x05;
 184                        else
 185                                device->chipset = 0x04;
 186                        device->card_type = NV_04;
 187                }
 188
 189                switch (device->card_type) {
 190                case NV_04: ret = nv04_identify(device); break;
 191                case NV_10: ret = nv10_identify(device); break;
 192                case NV_20: ret = nv20_identify(device); break;
 193                case NV_30: ret = nv30_identify(device); break;
 194                case NV_40: ret = nv40_identify(device); break;
 195                case NV_50: ret = nv50_identify(device); break;
 196                case NV_C0:
 197                case NV_D0: ret = nvc0_identify(device); break;
 198                case NV_E0: ret = nve0_identify(device); break;
 199                default:
 200                        ret = -EINVAL;
 201                        break;
 202                }
 203
 204                if (ret) {
 205                        nv_error(device, "unknown chipset, 0x%08x\n", boot0);
 206                        return ret;
 207                }
 208
 209                nv_info(device, "BOOT0  : 0x%08x\n", boot0);
 210                nv_info(device, "Chipset: %s (NV%02X)\n",
 211                        device->cname, device->chipset);
 212                nv_info(device, "Family : NV%02X\n", device->card_type);
 213
 214                /* determine frequency of timing crystal */
 215                if ( device->chipset < 0x17 ||
 216                    (device->chipset >= 0x20 && device->chipset < 0x25))
 217                        strap &= 0x00000040;
 218                else
 219                        strap &= 0x00400040;
 220
 221                switch (strap) {
 222                case 0x00000000: device->crystal = 13500; break;
 223                case 0x00000040: device->crystal = 14318; break;
 224                case 0x00400000: device->crystal = 27000; break;
 225                case 0x00400040: device->crystal = 25000; break;
 226                }
 227
 228                nv_debug(device, "crystal freq: %dKHz\n", device->crystal);
 229        }
 230
 231        if (!(args->disable & NV_DEVICE_DISABLE_MMIO) &&
 232            !nv_subdev(device)->mmio) {
 233                nv_subdev(device)->mmio  = ioremap(mmio_base, mmio_size);
 234                if (!nv_subdev(device)->mmio) {
 235                        nv_error(device, "unable to map device registers\n");
 236                        return -ENOMEM;
 237                }
 238        }
 239
 240        /* ensure requested subsystems are available for use */
 241        for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) {
 242                if (!(oclass = device->oclass[i]) || (disable & (1ULL << i)))
 243                        continue;
 244
 245                if (device->subdev[i]) {
 246                        nouveau_object_ref(device->subdev[i],
 247                                          &devobj->subdev[i]);
 248                        continue;
 249                }
 250
 251                ret = nouveau_object_ctor(nv_object(device), NULL,
 252                                          oclass, NULL, i,
 253                                          &devobj->subdev[i]);
 254                if (ret == -ENODEV)
 255                        continue;
 256                if (ret)
 257                        return ret;
 258
 259                /* note: can't init *any* subdevs until devinit has been run
 260                 * due to not knowing exactly what the vbios init tables will
 261                 * mess with.  devinit also can't be run until all of its
 262                 * dependencies have been created.
 263                 *
 264                 * this code delays init of any subdev until all of devinit's
 265                 * dependencies have been created, and then initialises each
 266                 * subdev in turn as they're created.
 267                 */
 268                while (i >= NVDEV_SUBDEV_DEVINIT_LAST && c <= i) {
 269                        struct nouveau_object *subdev = devobj->subdev[c++];
 270                        if (subdev && !nv_iclass(subdev, NV_ENGINE_CLASS)) {
 271                                ret = nouveau_object_inc(subdev);
 272                                if (ret)
 273                                        return ret;
 274                                atomic_dec(&nv_object(device)->usecount);
 275                        } else
 276                        if (subdev) {
 277                                nouveau_subdev_reset(subdev);
 278                        }
 279                }
 280        }
 281
 282        return 0;
 283}
 284
 285static void
 286nouveau_devobj_dtor(struct nouveau_object *object)
 287{
 288        struct nouveau_devobj *devobj = (void *)object;
 289        int i;
 290
 291        for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
 292                nouveau_object_ref(NULL, &devobj->subdev[i]);
 293
 294        nouveau_parent_destroy(&devobj->base);
 295}
 296
 297static u8
 298nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
 299{
 300        return nv_rd08(object->engine, addr);
 301}
 302
 303static u16
 304nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
 305{
 306        return nv_rd16(object->engine, addr);
 307}
 308
 309static u32
 310nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
 311{
 312        return nv_rd32(object->engine, addr);
 313}
 314
 315static void
 316nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
 317{
 318        nv_wr08(object->engine, addr, data);
 319}
 320
 321static void
 322nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
 323{
 324        nv_wr16(object->engine, addr, data);
 325}
 326
 327static void
 328nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
 329{
 330        nv_wr32(object->engine, addr, data);
 331}
 332
 333static struct nouveau_ofuncs
 334nouveau_devobj_ofuncs = {
 335        .ctor = nouveau_devobj_ctor,
 336        .dtor = nouveau_devobj_dtor,
 337        .init = _nouveau_parent_init,
 338        .fini = _nouveau_parent_fini,
 339        .rd08 = nouveau_devobj_rd08,
 340        .rd16 = nouveau_devobj_rd16,
 341        .rd32 = nouveau_devobj_rd32,
 342        .wr08 = nouveau_devobj_wr08,
 343        .wr16 = nouveau_devobj_wr16,
 344        .wr32 = nouveau_devobj_wr32,
 345};
 346
 347/******************************************************************************
 348 * nouveau_device: engine functions
 349 *****************************************************************************/
 350static struct nouveau_oclass
 351nouveau_device_sclass[] = {
 352        { 0x0080, &nouveau_devobj_ofuncs },
 353        {}
 354};
 355
 356static int
 357nouveau_device_fini(struct nouveau_object *object, bool suspend)
 358{
 359        struct nouveau_device *device = (void *)object;
 360        struct nouveau_object *subdev;
 361        int ret, i;
 362
 363        for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
 364                if ((subdev = device->subdev[i])) {
 365                        if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
 366                                ret = nouveau_object_dec(subdev, suspend);
 367                                if (ret && suspend)
 368                                        goto fail;
 369                        }
 370                }
 371        }
 372
 373        ret = 0;
 374fail:
 375        for (; ret && i < NVDEV_SUBDEV_NR; i++) {
 376                if ((subdev = device->subdev[i])) {
 377                        if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
 378                                ret = nouveau_object_inc(subdev);
 379                                if (ret) {
 380                                        /* XXX */
 381                                }
 382                        }
 383                }
 384        }
 385
 386        return ret;
 387}
 388
 389static int
 390nouveau_device_init(struct nouveau_object *object)
 391{
 392        struct nouveau_device *device = (void *)object;
 393        struct nouveau_object *subdev;
 394        int ret, i;
 395
 396        for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
 397                if ((subdev = device->subdev[i])) {
 398                        if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
 399                                ret = nouveau_object_inc(subdev);
 400                                if (ret)
 401                                        goto fail;
 402                        } else {
 403                                nouveau_subdev_reset(subdev);
 404                        }
 405                }
 406        }
 407
 408        ret = 0;
 409fail:
 410        for (--i; ret && i >= 0; i--) {
 411                if ((subdev = device->subdev[i])) {
 412                        if (!nv_iclass(subdev, NV_ENGINE_CLASS))
 413                                nouveau_object_dec(subdev, false);
 414                }
 415        }
 416
 417        return ret;
 418}
 419
 420static void
 421nouveau_device_dtor(struct nouveau_object *object)
 422{
 423        struct nouveau_device *device = (void *)object;
 424
 425        mutex_lock(&nv_devices_mutex);
 426        list_del(&device->head);
 427        mutex_unlock(&nv_devices_mutex);
 428
 429        if (nv_subdev(device)->mmio)
 430                iounmap(nv_subdev(device)->mmio);
 431
 432        nouveau_engine_destroy(&device->base);
 433}
 434
 435static struct nouveau_oclass
 436nouveau_device_oclass = {
 437        .handle = NV_ENGINE(DEVICE, 0x00),
 438        .ofuncs = &(struct nouveau_ofuncs) {
 439                .dtor = nouveau_device_dtor,
 440                .init = nouveau_device_init,
 441                .fini = nouveau_device_fini,
 442        },
 443};
 444
 445int
 446nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,
 447                       const char *cfg, const char *dbg,
 448                       int length, void **pobject)
 449{
 450        struct nouveau_device *device;
 451        int ret = -EEXIST;
 452
 453        mutex_lock(&nv_devices_mutex);
 454        list_for_each_entry(device, &nv_devices, head) {
 455                if (device->handle == name)
 456                        goto done;
 457        }
 458
 459        ret = nouveau_engine_create_(NULL, NULL, &nouveau_device_oclass, true,
 460                                     "DEVICE", "device", length, pobject);
 461        device = *pobject;
 462        if (ret)
 463                goto done;
 464
 465        device->pdev = pdev;
 466        device->handle = name;
 467        device->cfgopt = cfg;
 468        device->dbgopt = dbg;
 469        device->name = sname;
 470
 471        nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE");
 472        nv_engine(device)->sclass = nouveau_device_sclass;
 473        list_add(&device->head, &nv_devices);
 474done:
 475        mutex_unlock(&nv_devices_mutex);
 476        return ret;
 477}
 478