Merge branch 'linux-3.17' of git://anongit.freedesktop.org/git/nouveau/linux-2.6

Pull nouveau drm updates from Ben Skeggs:
 "Apologies for not getting this done in time for Dave's drm-next merge
  window.  As he mentioned, a pre-existing bug reared its head a lot
  more obviously after this lot of changes.  It took quite a bit of time
  to track it down.  In any case, Dave suggested I try my luck by
  sending directly to you this time.

  Overview:

   - more code for Tegra GK20A from NVIDIA - probing, reclockig
   - better fix for Kepler GPUs that have the graphics engine powered
     off on startup, method courtesy of info provided by NVIDIA
   - unhardcoding of a bunch of graphics engine setup on
     Fermi/Kepler/Maxwell, will hopefully solve some issues people have
     noticed on higher-end models
   - support for "Zero Bandwidth Clear" on Fermi/Kepler/Maxwell, needs
     userspace support in general, but some lucky apps will benefit
     automagically
   - reviewed/exposed the full object APIs to userspace (finally), gives
     it access to perfctrs, ZBC controls, various events.  More to come
     in the future.
   - various other fixes"

Acked-by: Dave Airlie <airlied@redhat.com>

* 'linux-3.17' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (87 commits)
  drm/nouveau: expose the full object/event interfaces to userspace
  drm/nouveau: fix headless mode
  drm/nouveau: hide sysfs pstate file behind an option again
  drm/nv50/disp: shhh compiler
  drm/gf100-/gr: implement the proper SetShaderExceptions method
  drm/gf100-/gr: remove some broken ltc bashing, for now
  drm/gf100-/gr: unhardcode attribute cb config
  drm/gf100-/gr: fetch tpcs-per-ppc info on startup
  drm/gf100-/gr: unhardcode pagepool config
  drm/gf100-/gr: unhardcode bundle cb config
  drm/gf100-/gr: improve initial context patch list helpers
  drm/gf100-/gr: add support for zero bandwidth clear
  drm/nouveau/ltc: add zbc drivers
  drm/nouveau/ltc: s/ltcg/ltc/ + cleanup
  drm/nouveau: use ram info from nvif_device
  drm/nouveau/disp: implement nvif event sources for vblank/connector notifiers
  drm/nouveau/disp: allow user direct access to channel control registers
  drm/nouveau/disp: audit and version display classes
  drm/nouveau/disp: audit and version SCANOUTPOS method
  drm/nv50-/disp: audit and version PIOR_PWR method
  ...
This commit is contained in:
Linus Torvalds 2014-08-09 17:46:39 -07:00
commit 9138475862
264 changed files with 12198 additions and 5840 deletions

View File

@ -1,5 +1,5 @@
config DRM_NOUVEAU
tristate "Nouveau (nVidia) cards"
tristate "Nouveau (NVIDIA) cards"
depends on DRM && PCI
select FW_LOADER
select DRM_KMS_HELPER
@ -23,7 +23,15 @@ config DRM_NOUVEAU
select THERMAL if ACPI && X86
select ACPI_VIDEO if ACPI && X86
help
Choose this option for open-source nVidia support.
Choose this option for open-source NVIDIA support.
config NOUVEAU_PLATFORM_DRIVER
tristate "Nouveau (NVIDIA) SoC GPUs"
depends on DRM_NOUVEAU && ARCH_TEGRA
default y
help
Support for Nouveau platform driver, used for SoC GPUs as found
on NVIDIA Tegra K1.
config NOUVEAU_DEBUG
int "Maximum debug level"

View File

@ -14,8 +14,10 @@ nouveau-y += core/core/enum.o
nouveau-y += core/core/event.o
nouveau-y += core/core/gpuobj.o
nouveau-y += core/core/handle.o
nouveau-y += core/core/ioctl.o
nouveau-y += core/core/mm.o
nouveau-y += core/core/namedb.o
nouveau-y += core/core/notify.o
nouveau-y += core/core/object.o
nouveau-y += core/core/option.o
nouveau-y += core/core/parent.o
@ -26,6 +28,7 @@ nouveau-y += core/core/subdev.o
nouveau-y += core/subdev/bar/base.o
nouveau-y += core/subdev/bar/nv50.o
nouveau-y += core/subdev/bar/nvc0.o
nouveau-y += core/subdev/bar/gk20a.o
nouveau-y += core/subdev/bios/base.o
nouveau-y += core/subdev/bios/bit.o
nouveau-y += core/subdev/bios/boost.o
@ -64,6 +67,7 @@ nouveau-y += core/subdev/clock/nva3.o
nouveau-y += core/subdev/clock/nvaa.o
nouveau-y += core/subdev/clock/nvc0.o
nouveau-y += core/subdev/clock/nve0.o
nouveau-y += core/subdev/clock/gk20a.o
nouveau-y += core/subdev/clock/pllnv04.o
nouveau-y += core/subdev/clock/pllnva3.o
nouveau-y += core/subdev/devinit/base.o
@ -149,8 +153,10 @@ nouveau-y += core/subdev/instmem/base.o
nouveau-y += core/subdev/instmem/nv04.o
nouveau-y += core/subdev/instmem/nv40.o
nouveau-y += core/subdev/instmem/nv50.o
nouveau-y += core/subdev/ltcg/gf100.o
nouveau-y += core/subdev/ltcg/gm107.o
nouveau-y += core/subdev/ltc/base.o
nouveau-y += core/subdev/ltc/gf100.o
nouveau-y += core/subdev/ltc/gk104.o
nouveau-y += core/subdev/ltc/gm107.o
nouveau-y += core/subdev/mc/base.o
nouveau-y += core/subdev/mc/nv04.o
nouveau-y += core/subdev/mc/nv40.o
@ -161,6 +167,7 @@ nouveau-y += core/subdev/mc/nv94.o
nouveau-y += core/subdev/mc/nv98.o
nouveau-y += core/subdev/mc/nvc0.o
nouveau-y += core/subdev/mc/nvc3.o
nouveau-y += core/subdev/mc/gk20a.o
nouveau-y += core/subdev/mxm/base.o
nouveau-y += core/subdev/mxm/mxms.o
nouveau-y += core/subdev/mxm/nv50.o
@ -169,6 +176,7 @@ nouveau-y += core/subdev/pwr/memx.o
nouveau-y += core/subdev/pwr/nva3.o
nouveau-y += core/subdev/pwr/nvc0.o
nouveau-y += core/subdev/pwr/nvd0.o
nouveau-y += core/subdev/pwr/gk104.o
nouveau-y += core/subdev/pwr/nv108.o
nouveau-y += core/subdev/therm/base.o
nouveau-y += core/subdev/therm/fan.o
@ -211,6 +219,7 @@ nouveau-y += core/engine/copy/nvc0.o
nouveau-y += core/engine/copy/nve0.o
nouveau-y += core/engine/crypt/nv84.o
nouveau-y += core/engine/crypt/nv98.o
nouveau-y += core/engine/device/acpi.o
nouveau-y += core/engine/device/base.o
nouveau-y += core/engine/device/ctrl.o
nouveau-y += core/engine/device/nv04.o
@ -270,6 +279,7 @@ nouveau-y += core/engine/graph/ctxnvd9.o
nouveau-y += core/engine/graph/ctxnve4.o
nouveau-y += core/engine/graph/ctxgk20a.o
nouveau-y += core/engine/graph/ctxnvf0.o
nouveau-y += core/engine/graph/ctxgk110b.o
nouveau-y += core/engine/graph/ctxnv108.o
nouveau-y += core/engine/graph/ctxgm107.o
nouveau-y += core/engine/graph/nv04.o
@ -291,6 +301,7 @@ nouveau-y += core/engine/graph/nvd9.o
nouveau-y += core/engine/graph/nve4.o
nouveau-y += core/engine/graph/gk20a.o
nouveau-y += core/engine/graph/nvf0.o
nouveau-y += core/engine/graph/gk110b.o
nouveau-y += core/engine/graph/nv108.o
nouveau-y += core/engine/graph/gm107.o
nouveau-y += core/engine/mpeg/nv31.o
@ -318,11 +329,18 @@ nouveau-y += core/engine/vp/nv98.o
nouveau-y += core/engine/vp/nvc0.o
nouveau-y += core/engine/vp/nve0.o
# nvif
nouveau-y += nvif/object.o
nouveau-y += nvif/client.o
nouveau-y += nvif/device.o
nouveau-y += nvif/notify.o
# drm/core
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
nouveau-y += nouveau_vga.o nouveau_agp.o
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
nouveau-y += nouveau_prime.o nouveau_abi16.o
nouveau-y += nouveau_nvif.o nouveau_usif.o
nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o
nouveau-y += nv50_fence.o nv84_fence.o nvc0_fence.o
@ -349,3 +367,6 @@ nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o
obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
# platform driver
obj-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o

View File

@ -26,13 +26,167 @@
#include <core/client.h>
#include <core/handle.h>
#include <core/option.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <nvif/unpack.h>
#include <nvif/event.h>
#include <engine/device.h>
struct nvkm_client_notify {
struct nouveau_client *client;
struct nvkm_notify n;
u8 version;
u8 size;
union {
struct nvif_notify_rep_v0 v0;
} rep;
};
static int
nvkm_client_notify(struct nvkm_notify *n)
{
struct nvkm_client_notify *notify = container_of(n, typeof(*notify), n);
struct nouveau_client *client = notify->client;
return client->ntfy(&notify->rep, notify->size, n->data, n->size);
}
int
nvkm_client_notify_put(struct nouveau_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_put(&client->notify[index]->n);
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_get(struct nouveau_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_get(&client->notify[index]->n);
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_del(struct nouveau_client *client, int index)
{
if (index < ARRAY_SIZE(client->notify)) {
if (client->notify[index]) {
nvkm_notify_fini(&client->notify[index]->n);
kfree(client->notify[index]);
client->notify[index] = NULL;
return 0;
}
}
return -ENOENT;
}
int
nvkm_client_notify_new(struct nouveau_client *client,
struct nvkm_event *event, void *data, u32 size)
{
struct nvkm_client_notify *notify;
union {
struct nvif_notify_req_v0 v0;
} *req = data;
u8 index, reply;
int ret;
for (index = 0; index < ARRAY_SIZE(client->notify); index++) {
if (!client->notify[index])
break;
}
if (index == ARRAY_SIZE(client->notify))
return -ENOSPC;
notify = kzalloc(sizeof(*notify), GFP_KERNEL);
if (!notify)
return -ENOMEM;
nv_ioctl(client, "notify new size %d\n", size);
if (nvif_unpack(req->v0, 0, 0, true)) {
nv_ioctl(client, "notify new vers %d reply %d route %02x "
"token %llx\n", req->v0.version,
req->v0.reply, req->v0.route, req->v0.token);
notify->version = req->v0.version;
notify->size = sizeof(notify->rep.v0);
notify->rep.v0.version = req->v0.version;
notify->rep.v0.route = req->v0.route;
notify->rep.v0.token = req->v0.token;
reply = req->v0.reply;
}
if (ret == 0) {
ret = nvkm_notify_init(event, nvkm_client_notify, false,
data, size, reply, &notify->n);
if (ret == 0) {
client->notify[index] = notify;
notify->client = client;
return 0;
}
}
kfree(notify);
return 0;
}
static int
nouveau_client_devlist(struct nouveau_object *object, void *data, u32 size)
{
union {
struct nv_client_devlist_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "client devlist size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "client devlist vers %d count %d\n",
args->v0.version, args->v0.count);
if (size == sizeof(args->v0.device[0]) * args->v0.count) {
ret = nouveau_device_list(args->v0.device,
args->v0.count);
if (ret >= 0) {
args->v0.count = ret;
ret = 0;
}
} else {
ret = -EINVAL;
}
}
return ret;
}
static int
nouveau_client_mthd(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
{
switch (mthd) {
case NV_CLIENT_DEVLIST:
return nouveau_client_devlist(object, data, size);
default:
break;
}
return -EINVAL;
}
static void
nouveau_client_dtor(struct nouveau_object *object)
{
struct nouveau_client *client = (void *)object;
int i;
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_del(client, i);
nouveau_object_ref(NULL, &client->device);
nouveau_handle_destroy(client->root);
nouveau_namedb_destroy(&client->base);
@ -42,6 +196,7 @@ static struct nouveau_oclass
nouveau_client_oclass = {
.ofuncs = &(struct nouveau_ofuncs) {
.dtor = nouveau_client_dtor,
.mthd = nouveau_client_mthd,
},
};
@ -93,9 +248,12 @@ int
nouveau_client_fini(struct nouveau_client *client, bool suspend)
{
const char *name[2] = { "fini", "suspend" };
int ret;
int ret, i;
nv_debug(client, "%s running\n", name[suspend]);
nv_debug(client, "%s notify\n", name[suspend]);
for (i = 0; i < ARRAY_SIZE(client->notify); i++)
nvkm_client_notify_put(client, i);
nv_debug(client, "%s object\n", name[suspend]);
ret = nouveau_handle_fini(client->root, suspend);
nv_debug(client, "%s completed with %d\n", name[suspend], ret);
return ret;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2013 Red Hat Inc.
* Copyright 2013-2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -24,173 +24,77 @@
#include <core/event.h>
void
nouveau_event_put(struct nouveau_eventh *handler)
nvkm_event_put(struct nvkm_event *event, u32 types, int index)
{
struct nouveau_event *event = handler->event;
unsigned long flags;
u32 m, t;
if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags))
return;
spin_lock_irqsave(&event->refs_lock, flags);
for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
if (!--event->refs[handler->index * event->types_nr + t]) {
if (event->disable)
event->disable(event, 1 << t, handler->index);
BUG_ON(!spin_is_locked(&event->refs_lock));
while (types) {
int type = __ffs(types); types &= ~(1 << type);
if (--event->refs[index * event->types_nr + type] == 0) {
if (event->func->fini)
event->func->fini(event, 1 << type, index);
}
}
spin_unlock_irqrestore(&event->refs_lock, flags);
}
void
nouveau_event_get(struct nouveau_eventh *handler)
nvkm_event_get(struct nvkm_event *event, u32 types, int index)
{
struct nouveau_event *event = handler->event;
unsigned long flags;
u32 m, t;
if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags))
return;
spin_lock_irqsave(&event->refs_lock, flags);
for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) {
if (!event->refs[handler->index * event->types_nr + t]++) {
if (event->enable)
event->enable(event, 1 << t, handler->index);
BUG_ON(!spin_is_locked(&event->refs_lock));
while (types) {
int type = __ffs(types); types &= ~(1 << type);
if (++event->refs[index * event->types_nr + type] == 1) {
if (event->func->init)
event->func->init(event, 1 << type, index);
}
}
spin_unlock_irqrestore(&event->refs_lock, flags);
}
static void
nouveau_event_fini(struct nouveau_eventh *handler)
{
struct nouveau_event *event = handler->event;
unsigned long flags;
nouveau_event_put(handler);
spin_lock_irqsave(&event->list_lock, flags);
list_del(&handler->head);
spin_unlock_irqrestore(&event->list_lock, flags);
}
static int
nouveau_event_init(struct nouveau_event *event, u32 types, int index,
int (*func)(void *, u32, int), void *priv,
struct nouveau_eventh *handler)
{
unsigned long flags;
if (types & ~((1 << event->types_nr) - 1))
return -EINVAL;
if (index >= event->index_nr)
return -EINVAL;
handler->event = event;
handler->flags = 0;
handler->types = types;
handler->index = index;
handler->func = func;
handler->priv = priv;
spin_lock_irqsave(&event->list_lock, flags);
list_add_tail(&handler->head, &event->list[index]);
spin_unlock_irqrestore(&event->list_lock, flags);
return 0;
}
int
nouveau_event_new(struct nouveau_event *event, u32 types, int index,
int (*func)(void *, u32, int), void *priv,
struct nouveau_eventh **phandler)
{
struct nouveau_eventh *handler;
int ret = -ENOMEM;
if (event->check) {
ret = event->check(event, types, index);
if (ret)
return ret;
}
handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL);
if (handler) {
ret = nouveau_event_init(event, types, index, func, priv, handler);
if (ret)
kfree(handler);
}
return ret;
}
void
nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref)
nvkm_event_send(struct nvkm_event *event, u32 types, int index,
void *data, u32 size)
{
BUG_ON(handler != NULL);
if (*ref) {
nouveau_event_fini(*ref);
kfree(*ref);
}
*ref = handler;
}
void
nouveau_event_trigger(struct nouveau_event *event, u32 types, int index)
{
struct nouveau_eventh *handler;
struct nvkm_notify *notify;
unsigned long flags;
if (WARN_ON(index >= event->index_nr))
if (!event->refs || WARN_ON(index >= event->index_nr))
return;
spin_lock_irqsave(&event->list_lock, flags);
list_for_each_entry(handler, &event->list[index], head) {
if (!test_bit(NVKM_EVENT_ENABLE, &handler->flags))
continue;
if (!(handler->types & types))
continue;
if (handler->func(handler->priv, handler->types & types, index)
!= NVKM_EVENT_DROP)
continue;
nouveau_event_put(handler);
list_for_each_entry(notify, &event->list, head) {
if (notify->index == index && (notify->types & types)) {
if (event->func->send) {
event->func->send(data, size, notify);
continue;
}
nvkm_notify_send(notify, data, size);
}
}
spin_unlock_irqrestore(&event->list_lock, flags);
}
void
nouveau_event_destroy(struct nouveau_event **pevent)
nvkm_event_fini(struct nvkm_event *event)
{
struct nouveau_event *event = *pevent;
if (event) {
kfree(event);
*pevent = NULL;
if (event->refs) {
kfree(event->refs);
event->refs = NULL;
}
}
int
nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **pevent)
nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr,
struct nvkm_event *event)
{
struct nouveau_event *event;
int i;
event = *pevent = kzalloc(sizeof(*event) + (index_nr * types_nr) *
sizeof(event->refs[0]), GFP_KERNEL);
if (!event)
event->refs = kzalloc(sizeof(*event->refs) * index_nr * types_nr,
GFP_KERNEL);
if (!event->refs)
return -ENOMEM;
event->list = kmalloc(sizeof(*event->list) * index_nr, GFP_KERNEL);
if (!event->list) {
kfree(event);
return -ENOMEM;
}
spin_lock_init(&event->list_lock);
spin_lock_init(&event->refs_lock);
for (i = 0; i < index_nr; i++)
INIT_LIST_HEAD(&event->list[i]);
event->func = func;
event->types_nr = types_nr;
event->index_nr = index_nr;
spin_lock_init(&event->refs_lock);
spin_lock_init(&event->list_lock);
INIT_LIST_HEAD(&event->list);
return 0;
}

View File

@ -146,9 +146,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle,
}
hprintk(handle, TRACE, "created\n");
*phandle = handle;
return 0;
}
@ -224,3 +222,116 @@ nouveau_handle_put(struct nouveau_handle *handle)
if (handle)
nouveau_namedb_put(handle);
}
int
nouveau_handle_new(struct nouveau_object *client, u32 _parent, u32 _handle,
u16 _oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nouveau_object *parent = NULL;
struct nouveau_object *engctx = NULL;
struct nouveau_object *object = NULL;
struct nouveau_object *engine;
struct nouveau_oclass *oclass;
struct nouveau_handle *handle;
int ret;
/* lookup parent object and ensure it *is* a parent */
parent = nouveau_handle_ref(client, _parent);
if (!parent) {
nv_error(client, "parent 0x%08x not found\n", _parent);
return -ENOENT;
}
if (!nv_iclass(parent, NV_PARENT_CLASS)) {
nv_error(parent, "cannot have children\n");
ret = -EINVAL;
goto fail_class;
}
/* check that parent supports the requested subclass */
ret = nouveau_parent_sclass(parent, _oclass, &engine, &oclass);
if (ret) {
nv_debug(parent, "illegal class 0x%04x\n", _oclass);
goto fail_class;
}
/* make sure engine init has been completed *before* any objects
* it controls are created - the constructors may depend on
* state calculated at init (ie. default context construction)
*/
if (engine) {
ret = nouveau_object_inc(engine);
if (ret)
goto fail_class;
}
/* if engine requires it, create a context object to insert
* between the parent and its children (eg. PGRAPH context)
*/
if (engine && nv_engine(engine)->cclass) {
ret = nouveau_object_ctor(parent, engine,
nv_engine(engine)->cclass,
data, size, &engctx);
if (ret)
goto fail_engctx;
} else {
nouveau_object_ref(parent, &engctx);
}
/* finally, create new object and bind it to its handle */
ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
*pobject = object;
if (ret)
goto fail_ctor;
ret = nouveau_object_inc(object);
if (ret)
goto fail_init;
ret = nouveau_handle_create(parent, _parent, _handle, object, &handle);
if (ret)
goto fail_handle;
ret = nouveau_handle_init(handle);
if (ret)
nouveau_handle_destroy(handle);
fail_handle:
nouveau_object_dec(object, false);
fail_init:
nouveau_object_ref(NULL, &object);
fail_ctor:
nouveau_object_ref(NULL, &engctx);
fail_engctx:
if (engine)
nouveau_object_dec(engine, false);
fail_class:
nouveau_object_ref(NULL, &parent);
return ret;
}
int
nouveau_handle_del(struct nouveau_object *client, u32 _parent, u32 _handle)
{
struct nouveau_object *parent = NULL;
struct nouveau_object *namedb = NULL;
struct nouveau_handle *handle = NULL;
parent = nouveau_handle_ref(client, _parent);
if (!parent)
return -ENOENT;
namedb = nv_pclass(parent, NV_NAMEDB_CLASS);
if (namedb) {
handle = nouveau_namedb_get(nv_namedb(namedb), _handle);
if (handle) {
nouveau_namedb_put(handle);
nouveau_handle_fini(handle, false);
nouveau_handle_destroy(handle);
}
}
nouveau_object_ref(NULL, &parent);
return handle ? 0 : -EINVAL;
}

View File

@ -0,0 +1,531 @@
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include <core/object.h>
#include <core/parent.h>
#include <core/handle.h>
#include <core/namedb.h>
#include <core/client.h>
#include <core/device.h>
#include <core/ioctl.h>
#include <core/event.h>
#include <nvif/unpack.h>
#include <nvif/ioctl.h>
static int
nvkm_ioctl_nop(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
union {
struct nvif_ioctl_nop none;
} *args = data;
int ret;
nv_ioctl(object, "nop size %d\n", size);
if (nvif_unvers(args->none)) {
nv_ioctl(object, "nop\n");
}
return ret;
}
static int
nvkm_ioctl_sclass(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
union {
struct nvif_ioctl_sclass_v0 v0;
} *args = data;
int ret;
if (!nv_iclass(object, NV_PARENT_CLASS)) {
nv_debug(object, "cannot have children (sclass)\n");
return -ENODEV;
}
nv_ioctl(object, "sclass size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "sclass vers %d count %d\n",
args->v0.version, args->v0.count);
if (size == args->v0.count * sizeof(args->v0.oclass[0])) {
ret = nouveau_parent_lclass(object, args->v0.oclass,
args->v0.count);
if (ret >= 0) {
args->v0.count = ret;
ret = 0;
}
} else {
ret = -EINVAL;
}
}
return ret;
}
static int
nvkm_ioctl_new(struct nouveau_handle *parent, void *data, u32 size)
{
union {
struct nvif_ioctl_new_v0 v0;
} *args = data;
struct nouveau_client *client = nouveau_client(parent->object);
struct nouveau_object *engctx = NULL;
struct nouveau_object *object = NULL;
struct nouveau_object *engine;
struct nouveau_oclass *oclass;
struct nouveau_handle *handle;
u32 _handle, _oclass;
int ret;
nv_ioctl(client, "new size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
_handle = args->v0.handle;
_oclass = args->v0.oclass;
} else
return ret;
nv_ioctl(client, "new vers %d handle %08x class %08x "
"route %02x token %llx\n",
args->v0.version, _handle, _oclass,
args->v0.route, args->v0.token);
if (!nv_iclass(parent->object, NV_PARENT_CLASS)) {
nv_debug(parent->object, "cannot have children (ctor)\n");
ret = -ENODEV;
goto fail_class;
}
/* check that parent supports the requested subclass */
ret = nouveau_parent_sclass(parent->object, _oclass, &engine, &oclass);
if (ret) {
nv_debug(parent->object, "illegal class 0x%04x\n", _oclass);
goto fail_class;
}
/* make sure engine init has been completed *before* any objects
* it controls are created - the constructors may depend on
* state calculated at init (ie. default context construction)
*/
if (engine) {
ret = nouveau_object_inc(engine);
if (ret)
goto fail_class;
}
/* if engine requires it, create a context object to insert
* between the parent and its children (eg. PGRAPH context)
*/
if (engine && nv_engine(engine)->cclass) {
ret = nouveau_object_ctor(parent->object, engine,
nv_engine(engine)->cclass,
data, size, &engctx);
if (ret)
goto fail_engctx;
} else {
nouveau_object_ref(parent->object, &engctx);
}
/* finally, create new object and bind it to its handle */
ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
client->data = object;
if (ret)
goto fail_ctor;
ret = nouveau_object_inc(object);
if (ret)
goto fail_init;
ret = nouveau_handle_create(parent->object, parent->name,
_handle, object, &handle);
if (ret)
goto fail_handle;
ret = nouveau_handle_init(handle);
handle->route = args->v0.route;
handle->token = args->v0.token;
if (ret)
nouveau_handle_destroy(handle);
fail_handle:
nouveau_object_dec(object, false);
fail_init:
nouveau_object_ref(NULL, &object);
fail_ctor:
nouveau_object_ref(NULL, &engctx);
fail_engctx:
if (engine)
nouveau_object_dec(engine, false);
fail_class:
return ret;
}
static int
nvkm_ioctl_del(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
union {
struct nvif_ioctl_del none;
} *args = data;
int ret;
nv_ioctl(object, "delete size %d\n", size);
if (nvif_unvers(args->none)) {
nv_ioctl(object, "delete\n");
nouveau_handle_fini(handle, false);
nouveau_handle_destroy(handle);
}
return ret;
}
static int
nvkm_ioctl_mthd(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
union {
struct nvif_ioctl_mthd_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "mthd size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "mthd vers %d mthd %02x\n",
args->v0.version, args->v0.method);
if (ret = -ENODEV, ofuncs->mthd)
ret = ofuncs->mthd(object, args->v0.method, data, size);
}
return ret;
}
static int
nvkm_ioctl_rd(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
union {
struct nvif_ioctl_rd_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "rd size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "rd vers %d size %d addr %016llx\n",
args->v0.version, args->v0.size, args->v0.addr);
switch (args->v0.size) {
case 1:
if (ret = -ENODEV, ofuncs->rd08) {
args->v0.data = nv_ro08(object, args->v0.addr);
ret = 0;
}
break;
case 2:
if (ret = -ENODEV, ofuncs->rd16) {
args->v0.data = nv_ro16(object, args->v0.addr);
ret = 0;
}
break;
case 4:
if (ret = -ENODEV, ofuncs->rd32) {
args->v0.data = nv_ro32(object, args->v0.addr);
ret = 0;
}
break;
default:
ret = -EINVAL;
break;
}
}
return ret;
}
static int
nvkm_ioctl_wr(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
union {
struct nvif_ioctl_wr_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "wr size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "wr vers %d size %d addr %016llx data %08x\n",
args->v0.version, args->v0.size, args->v0.addr,
args->v0.data);
switch (args->v0.size) {
case 1:
if (ret = -ENODEV, ofuncs->wr08) {
nv_wo08(object, args->v0.addr, args->v0.data);
ret = 0;
}
break;
case 2:
if (ret = -ENODEV, ofuncs->wr16) {
nv_wo16(object, args->v0.addr, args->v0.data);
ret = 0;
}
break;
case 4:
if (ret = -ENODEV, ofuncs->wr32) {
nv_wo32(object, args->v0.addr, args->v0.data);
ret = 0;
}
break;
default:
ret = -EINVAL;
break;
}
}
return ret;
}
static int
nvkm_ioctl_map(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
union {
struct nvif_ioctl_map_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "map size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "map vers %d\n", args->v0.version);
if (ret = -ENODEV, ofuncs->map) {
ret = ofuncs->map(object, &args->v0.handle,
&args->v0.length);
}
}
return ret;
}
static int
nvkm_ioctl_unmap(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_object *object = handle->object;
union {
struct nvif_ioctl_unmap none;
} *args = data;
int ret;
nv_ioctl(object, "unmap size %d\n", size);
if (nvif_unvers(args->none)) {
nv_ioctl(object, "unmap\n");
}
return ret;
}
static int
nvkm_ioctl_ntfy_new(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_client *client = nouveau_client(handle->object);
struct nouveau_object *object = handle->object;
struct nouveau_ofuncs *ofuncs = object->oclass->ofuncs;
union {
struct nvif_ioctl_ntfy_new_v0 v0;
} *args = data;
struct nvkm_event *event;
int ret;
nv_ioctl(object, "ntfy new size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "ntfy new vers %d event %02x\n",
args->v0.version, args->v0.event);
if (ret = -ENODEV, ofuncs->ntfy)
ret = ofuncs->ntfy(object, args->v0.event, &event);
if (ret == 0) {
ret = nvkm_client_notify_new(client, event, data, size);
if (ret >= 0) {
args->v0.index = ret;
ret = 0;
}
}
}
return ret;
}
static int
nvkm_ioctl_ntfy_del(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_client *client = nouveau_client(handle->object);
struct nouveau_object *object = handle->object;
union {
struct nvif_ioctl_ntfy_del_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "ntfy del size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "ntfy del vers %d index %d\n",
args->v0.version, args->v0.index);
ret = nvkm_client_notify_del(client, args->v0.index);
}
return ret;
}
static int
nvkm_ioctl_ntfy_get(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_client *client = nouveau_client(handle->object);
struct nouveau_object *object = handle->object;
union {
struct nvif_ioctl_ntfy_get_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "ntfy get size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "ntfy get vers %d index %d\n",
args->v0.version, args->v0.index);
ret = nvkm_client_notify_get(client, args->v0.index);
}
return ret;
}
static int
nvkm_ioctl_ntfy_put(struct nouveau_handle *handle, void *data, u32 size)
{
struct nouveau_client *client = nouveau_client(handle->object);
struct nouveau_object *object = handle->object;
union {
struct nvif_ioctl_ntfy_put_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "ntfy put size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "ntfy put vers %d index %d\n",
args->v0.version, args->v0.index);
ret = nvkm_client_notify_put(client, args->v0.index);
}
return ret;
}
static struct {
int version;
int (*func)(struct nouveau_handle *, void *, u32);
}
nvkm_ioctl_v0[] = {
{ 0x00, nvkm_ioctl_nop },
{ 0x00, nvkm_ioctl_sclass },
{ 0x00, nvkm_ioctl_new },
{ 0x00, nvkm_ioctl_del },
{ 0x00, nvkm_ioctl_mthd },
{ 0x00, nvkm_ioctl_rd },
{ 0x00, nvkm_ioctl_wr },
{ 0x00, nvkm_ioctl_map },
{ 0x00, nvkm_ioctl_unmap },
{ 0x00, nvkm_ioctl_ntfy_new },
{ 0x00, nvkm_ioctl_ntfy_del },
{ 0x00, nvkm_ioctl_ntfy_get },
{ 0x00, nvkm_ioctl_ntfy_put },
};
static int
nvkm_ioctl_path(struct nouveau_handle *parent, u32 type, u32 nr,
u32 *path, void *data, u32 size,
u8 owner, u8 *route, u64 *token)
{
struct nouveau_handle *handle = parent;
struct nouveau_namedb *namedb;
struct nouveau_object *object;
int ret;
while ((object = parent->object), nr--) {
nv_ioctl(object, "path 0x%08x\n", path[nr]);
if (!nv_iclass(object, NV_PARENT_CLASS)) {
nv_debug(object, "cannot have children (path)\n");
return -EINVAL;
}
if (!(namedb = (void *)nv_pclass(object, NV_NAMEDB_CLASS)) ||
!(handle = nouveau_namedb_get(namedb, path[nr]))) {
nv_debug(object, "handle 0x%08x not found\n", path[nr]);
return -ENOENT;
}
nouveau_namedb_put(handle);
parent = handle;
}
if (owner != NVIF_IOCTL_V0_OWNER_ANY &&
owner != handle->route) {
nv_ioctl(object, "object route != owner\n");
return -EACCES;
}
*route = handle->route;
*token = handle->token;
if (ret = -EINVAL, type < ARRAY_SIZE(nvkm_ioctl_v0)) {
if (nvkm_ioctl_v0[type].version == 0) {
ret = nvkm_ioctl_v0[type].func(handle, data, size);
}
}
return ret;
}
int
nvkm_ioctl(struct nouveau_client *client, bool supervisor,
void *data, u32 size, void **hack)
{
union {
struct nvif_ioctl_v0 v0;
} *args = data;
int ret;
client->super = supervisor;
nv_ioctl(client, "size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(client, "vers %d type %02x path %d owner %02x\n",
args->v0.version, args->v0.type, args->v0.path_nr,
args->v0.owner);
ret = nvkm_ioctl_path(client->root, args->v0.type,
args->v0.path_nr, args->v0.path,
data, size, args->v0.owner,
&args->v0.route, &args->v0.token);
}
nv_ioctl(client, "return %d\n", ret);
if (hack) {
*hack = client->data;
client->data = NULL;
}
client->super = false;
return ret;
}

View File

@ -0,0 +1,167 @@
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include <core/client.h>
#include <core/event.h>
#include <core/notify.h>
#include <nvif/unpack.h>
#include <nvif/event.h>
static inline void
nvkm_notify_put_locked(struct nvkm_notify *notify)
{
if (notify->block++ == 0)
nvkm_event_put(notify->event, notify->types, notify->index);
}
void
nvkm_notify_put(struct nvkm_notify *notify)
{
struct nvkm_event *event = notify->event;
unsigned long flags;
if (likely(event) &&
test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
spin_lock_irqsave(&event->refs_lock, flags);
nvkm_notify_put_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
if (test_bit(NVKM_NOTIFY_WORK, &notify->flags))
flush_work(&notify->work);
}
}
static inline void
nvkm_notify_get_locked(struct nvkm_notify *notify)
{
if (--notify->block == 0)
nvkm_event_get(notify->event, notify->types, notify->index);
}
void
nvkm_notify_get(struct nvkm_notify *notify)
{
struct nvkm_event *event = notify->event;
unsigned long flags;
if (likely(event) &&
!test_and_set_bit(NVKM_NOTIFY_USER, &notify->flags)) {
spin_lock_irqsave(&event->refs_lock, flags);
nvkm_notify_get_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
}
}
static inline void
nvkm_notify_func(struct nvkm_notify *notify)
{
struct nvkm_event *event = notify->event;
int ret = notify->func(notify);
unsigned long flags;
if ((ret == NVKM_NOTIFY_KEEP) ||
!test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
spin_lock_irqsave(&event->refs_lock, flags);
nvkm_notify_get_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
}
}
static void
nvkm_notify_work(struct work_struct *work)
{
struct nvkm_notify *notify = container_of(work, typeof(*notify), work);
nvkm_notify_func(notify);
}
void
nvkm_notify_send(struct nvkm_notify *notify, void *data, u32 size)
{
struct nvkm_event *event = notify->event;
unsigned long flags;
BUG_ON(!spin_is_locked(&event->list_lock));
BUG_ON(size != notify->size);
spin_lock_irqsave(&event->refs_lock, flags);
if (notify->block) {
spin_unlock_irqrestore(&event->refs_lock, flags);
return;
}
nvkm_notify_put_locked(notify);
spin_unlock_irqrestore(&event->refs_lock, flags);
if (test_bit(NVKM_NOTIFY_WORK, &notify->flags)) {
memcpy((void *)notify->data, data, size);
schedule_work(&notify->work);
} else {
notify->data = data;
nvkm_notify_func(notify);
notify->data = NULL;
}
}
void
nvkm_notify_fini(struct nvkm_notify *notify)
{
unsigned long flags;
if (notify->event) {
nvkm_notify_put(notify);
spin_lock_irqsave(&notify->event->list_lock, flags);
list_del(&notify->head);
spin_unlock_irqrestore(&notify->event->list_lock, flags);
kfree((void *)notify->data);
notify->event = NULL;
}
}
int
nvkm_notify_init(struct nvkm_event *event, int (*func)(struct nvkm_notify *),
bool work, void *data, u32 size, u32 reply,
struct nvkm_notify *notify)
{
unsigned long flags;
int ret = -ENODEV;
if ((notify->event = event), event->refs) {
ret = event->func->ctor(data, size, notify);
if (ret == 0 && (ret = -EINVAL, notify->size == reply)) {
notify->flags = 0;
notify->block = 1;
notify->func = func;
notify->data = NULL;
if (ret = 0, work) {
INIT_WORK(&notify->work, nvkm_notify_work);
set_bit(NVKM_NOTIFY_WORK, &notify->flags);
notify->data = kmalloc(reply, GFP_KERNEL);
if (!notify->data)
ret = -ENOMEM;
}
}
if (ret == 0) {
spin_lock_irqsave(&event->list_lock, flags);
list_add_tail(&notify->head, &event->list);
spin_unlock_irqrestore(&event->list_lock, flags);
}
}
if (ret)
notify->event = NULL;
return ret;
}

View File

@ -23,9 +23,6 @@
*/
#include <core/object.h>
#include <core/parent.h>
#include <core/namedb.h>
#include <core/handle.h>
#include <core/engine.h>
#ifdef NOUVEAU_OBJECT_MAGIC
@ -61,21 +58,15 @@ nouveau_object_create_(struct nouveau_object *parent,
return 0;
}
static int
int
_nouveau_object_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nouveau_object *object;
int ret;
ret = nouveau_object_create(parent, engine, oclass, 0, &object);
*pobject = nv_object(object);
if (ret)
return ret;
return 0;
if (size != 0)
return -ENOSYS;
return nouveau_object_create(parent, engine, oclass, 0, pobject);
}
void
@ -91,42 +82,24 @@ nouveau_object_destroy(struct nouveau_object *object)
kfree(object);
}
static void
_nouveau_object_dtor(struct nouveau_object *object)
{
nouveau_object_destroy(object);
}
int
nouveau_object_init(struct nouveau_object *object)
{
return 0;
}
static int
_nouveau_object_init(struct nouveau_object *object)
{
return nouveau_object_init(object);
}
int
nouveau_object_fini(struct nouveau_object *object, bool suspend)
{
return 0;
}
static int
_nouveau_object_fini(struct nouveau_object *object, bool suspend)
{
return nouveau_object_fini(object, suspend);
}
struct nouveau_ofuncs
nouveau_object_ofuncs = {
.ctor = _nouveau_object_ctor,
.dtor = _nouveau_object_dtor,
.init = _nouveau_object_init,
.fini = _nouveau_object_fini,
.dtor = nouveau_object_destroy,
.init = nouveau_object_init,
.fini = nouveau_object_fini,
};
int
@ -188,119 +161,6 @@ nouveau_object_ref(struct nouveau_object *obj, struct nouveau_object **ref)
*ref = obj;
}
int
nouveau_object_new(struct nouveau_object *client, u32 _parent, u32 _handle,
u16 _oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nouveau_object *parent = NULL;
struct nouveau_object *engctx = NULL;
struct nouveau_object *object = NULL;
struct nouveau_object *engine;
struct nouveau_oclass *oclass;
struct nouveau_handle *handle;
int ret;
/* lookup parent object and ensure it *is* a parent */
parent = nouveau_handle_ref(client, _parent);
if (!parent) {
nv_error(client, "parent 0x%08x not found\n", _parent);
return -ENOENT;
}
if (!nv_iclass(parent, NV_PARENT_CLASS)) {
nv_error(parent, "cannot have children\n");
ret = -EINVAL;
goto fail_class;
}
/* check that parent supports the requested subclass */
ret = nouveau_parent_sclass(parent, _oclass, &engine, &oclass);
if (ret) {
nv_debug(parent, "illegal class 0x%04x\n", _oclass);
goto fail_class;
}
/* make sure engine init has been completed *before* any objects
* it controls are created - the constructors may depend on
* state calculated at init (ie. default context construction)
*/
if (engine) {
ret = nouveau_object_inc(engine);
if (ret)
goto fail_class;
}
/* if engine requires it, create a context object to insert
* between the parent and its children (eg. PGRAPH context)
*/
if (engine && nv_engine(engine)->cclass) {
ret = nouveau_object_ctor(parent, engine,
nv_engine(engine)->cclass,
data, size, &engctx);
if (ret)
goto fail_engctx;
} else {
nouveau_object_ref(parent, &engctx);
}
/* finally, create new object and bind it to its handle */
ret = nouveau_object_ctor(engctx, engine, oclass, data, size, &object);
*pobject = object;
if (ret)
goto fail_ctor;
ret = nouveau_object_inc(object);
if (ret)
goto fail_init;
ret = nouveau_handle_create(parent, _parent, _handle, object, &handle);
if (ret)
goto fail_handle;
ret = nouveau_handle_init(handle);
if (ret)
nouveau_handle_destroy(handle);
fail_handle:
nouveau_object_dec(object, false);
fail_init:
nouveau_object_ref(NULL, &object);
fail_ctor:
nouveau_object_ref(NULL, &engctx);
fail_engctx:
if (engine)
nouveau_object_dec(engine, false);
fail_class:
nouveau_object_ref(NULL, &parent);
return ret;
}
int
nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
{
struct nouveau_object *parent = NULL;
struct nouveau_object *namedb = NULL;
struct nouveau_handle *handle = NULL;
parent = nouveau_handle_ref(client, _parent);
if (!parent)
return -ENOENT;
namedb = nv_pclass(parent, NV_NAMEDB_CLASS);
if (namedb) {
handle = nouveau_namedb_get(nv_namedb(namedb), _handle);
if (handle) {
nouveau_namedb_put(handle);
nouveau_handle_fini(handle, false);
nouveau_handle_destroy(handle);
}
}
nouveau_object_ref(NULL, &parent);
return handle ? 0 : -EINVAL;
}
int
nouveau_object_inc(struct nouveau_object *object)
{

View File

@ -74,6 +74,39 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,
return -EINVAL;
}
int
nouveau_parent_lclass(struct nouveau_object *parent, u32 *lclass, int size)
{
struct nouveau_sclass *sclass;
struct nouveau_engine *engine;
struct nouveau_oclass *oclass;
int nr = -1, i;
u64 mask;
sclass = nv_parent(parent)->sclass;
while (sclass) {
if (++nr < size)
lclass[nr] = sclass->oclass->handle;
sclass = sclass->sclass;
}
mask = nv_parent(parent)->engine;
while (i = __ffs64(mask), mask) {
engine = nouveau_engine(parent, i);
if (engine && (oclass = engine->sclass)) {
while (oclass->ofuncs) {
if (++nr < size)
lclass[nr] = oclass->handle;
oclass++;
}
}
mask &= ~(1ULL << i);
}
return nr + 1;
}
int
nouveau_parent_create_(struct nouveau_object *parent,
struct nouveau_object *engine,

View File

@ -30,7 +30,6 @@
#include <subdev/vm.h>
#include <core/client.h>
#include <core/class.h>
#include <core/enum.h>

View File

@ -26,9 +26,7 @@
#include <engine/fifo.h>
#include <engine/copy.h>
#include <core/class.h>
#include <core/enum.h>
#include <core/class.h>
#include <core/enum.h>
#include "fuc/nvc0.fuc.h"

View File

@ -24,7 +24,6 @@
#include <core/os.h>
#include <core/enum.h>
#include <core/class.h>
#include <core/engctx.h>
#include <engine/copy.h>

View File

@ -25,7 +25,6 @@
#include <core/client.h>
#include <core/os.h>
#include <core/enum.h>
#include <core/class.h>
#include <core/engctx.h>
#include <core/gpuobj.h>

View File

@ -25,7 +25,6 @@
#include <core/client.h>
#include <core/os.h>
#include <core/enum.h>
#include <core/class.h>
#include <core/engctx.h>
#include <subdev/timer.h>

View File

@ -0,0 +1,59 @@
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "acpi.h"
#ifdef CONFIG_ACPI
static int
nvkm_acpi_ntfy(struct notifier_block *nb, unsigned long val, void *data)
{
struct nouveau_device *device =
container_of(nb, typeof(*device), acpi.nb);
struct acpi_bus_event *info = data;
if (!strcmp(info->device_class, "ac_adapter"))
nvkm_event_send(&device->event, 1, 0, NULL, 0);
return NOTIFY_DONE;
}
#endif
int
nvkm_acpi_fini(struct nouveau_device *device, bool suspend)
{
#ifdef CONFIG_ACPI
unregister_acpi_notifier(&device->acpi.nb);
#endif
return 0;
}
int
nvkm_acpi_init(struct nouveau_device *device)
{
#ifdef CONFIG_ACPI
device->acpi.nb.notifier_call = nvkm_acpi_ntfy;
register_acpi_notifier(&device->acpi.nb);
#endif
return 0;
}

View File

@ -0,0 +1,9 @@
#ifndef __NVKM_DEVICE_ACPI_H__
#define __NVKM_DEVICE_ACPI_H__
#include <engine/device.h>
int nvkm_acpi_init(struct nouveau_device *);
int nvkm_acpi_fini(struct nouveau_device *, bool);
#endif

View File

@ -26,10 +26,14 @@
#include <core/device.h>
#include <core/client.h>
#include <core/option.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/class.h>
#include <subdev/fb.h>
#include <subdev/instmem.h>
#include "priv.h"
#include "acpi.h"
static DEFINE_MUTEX(nv_devices_mutex);
static LIST_HEAD(nv_devices);
@ -49,74 +53,258 @@ nouveau_device_find(u64 name)
return match;
}
int
nouveau_device_list(u64 *name, int size)
{
struct nouveau_device *device;
int nr = 0;
mutex_lock(&nv_devices_mutex);
list_for_each_entry(device, &nv_devices, head) {
if (nr++ < size)
name[nr - 1] = device->handle;
}
mutex_unlock(&nv_devices_mutex);
return nr;
}
/******************************************************************************
* nouveau_devobj (0x0080): class implementation
*****************************************************************************/
struct nouveau_devobj {
struct nouveau_parent base;
struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
};
static int
nouveau_devobj_info(struct nouveau_object *object, void *data, u32 size)
{
struct nouveau_device *device = nv_device(object);
struct nouveau_fb *pfb = nouveau_fb(device);
struct nouveau_instmem *imem = nouveau_instmem(device);
union {
struct nv_device_info_v0 v0;
} *args = data;
int ret;
nv_ioctl(object, "device info size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "device info vers %d\n", args->v0.version);
} else
return ret;
switch (device->chipset) {
case 0x01a:
case 0x01f:
case 0x04c:
case 0x04e:
case 0x063:
case 0x067:
case 0x068:
case 0x0aa:
case 0x0ac:
case 0x0af:
args->v0.platform = NV_DEVICE_INFO_V0_IGP;
break;
default:
if (device->pdev) {
if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP))
args->v0.platform = NV_DEVICE_INFO_V0_AGP;
else
if (pci_is_pcie(device->pdev))
args->v0.platform = NV_DEVICE_INFO_V0_PCIE;
else
args->v0.platform = NV_DEVICE_INFO_V0_PCI;
} else {
args->v0.platform = NV_DEVICE_INFO_V0_SOC;
}
break;
}
switch (device->card_type) {
case NV_04: args->v0.family = NV_DEVICE_INFO_V0_TNT; break;
case NV_10:
case NV_11: args->v0.family = NV_DEVICE_INFO_V0_CELSIUS; break;
case NV_20: args->v0.family = NV_DEVICE_INFO_V0_KELVIN; break;
case NV_30: args->v0.family = NV_DEVICE_INFO_V0_RANKINE; break;
case NV_40: args->v0.family = NV_DEVICE_INFO_V0_CURIE; break;
case NV_50: args->v0.family = NV_DEVICE_INFO_V0_TESLA; break;
case NV_C0: args->v0.family = NV_DEVICE_INFO_V0_FERMI; break;
case NV_E0: args->v0.family = NV_DEVICE_INFO_V0_KEPLER; break;
case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break;
default:
args->v0.family = 0;
break;
}
args->v0.chipset = device->chipset;
args->v0.revision = device->chipset >= 0x10 ? nv_rd32(device, 0) : 0x00;
if (pfb) args->v0.ram_size = args->v0.ram_user = pfb->ram->size;
else args->v0.ram_size = args->v0.ram_user = 0;
if (imem) args->v0.ram_user = args->v0.ram_user - imem->reserved;
return 0;
}
static int
nouveau_devobj_mthd(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
{
switch (mthd) {
case NV_DEVICE_V0_INFO:
return nouveau_devobj_info(object, data, size);
default:
break;
}
return -EINVAL;
}
static u8
nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
{
return nv_rd08(object->engine, addr);
}
static u16
nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
{
return nv_rd16(object->engine, addr);
}
static u32
nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
{
return nv_rd32(object->engine, addr);
}
static void
nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
{
nv_wr08(object->engine, addr, data);
}
static void
nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
{
nv_wr16(object->engine, addr, data);
}
static void
nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
{
nv_wr32(object->engine, addr, data);
}
static int
nouveau_devobj_map(struct nouveau_object *object, u64 *addr, u32 *size)
{
struct nouveau_device *device = nv_device(object);
*addr = nv_device_resource_start(device, 0);
*size = nv_device_resource_len(device, 0);
return 0;
}
static const u64 disable_map[] = {
[NVDEV_SUBDEV_VBIOS] = NV_DEVICE_DISABLE_VBIOS,
[NVDEV_SUBDEV_DEVINIT] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_GPIO] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_I2C] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_MXM] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_BUS] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_LTCG] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_IBUS] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_VM] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_BAR] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_VOLT] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_THERM] = NV_DEVICE_DISABLE_CORE,
[NVDEV_SUBDEV_PWR] = NV_DEVICE_DISABLE_CORE,
[NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_DISABLE_CORE,
[NVDEV_ENGINE_PERFMON] = NV_DEVICE_DISABLE_CORE,
[NVDEV_ENGINE_FIFO] = NV_DEVICE_DISABLE_FIFO,
[NVDEV_ENGINE_SW] = NV_DEVICE_DISABLE_FIFO,
[NVDEV_ENGINE_GR] = NV_DEVICE_DISABLE_GRAPH,
[NVDEV_ENGINE_MPEG] = NV_DEVICE_DISABLE_MPEG,
[NVDEV_ENGINE_ME] = NV_DEVICE_DISABLE_ME,
[NVDEV_ENGINE_VP] = NV_DEVICE_DISABLE_VP,
[NVDEV_ENGINE_CRYPT] = NV_DEVICE_DISABLE_CRYPT,
[NVDEV_ENGINE_BSP] = NV_DEVICE_DISABLE_BSP,
[NVDEV_ENGINE_PPP] = NV_DEVICE_DISABLE_PPP,
[NVDEV_ENGINE_COPY0] = NV_DEVICE_DISABLE_COPY0,
[NVDEV_ENGINE_COPY1] = NV_DEVICE_DISABLE_COPY1,
[NVDEV_ENGINE_VIC] = NV_DEVICE_DISABLE_VIC,
[NVDEV_ENGINE_VENC] = NV_DEVICE_DISABLE_VENC,
[NVDEV_ENGINE_DISP] = NV_DEVICE_DISABLE_DISP,
[NVDEV_SUBDEV_VBIOS] = NV_DEVICE_V0_DISABLE_VBIOS,
[NVDEV_SUBDEV_DEVINIT] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_GPIO] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_I2C] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_CLOCK] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_MXM] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_MC] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_BUS] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_TIMER] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_FB] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_LTC] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_IBUS] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_INSTMEM] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_VM] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_BAR] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_VOLT] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_THERM] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_SUBDEV_PWR] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_ENGINE_DMAOBJ] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_ENGINE_PERFMON] = NV_DEVICE_V0_DISABLE_CORE,
[NVDEV_ENGINE_FIFO] = NV_DEVICE_V0_DISABLE_FIFO,
[NVDEV_ENGINE_SW] = NV_DEVICE_V0_DISABLE_FIFO,
[NVDEV_ENGINE_GR] = NV_DEVICE_V0_DISABLE_GRAPH,
[NVDEV_ENGINE_MPEG] = NV_DEVICE_V0_DISABLE_MPEG,
[NVDEV_ENGINE_ME] = NV_DEVICE_V0_DISABLE_ME,
[NVDEV_ENGINE_VP] = NV_DEVICE_V0_DISABLE_VP,
[NVDEV_ENGINE_CRYPT] = NV_DEVICE_V0_DISABLE_CRYPT,
[NVDEV_ENGINE_BSP] = NV_DEVICE_V0_DISABLE_BSP,
[NVDEV_ENGINE_PPP] = NV_DEVICE_V0_DISABLE_PPP,
[NVDEV_ENGINE_COPY0] = NV_DEVICE_V0_DISABLE_COPY0,
[NVDEV_ENGINE_COPY1] = NV_DEVICE_V0_DISABLE_COPY1,
[NVDEV_ENGINE_VIC] = NV_DEVICE_V0_DISABLE_VIC,
[NVDEV_ENGINE_VENC] = NV_DEVICE_V0_DISABLE_VENC,
[NVDEV_ENGINE_DISP] = NV_DEVICE_V0_DISABLE_DISP,
[NVDEV_SUBDEV_NR] = 0,
};
static void
nouveau_devobj_dtor(struct nouveau_object *object)
{
struct nouveau_devobj *devobj = (void *)object;
int i;
for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
nouveau_object_ref(NULL, &devobj->subdev[i]);
nouveau_parent_destroy(&devobj->base);
}
static struct nouveau_oclass
nouveau_devobj_oclass_super = {
.handle = NV_DEVICE,
.ofuncs = &(struct nouveau_ofuncs) {
.dtor = nouveau_devobj_dtor,
.init = _nouveau_parent_init,
.fini = _nouveau_parent_fini,
.mthd = nouveau_devobj_mthd,
.map = nouveau_devobj_map,
.rd08 = nouveau_devobj_rd08,
.rd16 = nouveau_devobj_rd16,
.rd32 = nouveau_devobj_rd32,
.wr08 = nouveau_devobj_wr08,
.wr16 = nouveau_devobj_wr16,
.wr32 = nouveau_devobj_wr32,
}
};
static int
nouveau_devobj_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv_device_v0 v0;
} *args = data;
struct nouveau_client *client = nv_client(parent);
struct nouveau_device *device;
struct nouveau_devobj *devobj;
struct nv_device_class *args = data;
u32 boot0, strap;
u64 disable, mmio_base, mmio_size;
void __iomem *map;
int ret, i, c;
if (size < sizeof(struct nv_device_class))
return -EINVAL;
nv_ioctl(parent, "create device size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create device v%d device %016llx "
"disable %016llx debug0 %016llx\n",
args->v0.version, args->v0.device,
args->v0.disable, args->v0.debug0);
} else
return ret;
/* give priviledged clients register access */
if (client->super)
oclass = &nouveau_devobj_oclass_super;
/* find the device subdev that matches what the client requested */
device = nv_device(client->device);
if (args->device != ~0) {
device = nouveau_device_find(args->device);
if (args->v0.device != ~0) {
device = nouveau_device_find(args->v0.device);
if (!device)
return -ENODEV;
}
@ -135,14 +323,14 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
mmio_size = nv_device_resource_len(device, 0);
/* translate api disable mask into internal mapping */
disable = args->debug0;
disable = args->v0.debug0;
for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
if (args->disable & disable_map[i])
if (args->v0.disable & disable_map[i])
disable |= (1ULL << i);
}
/* identify the chipset, and determine classes of subdev/engines */
if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) &&
if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_IDENTIFY) &&
!device->card_type) {
map = ioremap(mmio_base, 0x102000);
if (map == NULL)
@ -180,8 +368,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
case 0x080:
case 0x090:
case 0x0a0: device->card_type = NV_50; break;
case 0x0c0: device->card_type = NV_C0; break;
case 0x0d0: device->card_type = NV_D0; break;
case 0x0c0:
case 0x0d0: device->card_type = NV_C0; break;
case 0x0e0:
case 0x0f0:
case 0x100: device->card_type = NV_E0; break;
@ -206,8 +394,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
case NV_30: ret = nv30_identify(device); break;
case NV_40: ret = nv40_identify(device); break;
case NV_50: ret = nv50_identify(device); break;
case NV_C0:
case NV_D0: ret = nvc0_identify(device); break;
case NV_C0: ret = nvc0_identify(device); break;
case NV_E0: ret = nve0_identify(device); break;
case GM100: ret = gm100_identify(device); break;
default:
@ -242,7 +429,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
nv_debug(device, "crystal freq: %dKHz\n", device->crystal);
}
if (!(args->disable & NV_DEVICE_DISABLE_MMIO) &&
if (!(args->v0.disable & NV_DEVICE_V0_DISABLE_MMIO) &&
!nv_subdev(device)->mmio) {
nv_subdev(device)->mmio = ioremap(mmio_base, mmio_size);
if (!nv_subdev(device)->mmio) {
@ -298,77 +485,42 @@ nouveau_devobj_ctor(struct nouveau_object *parent,
return 0;
}
static void
nouveau_devobj_dtor(struct nouveau_object *object)
{
struct nouveau_devobj *devobj = (void *)object;
int i;
for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
nouveau_object_ref(NULL, &devobj->subdev[i]);
nouveau_parent_destroy(&devobj->base);
}
static u8
nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
{
return nv_rd08(object->engine, addr);
}
static u16
nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
{
return nv_rd16(object->engine, addr);
}
static u32
nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
{
return nv_rd32(object->engine, addr);
}
static void
nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
{
nv_wr08(object->engine, addr, data);
}
static void
nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
{
nv_wr16(object->engine, addr, data);
}
static void
nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
{
nv_wr32(object->engine, addr, data);
}
static struct nouveau_ofuncs
nouveau_devobj_ofuncs = {
.ctor = nouveau_devobj_ctor,
.dtor = nouveau_devobj_dtor,
.init = _nouveau_parent_init,
.fini = _nouveau_parent_fini,
.rd08 = nouveau_devobj_rd08,
.rd16 = nouveau_devobj_rd16,
.rd32 = nouveau_devobj_rd32,
.wr08 = nouveau_devobj_wr08,
.wr16 = nouveau_devobj_wr16,
.wr32 = nouveau_devobj_wr32,
.mthd = nouveau_devobj_mthd,
};
/******************************************************************************
* nouveau_device: engine functions
*****************************************************************************/
static struct nouveau_oclass
nouveau_device_sclass[] = {
{ 0x0080, &nouveau_devobj_ofuncs },
{}
};
static int
nouveau_device_event_ctor(void *data, u32 size, struct nvkm_notify *notify)
{
if (!WARN_ON(size != 0)) {
notify->size = 0;
notify->types = 1;
notify->index = 0;
return 0;
}
return -EINVAL;
}
static const struct nvkm_event_func
nouveau_device_event_func = {
.ctor = nouveau_device_event_ctor,
};
static int
nouveau_device_fini(struct nouveau_object *object, bool suspend)
{
@ -386,7 +538,7 @@ nouveau_device_fini(struct nouveau_object *object, bool suspend)
}
}
ret = 0;
ret = nvkm_acpi_fini(device, suspend);
fail:
for (; ret && i < NVDEV_SUBDEV_NR; i++) {
if ((subdev = device->subdev[i])) {
@ -407,7 +559,11 @@ nouveau_device_init(struct nouveau_object *object)
{
struct nouveau_device *device = (void *)object;
struct nouveau_object *subdev;
int ret, i;
int ret, i = 0;
ret = nvkm_acpi_init(device);
if (ret)
goto fail;
for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
if ((subdev = device->subdev[i])) {
@ -430,6 +586,8 @@ fail:
}
}
if (ret)
nvkm_acpi_fini(device, false);
return ret;
}
@ -438,6 +596,8 @@ nouveau_device_dtor(struct nouveau_object *object)
{
struct nouveau_device *device = (void *)object;
nvkm_event_fini(&device->event);
mutex_lock(&nv_devices_mutex);
list_del(&device->head);
mutex_unlock(&nv_devices_mutex);
@ -478,31 +638,6 @@ nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
}
}
dma_addr_t
nv_device_map_page(struct nouveau_device *device, struct page *page)
{
dma_addr_t ret;
if (nv_device_is_pci(device)) {
ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
if (pci_dma_mapping_error(device->pdev, ret))
ret = 0;
} else {
ret = page_to_phys(page);
}
return ret;
}
void
nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
{
if (nv_device_is_pci(device))
pci_unmap_page(device->pdev, addr, PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
}
int
nv_device_get_irq(struct nouveau_device *device, bool stall)
{
@ -560,6 +695,9 @@ nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE");
nv_engine(device)->sclass = nouveau_device_sclass;
list_add(&device->head, &nv_devices);
ret = nvkm_event_init(&nouveau_device_event_func, 1, 1,
&device->event);
done:
mutex_unlock(&nv_devices_mutex);
return ret;

View File

@ -22,55 +22,82 @@
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include <core/client.h>
#include <core/object.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <nvif/ioctl.h>
#include <subdev/clock.h>
#include "priv.h"
static int
nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
nouveau_control_mthd_pstate_info(struct nouveau_object *object,
void *data, u32 size)
{
union {
struct nvif_control_pstate_info_v0 v0;
} *args = data;
struct nouveau_clock *clk = nouveau_clock(object);
struct nv_control_pstate_info *args = data;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(object, "control pstate info size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "control pstate info vers %d\n",
args->v0.version);
} else
return ret;
if (clk) {
args->count = clk->state_nr;
args->ustate = clk->ustate;
args->pstate = clk->pstate;
args->v0.count = clk->state_nr;
args->v0.ustate_ac = clk->ustate_ac;
args->v0.ustate_dc = clk->ustate_dc;
args->v0.pwrsrc = clk->pwrsrc;
args->v0.pstate = clk->pstate;
} else {
args->count = 0;
args->ustate = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE;
args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN;
args->v0.count = 0;
args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
args->v0.pwrsrc = -ENOSYS;
args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN;
}
return 0;
}
static int
nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
nouveau_control_mthd_pstate_attr(struct nouveau_object *object,
void *data, u32 size)
{
union {
struct nvif_control_pstate_attr_v0 v0;
} *args = data;
struct nouveau_clock *clk = nouveau_clock(object);
struct nv_control_pstate_attr *args = data;
struct nouveau_clocks *domain;
struct nouveau_pstate *pstate;
struct nouveau_cstate *cstate;
int i = 0, j = -1;
u32 lo, hi;
int ret;
if ((size < sizeof(*args)) || !clk ||
(args->state >= 0 && args->state >= clk->state_nr))
return -EINVAL;
nv_ioctl(object, "control pstate attr size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "control pstate attr vers %d state %d "
"index %d\n",
args->v0.version, args->v0.state, args->v0.index);
if (!clk)
return -ENODEV;
if (args->v0.state < NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT)
return -EINVAL;
if (args->v0.state >= clk->state_nr)
return -EINVAL;
} else
return ret;
domain = clk->domains;
while (domain->name != nv_clk_src_max) {
if (domain->mname && ++j == args->index)
if (domain->mname && ++j == args->v0.index)
break;
domain++;
}
@ -78,9 +105,9 @@ nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
if (domain->name == nv_clk_src_max)
return -EINVAL;
if (args->state != NV_CONTROL_PSTATE_ATTR_STATE_CURRENT) {
if (args->v0.state != NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT) {
list_for_each_entry(pstate, &clk->states, head) {
if (i++ == args->state)
if (i++ == args->v0.state)
break;
}
@ -91,21 +118,21 @@ nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
hi = max(hi, cstate->domain[domain->name]);
}
args->state = pstate->pstate;
args->v0.state = pstate->pstate;
} else {
lo = max(clk->read(clk, domain->name), 0);
hi = lo;
}
snprintf(args->name, sizeof(args->name), "%s", domain->mname);
snprintf(args->unit, sizeof(args->unit), "MHz");
args->min = lo / domain->mdiv;
args->max = hi / domain->mdiv;
snprintf(args->v0.name, sizeof(args->v0.name), "%s", domain->mname);
snprintf(args->v0.unit, sizeof(args->v0.unit), "MHz");
args->v0.min = lo / domain->mdiv;
args->v0.max = hi / domain->mdiv;
args->index = 0;
args->v0.index = 0;
while ((++domain)->name != nv_clk_src_max) {
if (domain->mname) {
args->index = ++j;
args->v0.index = ++j;
break;
}
}
@ -114,31 +141,65 @@ nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd,
}
static int
nouveau_control_mthd_pstate_user(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
nouveau_control_mthd_pstate_user(struct nouveau_object *object,
void *data, u32 size)
{
union {
struct nvif_control_pstate_user_v0 v0;
} *args = data;
struct nouveau_clock *clk = nouveau_clock(object);
struct nv_control_pstate_user *args = data;
int ret;
if (size < sizeof(*args) || !clk)
return -EINVAL;
nv_ioctl(object, "control pstate user size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "control pstate user vers %d ustate %d "
"pwrsrc %d\n", args->v0.version,
args->v0.ustate, args->v0.pwrsrc);
if (!clk)
return -ENODEV;
} else
return ret;
return nouveau_clock_ustate(clk, args->state);
if (args->v0.pwrsrc >= 0) {
ret |= nouveau_clock_ustate(clk, args->v0.ustate, args->v0.pwrsrc);
} else {
ret |= nouveau_clock_ustate(clk, args->v0.ustate, 0);
ret |= nouveau_clock_ustate(clk, args->v0.ustate, 1);
}
return ret;
}
static int
nouveau_control_mthd(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
{
switch (mthd) {
case NVIF_CONTROL_PSTATE_INFO:
return nouveau_control_mthd_pstate_info(object, data, size);
case NVIF_CONTROL_PSTATE_ATTR:
return nouveau_control_mthd_pstate_attr(object, data, size);
case NVIF_CONTROL_PSTATE_USER:
return nouveau_control_mthd_pstate_user(object, data, size);
default:
break;
}
return -EINVAL;
}
static struct nouveau_ofuncs
nouveau_control_ofuncs = {
.ctor = _nouveau_object_ctor,
.dtor = nouveau_object_destroy,
.init = nouveau_object_init,
.fini = nouveau_object_fini,
.mthd = nouveau_control_mthd,
};
struct nouveau_oclass
nouveau_control_oclass[] = {
{ .handle = NV_CONTROL_CLASS,
.ofuncs = &nouveau_object_ofuncs,
.omthds = (struct nouveau_omthds[]) {
{ NV_CONTROL_PSTATE_INFO,
NV_CONTROL_PSTATE_INFO, nouveau_control_mthd_pstate_info },
{ NV_CONTROL_PSTATE_ATTR,
NV_CONTROL_PSTATE_ATTR, nouveau_control_mthd_pstate_attr },
{ NV_CONTROL_PSTATE_USER,
NV_CONTROL_PSTATE_USER, nouveau_control_mthd_pstate_user },
{},
},
{ .handle = NVIF_IOCTL_NEW_V0_CONTROL,
.ofuncs = &nouveau_control_ofuncs
},
{}
};

View File

@ -33,7 +33,7 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
#include <subdev/ltcg.h>
#include <subdev/ltc.h>
#include <subdev/ibus.h>
#include <subdev/instmem.h>
#include <subdev/vm.h>
@ -68,20 +68,20 @@ gm100_identify(struct nouveau_device *device)
#endif
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = gm107_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = gm107_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gm107_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gm107_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
#if 0
device->oclass[NVDEV_SUBDEV_PWR ] = &nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
#endif
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = gm107_graph_oclass;

View File

@ -56,7 +56,7 @@ nv04_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;
@ -74,7 +74,7 @@ nv04_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv04_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv04_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv04_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv04_graph_oclass;

View File

@ -58,7 +58,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
device->oclass[NVDEV_ENGINE_DISP ] = nv04_disp_oclass;
break;
@ -75,7 +75,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@ -94,7 +94,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@ -113,7 +113,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@ -132,7 +132,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv10_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@ -151,7 +151,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@ -170,7 +170,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv1a_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;
@ -189,7 +189,7 @@ nv10_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv10_graph_oclass;

View File

@ -59,7 +59,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv20_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv20_graph_oclass;
@ -78,7 +78,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
@ -97,7 +97,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv25_graph_oclass;
@ -116,7 +116,7 @@ nv20_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv25_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv2a_graph_oclass;

View File

@ -59,7 +59,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
@ -78,7 +78,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv35_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
@ -97,7 +97,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv30_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv30_graph_oclass;
@ -117,7 +117,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv36_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv35_graph_oclass;
@ -137,7 +137,7 @@ nv30_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = nv10_fb_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv04_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv17_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv34_graph_oclass;

View File

@ -65,7 +65,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -88,7 +88,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -111,7 +111,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -134,7 +134,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -157,7 +157,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv04_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -180,7 +180,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -203,7 +203,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -226,7 +226,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv41_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -249,7 +249,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -272,7 +272,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -295,7 +295,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -318,7 +318,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -341,7 +341,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -364,7 +364,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -387,7 +387,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;
@ -410,7 +410,7 @@ nv40_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv40_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv44_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv04_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv40_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv10_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv40_graph_oclass;

View File

@ -74,7 +74,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv50_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -99,7 +99,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -127,7 +127,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -155,7 +155,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -183,7 +183,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -211,7 +211,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -239,7 +239,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -267,7 +267,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -295,7 +295,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -323,7 +323,7 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -350,9 +350,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -380,9 +380,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -409,9 +409,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;
@ -438,9 +438,9 @@ nv50_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nv50_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nv50_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nva3_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nv50_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv84_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nv50_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = &nv50_graph_oclass;

View File

@ -33,7 +33,7 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
#include <subdev/ltcg.h>
#include <subdev/ltc.h>
#include <subdev/ibus.h>
#include <subdev/instmem.h>
#include <subdev/vm.h>
@ -70,14 +70,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc0_graph_oclass;
@ -102,14 +102,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@ -134,14 +134,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@ -165,14 +165,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@ -197,14 +197,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc4_graph_oclass;
@ -229,14 +229,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc1_graph_oclass;
@ -260,14 +260,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvc0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvc0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvc8_graph_oclass;
@ -292,14 +292,14 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvd9_graph_oclass;
@ -323,12 +323,12 @@ nvc0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nvc0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gf100_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nvc0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nvc0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvd7_graph_oclass;

View File

@ -33,7 +33,7 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
#include <subdev/ltcg.h>
#include <subdev/ltc.h>
#include <subdev/ibus.h>
#include <subdev/instmem.h>
#include <subdev/vm.h>
@ -70,14 +70,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = gk104_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
@ -103,14 +103,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
@ -136,14 +136,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = gk104_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nve4_graph_oclass;
@ -158,15 +158,16 @@ nve0_identify(struct nouveau_device *device)
break;
case 0xea:
device->cname = "GK20A";
device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
device->oclass[NVDEV_SUBDEV_CLOCK ] = &gk20a_clock_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &gk20a_bar_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = gk20a_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = gk20a_graph_oclass;
@ -186,14 +187,14 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvf0_graph_oclass;
@ -219,17 +220,17 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nvd0_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nve0_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nvf0_graph_oclass;
device->oclass[NVDEV_ENGINE_GR ] = gk110b_graph_oclass;
device->oclass[NVDEV_ENGINE_DISP ] = nvf0_disp_oclass;
device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
@ -248,18 +249,18 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = nvc3_mc_oclass;
device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass;
device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass;
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTCG ] = gf100_ltcg_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = &nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass;
device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass;
device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass;
device->oclass[NVDEV_ENGINE_GR ] = nv108_graph_oclass;

View File

@ -22,23 +22,93 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <nvif/event.h>
#include "priv.h"
#include "outp.h"
#include "conn.h"
static int
nouveau_disp_hpd_check(struct nouveau_event *event, u32 types, int index)
int
nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *notify)
{
struct nouveau_disp *disp = event->priv;
struct nvkm_output *outp;
list_for_each_entry(outp, &disp->outp, head) {
if (outp->conn->index == index) {
if (outp->conn->hpd.event)
return 0;
break;
struct nouveau_disp *disp =
container_of(notify->event, typeof(*disp), vblank);
union {
struct nvif_notify_head_req_v0 v0;
} *req = data;
int ret;
if (nvif_unpack(req->v0, 0, 0, false)) {
notify->size = sizeof(struct nvif_notify_head_rep_v0);
if (ret = -ENXIO, req->v0.head <= disp->vblank.index_nr) {
notify->types = 1;
notify->index = req->v0.head;
return 0;
}
}
return -ENOSYS;
return ret;
}
void
nouveau_disp_vblank(struct nouveau_disp *disp, int head)
{
struct nvif_notify_head_rep_v0 rep = {};
nvkm_event_send(&disp->vblank, 1, head, &rep, sizeof(rep));
}
static int
nouveau_disp_hpd_ctor(void *data, u32 size, struct nvkm_notify *notify)
{
struct nouveau_disp *disp =
container_of(notify->event, typeof(*disp), hpd);
union {
struct nvif_notify_conn_req_v0 v0;
} *req = data;
struct nvkm_output *outp;
int ret;
if (nvif_unpack(req->v0, 0, 0, false)) {
notify->size = sizeof(struct nvif_notify_conn_rep_v0);
list_for_each_entry(outp, &disp->outp, head) {
if (ret = -ENXIO, outp->conn->index == req->v0.conn) {
if (ret = -ENODEV, outp->conn->hpd.event) {
notify->types = req->v0.mask;
notify->index = req->v0.conn;
ret = 0;
}
break;
}
}
}
return ret;
}
static const struct nvkm_event_func
nouveau_disp_hpd_func = {
.ctor = nouveau_disp_hpd_ctor
};
int
nouveau_disp_ntfy(struct nouveau_object *object, u32 type,
struct nvkm_event **event)
{
struct nouveau_disp *disp = (void *)object->engine;
switch (type) {
case NV04_DISP_NTFY_VBLANK:
*event = &disp->vblank;
return 0;
case NV04_DISP_NTFY_CONN:
*event = &disp->hpd;
return 0;
default:
break;
}
return -EINVAL;
}
int
@ -97,7 +167,8 @@ _nouveau_disp_dtor(struct nouveau_object *object)
struct nouveau_disp *disp = (void *)object;
struct nvkm_output *outp, *outt;
nouveau_event_destroy(&disp->vblank);
nvkm_event_fini(&disp->vblank);
nvkm_event_fini(&disp->hpd);
if (disp->outp.next) {
list_for_each_entry_safe(outp, outt, &disp->outp, head) {
@ -157,14 +228,11 @@ nouveau_disp_create_(struct nouveau_object *parent,
hpd = max(hpd, (u8)(dcbE.connector + 1));
}
ret = nouveau_event_create(3, hpd, &disp->hpd);
ret = nvkm_event_init(&nouveau_disp_hpd_func, 3, hpd, &disp->hpd);
if (ret)
return ret;
disp->hpd->priv = disp;
disp->hpd->check = nouveau_disp_hpd_check;
ret = nouveau_event_create(1, heads, &disp->vblank);
ret = nvkm_event_init(impl->vblank, 1, heads, &disp->vblank);
if (ret)
return ret;

View File

@ -22,39 +22,41 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <nvif/event.h>
#include <subdev/gpio.h>
#include "conn.h"
#include "outp.h"
static void
nvkm_connector_hpd_work(struct work_struct *w)
static int
nvkm_connector_hpd(struct nvkm_notify *notify)
{
struct nvkm_connector *conn = container_of(w, typeof(*conn), hpd.work);
struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd);
struct nouveau_disp *disp = nouveau_disp(conn);
struct nouveau_gpio *gpio = nouveau_gpio(conn);
u32 send = NVKM_HPD_UNPLUG;
if (gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.event->index))
send = NVKM_HPD_PLUG;
nouveau_event_trigger(disp->hpd, send, conn->index);
nouveau_event_get(conn->hpd.event);
}
const struct nvkm_gpio_ntfy_rep *line = notify->data;
struct nvif_notify_conn_rep_v0 rep;
int index = conn->index;
static int
nvkm_connector_hpd(void *data, u32 type, int index)
{
struct nvkm_connector *conn = data;
DBG("HPD: %d\n", type);
schedule_work(&conn->hpd.work);
return NVKM_EVENT_DROP;
DBG("HPD: %d\n", line->mask);
if (!gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index))
rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG;
else
rep.mask = NVIF_NOTIFY_CONN_V0_PLUG;
rep.version = 0;
nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
return NVKM_NOTIFY_KEEP;
}
int
_nvkm_connector_fini(struct nouveau_object *object, bool suspend)
{
struct nvkm_connector *conn = (void *)object;
if (conn->hpd.event)
nouveau_event_put(conn->hpd.event);
nvkm_notify_put(&conn->hpd);
return nouveau_object_fini(&conn->base, suspend);
}
@ -63,10 +65,8 @@ _nvkm_connector_init(struct nouveau_object *object)
{
struct nvkm_connector *conn = (void *)object;
int ret = nouveau_object_init(&conn->base);
if (ret == 0) {
if (conn->hpd.event)
nouveau_event_get(conn->hpd.event);
}
if (ret == 0)
nvkm_notify_get(&conn->hpd);
return ret;
}
@ -74,7 +74,7 @@ void
_nvkm_connector_dtor(struct nouveau_object *object)
{
struct nvkm_connector *conn = (void *)object;
nouveau_event_ref(NULL, &conn->hpd.event);
nvkm_notify_fini(&conn->hpd);
nouveau_object_destroy(&conn->base);
}
@ -116,19 +116,24 @@ nvkm_connector_create_(struct nouveau_object *parent,
if ((info->hpd = ffs(info->hpd))) {
if (--info->hpd >= ARRAY_SIZE(hpd)) {
ERR("hpd %02x unknown\n", info->hpd);
goto done;
return 0;
}
info->hpd = hpd[info->hpd];
ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func);
if (ret) {
ERR("func %02x lookup failed, %d\n", info->hpd, ret);
goto done;
return 0;
}
ret = nouveau_event_new(gpio->events, NVKM_GPIO_TOGGLED,
func.line, nvkm_connector_hpd,
conn, &conn->hpd.event);
ret = nvkm_notify_init(&gpio->event, nvkm_connector_hpd, true,
&(struct nvkm_gpio_ntfy_req) {
.mask = NVKM_GPIO_TOGGLED,
.line = func.line,
},
sizeof(struct nvkm_gpio_ntfy_req),
sizeof(struct nvkm_gpio_ntfy_rep),
&conn->hpd);
if (ret) {
ERR("func %02x failed, %d\n", info->hpd, ret);
} else {
@ -136,8 +141,6 @@ nvkm_connector_create_(struct nouveau_object *parent,
}
}
done:
INIT_WORK(&conn->hpd.work, nvkm_connector_hpd_work);
return 0;
}

View File

@ -10,10 +10,7 @@ struct nvkm_connector {
struct nvbios_connE info;
int index;
struct {
struct nouveau_eventh *event;
struct work_struct work;
} hpd;
struct nvkm_notify hpd;
};
#define nvkm_connector_create(p,e,c,b,i,d) \

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@ -32,13 +33,28 @@
#include "nv50.h"
int
nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data)
nv50_dac_power(NV50_DISP_MTHD_V1)
{
const u32 stat = (data & NV50_DISP_DAC_PWR_HSYNC) |
(data & NV50_DISP_DAC_PWR_VSYNC) |
(data & NV50_DISP_DAC_PWR_DATA) |
(data & NV50_DISP_DAC_PWR_STATE);
const u32 doff = (or * 0x800);
const u32 doff = outp->or * 0x800;
union {
struct nv50_disp_dac_pwr_v0 v0;
} *args = data;
u32 stat;
int ret;
nv_ioctl(object, "disp dac pwr size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp dac pwr vers %d state %d data %d "
"vsync %d hsync %d\n",
args->v0.version, args->v0.state, args->v0.data,
args->v0.vsync, args->v0.hsync);
stat = 0x00000040 * !args->v0.state;
stat |= 0x00000010 * !args->v0.data;
stat |= 0x00000004 * !args->v0.vsync;
stat |= 0x00000001 * !args->v0.hsync;
} else
return ret;
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
nv_mask(priv, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat);
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
@ -46,9 +62,24 @@ nv50_dac_power(struct nv50_disp_priv *priv, int or, u32 data)
}
int
nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
nv50_dac_sense(NV50_DISP_MTHD_V1)
{
const u32 doff = (or * 0x800);
union {
struct nv50_disp_dac_load_v0 v0;
} *args = data;
const u32 doff = outp->or * 0x800;
u32 loadval;
int ret;
nv_ioctl(object, "disp dac load size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp dac load vers %d data %08x\n",
args->v0.version, args->v0.data);
if (args->v0.data & 0xfff00000)
return -EINVAL;
loadval = args->v0.data;
} else
return ret;
nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000);
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
@ -61,38 +92,10 @@ nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000);
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval);
nv_debug(priv, "DAC%d sense: 0x%08x\n", outp->or, loadval);
if (!(loadval & 0x80000000))
return -ETIMEDOUT;
return (loadval & 0x38000000) >> 27;
}
int
nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
{
struct nv50_disp_priv *priv = (void *)object->engine;
const u8 or = (mthd & NV50_DISP_DAC_MTHD_OR);
u32 *data = args;
int ret;
if (size < sizeof(u32))
return -EINVAL;
switch (mthd & ~0x3f) {
case NV50_DISP_DAC_PWR:
ret = priv->dac.power(priv, or, data[0]);
break;
case NV50_DISP_DAC_LOAD:
ret = priv->dac.sense(priv, or, data[0]);
if (ret >= 0) {
data[0] = ret;
ret = 0;
}
break;
default:
BUG_ON(1);
}
return ret;
args->v0.load = (loadval & 0x38000000) >> 27;
return 0;
}

View File

@ -30,7 +30,7 @@
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "dport.h"
#include "outpdp.h"
@ -335,7 +335,7 @@ nouveau_dp_train(struct work_struct *w)
int ret;
/* bring capabilities within encoder limits */
if (nv_mclass(disp) < NVD0_DISP_CLASS)
if (nv_mclass(disp) < GF110_DISP)
outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED;
if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) {
outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT;
@ -354,7 +354,7 @@ nouveau_dp_train(struct work_struct *w)
cfg--;
/* disable link interrupt handling during link training */
nouveau_event_put(outp->irq);
nvkm_notify_put(&outp->irq);
/* enable down-spreading and execute pre-train script from vbios */
dp_link_train_init(dp, outp->dpcd[3] & 0x01);
@ -395,5 +395,5 @@ nouveau_dp_train(struct work_struct *w)
DBG("training complete\n");
atomic_set(&outp->lt.done, 1);
wake_up(&outp->lt.wait);
nouveau_event_get(outp->irq);
nvkm_notify_get(&outp->irq);
}

View File

@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "nv50.h"
@ -35,17 +35,17 @@
static struct nouveau_oclass
gm107_disp_sclass[] = {
{ GM107_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
{ GM107_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
{ GM107_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
{ GM107_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
{ GM107_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
{ GM107_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
{ GK110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
{ GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
{ GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
{ GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
gm107_disp_base_oclass[] = {
{ GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
{ GM107_DISP, &nvd0_disp_base_ofuncs },
{}
};
@ -93,9 +93,11 @@ gm107_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nve0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
.head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;

View File

@ -22,25 +22,37 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include "nv50.h"
int
nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
nva3_hda_eld(NV50_DISP_MTHD_V1)
{
const u32 soff = (or * 0x800);
int i;
union {
struct nv50_disp_sor_hda_eld_v0 v0;
} *args = data;
const u32 soff = outp->or * 0x800;
int ret, i;
if (data && data[0]) {
nv_ioctl(object, "disp sor hda eld size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version);
if (size > 0x60)
return -E2BIG;
} else
return ret;
if (size && args->v0.data[0]) {
for (i = 0; i < size; i++)
nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]);
nv_wr32(priv, 0x61c440 + soff, (i << 8) | args->v0.data[0]);
for (; i < 0x60; i++)
nv_wr32(priv, 0x61c440 + soff, (i << 8));
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003);
} else
if (data) {
if (size) {
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000001);
} else {
nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000000);

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@ -33,19 +34,30 @@
#include "nv50.h"
int
nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
nvd0_hda_eld(NV50_DISP_MTHD_V1)
{
const u32 soff = (or * 0x030);
int i;
union {
struct nv50_disp_sor_hda_eld_v0 v0;
} *args = data;
const u32 soff = outp->or * 0x030;
int ret, i;
if (data && data[0]) {
nv_ioctl(object, "disp sor hda eld size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "disp sor hda eld vers %d\n", args->v0.version);
if (size > 0x60)
return -E2BIG;
} else
return ret;
if (size && args->v0.data[0]) {
for (i = 0; i < size; i++)
nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]);
nv_wr32(priv, 0x10ec00 + soff, (i << 8) | args->v0.data[i]);
for (; i < 0x60; i++)
nv_wr32(priv, 0x10ec00 + soff, (i << 8));
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003);
} else
if (data) {
if (size) {
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000001);
} else {
nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000000);

View File

@ -22,17 +22,38 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include "nv50.h"
int
nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv84_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
const u32 hoff = (head * 0x800);
union {
struct nv50_disp_sor_hdmi_pwr_v0 v0;
} *args = data;
u32 ctrl;
int ret;
if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
"max_ac_packet %d rekey %d\n",
args->v0.version, args->v0.state,
args->v0.max_ac_packet, args->v0.rekey);
if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
return -EINVAL;
ctrl = 0x40000000 * !!args->v0.state;
ctrl |= args->v0.max_ac_packet << 16;
ctrl |= args->v0.rekey;
ctrl |= 0x1f000000; /* ??? */
} else
return ret;
if (!(ctrl & 0x40000000)) {
nv_mask(priv, 0x6165a4 + hoff, 0x40000000, 0x00000000);
nv_mask(priv, 0x616520 + hoff, 0x00000001, 0x00000000);
nv_mask(priv, 0x616500 + hoff, 0x00000001, 0x00000000);
@ -65,6 +86,6 @@ nv84_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
/* HDMI_CTRL */
nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
nv_mask(priv, 0x6165a4 + hoff, 0x5f1f007f, ctrl);
return 0;
}

View File

@ -22,17 +22,38 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include "nv50.h"
int
nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nva3_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
const u32 soff = (or * 0x800);
const u32 soff = outp->or * 0x800;
union {
struct nv50_disp_sor_hdmi_pwr_v0 v0;
} *args = data;
u32 ctrl;
int ret;
if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
"max_ac_packet %d rekey %d\n",
args->v0.version, args->v0.state,
args->v0.max_ac_packet, args->v0.rekey);
if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
return -EINVAL;
ctrl = 0x40000000 * !!args->v0.state;
ctrl |= args->v0.max_ac_packet << 16;
ctrl |= args->v0.rekey;
ctrl |= 0x1f000000; /* ??? */
} else
return ret;
if (!(ctrl & 0x40000000)) {
nv_mask(priv, 0x61c5a4 + soff, 0x40000000, 0x00000000);
nv_mask(priv, 0x61c520 + soff, 0x00000001, 0x00000000);
nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000000);
@ -65,6 +86,6 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_mask(priv, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
/* HDMI_CTRL */
nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, data | 0x1f000000 /* ??? */);
nv_mask(priv, 0x61c5a4 + soff, 0x5f1f007f, ctrl);
return 0;
}

View File

@ -22,17 +22,37 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include "nv50.h"
int
nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1)
{
const u32 hoff = (head * 0x800);
union {
struct nv50_disp_sor_hdmi_pwr_v0 v0;
} *args = data;
u32 ctrl;
int ret;
if (!(data & NV84_DISP_SOR_HDMI_PWR_STATE_ON)) {
nv_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
"max_ac_packet %d rekey %d\n",
args->v0.version, args->v0.state,
args->v0.max_ac_packet, args->v0.rekey);
if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
return -EINVAL;
ctrl = 0x40000000 * !!args->v0.state;
ctrl |= args->v0.max_ac_packet << 16;
ctrl |= args->v0.rekey;
} else
return ret;
if (!(ctrl & 0x40000000)) {
nv_mask(priv, 0x616798 + hoff, 0x40000000, 0x00000000);
nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000000);
nv_mask(priv, 0x616714 + hoff, 0x00000001, 0x00000000);
@ -54,7 +74,7 @@ nvd0_hdmi_ctrl(struct nv50_disp_priv *priv, int head, int or, u32 data)
nv_mask(priv, 0x6167a4 + hoff, 0x00000001, 0x00000001);
/* HDMI_CTRL */
nv_mask(priv, 0x616798 + hoff, 0x401f007f, data);
nv_mask(priv, 0x616798 + hoff, 0x401f007f, ctrl);
/* NFI, audio doesn't work without it though.. */
nv_mask(priv, 0x616548 + hoff, 0x00000070, 0x00000000);

View File

@ -24,60 +24,100 @@
#include "priv.h"
#include <core/client.h>
#include <core/event.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
struct nv04_disp_priv {
struct nouveau_disp base;
};
static int
nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
nv04_disp_scanoutpos(struct nouveau_object *object, struct nv04_disp_priv *priv,
void *data, u32 size, int head)
{
struct nv04_disp_priv *priv = (void *)object->engine;
struct nv04_display_scanoutpos *args = data;
const int head = (mthd & NV04_DISP_MTHD_HEAD);
const u32 hoff = head * 0x2000;
union {
struct nv04_disp_scanoutpos_v0 v0;
} *args = data;
u32 line;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(object, "disp scanoutpos size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
args->v0.vblanks = nv_rd32(priv, 0x680800 + hoff) & 0xffff;
args->v0.vtotal = nv_rd32(priv, 0x680804 + hoff) & 0xffff;
args->v0.vblanke = args->v0.vtotal - 1;
args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff;
args->vtotal = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff;
args->vblanke = args->vtotal - 1;
args->v0.hblanks = nv_rd32(priv, 0x680820 + hoff) & 0xffff;
args->v0.htotal = nv_rd32(priv, 0x680824 + hoff) & 0xffff;
args->v0.hblanke = args->v0.htotal - 1;
args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
args->htotal = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
args->hblanke = args->htotal - 1;
/*
* If output is vga instead of digital then vtotal/htotal is
* invalid so we have to give up and trigger the timestamping
* fallback in the drm core.
*/
if (!args->v0.vtotal || !args->v0.htotal)
return -ENOTSUPP;
/*
* If output is vga instead of digital then vtotal/htotal is invalid
* so we have to give up and trigger the timestamping fallback in the
* drm core.
*/
if (!args->vtotal || !args->htotal)
return -ENOTSUPP;
args->v0.time[0] = ktime_to_ns(ktime_get());
line = nv_rd32(priv, 0x600868 + hoff);
args->v0.time[1] = ktime_to_ns(ktime_get());
args->v0.hline = (line & 0xffff0000) >> 16;
args->v0.vline = (line & 0x0000ffff);
} else
return ret;
args->time[0] = ktime_to_ns(ktime_get());
line = nv_rd32(priv, 0x600868 + (head * 0x2000));
args->time[1] = ktime_to_ns(ktime_get());
args->hline = (line & 0xffff0000) >> 16;
args->vline = (line & 0x0000ffff);
return 0;
}
#define HEAD_MTHD(n) (n), (n) + 0x01
static int
nv04_disp_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
{
union {
struct nv04_disp_mthd_v0 v0;
} *args = data;
struct nv04_disp_priv *priv = (void *)object->engine;
int head, ret;
static struct nouveau_omthds
nv04_disp_omthds[] = {
{ HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos },
{}
nv_ioctl(object, "disp mthd size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
args->v0.version, args->v0.method, args->v0.head);
mthd = args->v0.method;
head = args->v0.head;
} else
return ret;
if (head < 0 || head >= 2)
return -ENXIO;
switch (mthd) {
case NV04_DISP_SCANOUTPOS:
return nv04_disp_scanoutpos(object, priv, data, size, head);
default:
break;
}
return -EINVAL;
}
static struct nouveau_ofuncs
nv04_disp_ofuncs = {
.ctor = _nouveau_object_ctor,
.dtor = nouveau_object_destroy,
.init = nouveau_object_init,
.fini = nouveau_object_fini,
.mthd = nv04_disp_mthd,
.ntfy = nouveau_disp_ntfy,
};
static struct nouveau_oclass
nv04_disp_sclass[] = {
{ NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },
{ NV04_DISP, &nv04_disp_ofuncs },
{},
};
@ -86,17 +126,26 @@ nv04_disp_sclass[] = {
******************************************************************************/
static void
nv04_disp_vblank_enable(struct nouveau_event *event, int type, int head)
nv04_disp_vblank_init(struct nvkm_event *event, int type, int head)
{
nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);
struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000001);
}
static void
nv04_disp_vblank_disable(struct nouveau_event *event, int type, int head)
nv04_disp_vblank_fini(struct nvkm_event *event, int type, int head)
{
nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);
struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
nv_wr32(disp, 0x600140 + (head * 0x2000) , 0x00000000);
}
static const struct nvkm_event_func
nv04_disp_vblank_func = {
.ctor = nouveau_disp_vblank_ctor,
.init = nv04_disp_vblank_init,
.fini = nv04_disp_vblank_fini,
};
static void
nv04_disp_intr(struct nouveau_subdev *subdev)
{
@ -106,12 +155,12 @@ nv04_disp_intr(struct nouveau_subdev *subdev)
u32 pvideo;
if (crtc0 & 0x00000001) {
nouveau_event_trigger(priv->base.vblank, 1, 0);
nouveau_disp_vblank(&priv->base, 0);
nv_wr32(priv, 0x600100, 0x00000001);
}
if (crtc1 & 0x00000001) {
nouveau_event_trigger(priv->base.vblank, 1, 1);
nouveau_disp_vblank(&priv->base, 1);
nv_wr32(priv, 0x602100, 0x00000001);
}
@ -140,9 +189,6 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv_engine(priv)->sclass = nv04_disp_sclass;
nv_subdev(priv)->intr = nv04_disp_intr;
priv->base.vblank->priv = priv;
priv->base.vblank->enable = nv04_disp_vblank_enable;
priv->base.vblank->disable = nv04_disp_vblank_disable;
return 0;
}
@ -155,4 +201,5 @@ nv04_disp_oclass = &(struct nouveau_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.vblank = &nv04_disp_vblank_func,
}.base;

View File

@ -23,10 +23,12 @@
*/
#include <core/object.h>
#include <core/client.h>
#include <core/parent.h>
#include <core/handle.h>
#include <core/class.h>
#include <core/enum.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@ -43,14 +45,16 @@
* EVO channel base class
******************************************************************************/
int
static int
nv50_disp_chan_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, int chid,
struct nouveau_oclass *oclass, int head,
int length, void **pobject)
{
const struct nv50_disp_chan_impl *impl = (void *)oclass->ofuncs;
struct nv50_disp_base *base = (void *)parent;
struct nv50_disp_chan *chan;
int chid = impl->chid + head;
int ret;
if (base->chan & (1 << chid))
@ -63,12 +67,14 @@ nv50_disp_chan_create_(struct nouveau_object *parent,
chan = *pobject;
if (ret)
return ret;
chan->chid = chid;
nv_parent(chan)->object_attach = impl->attach;
nv_parent(chan)->object_detach = impl->detach;
return 0;
}
void
static void
nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
{
struct nv50_disp_base *base = (void *)nv_object(chan)->parent;
@ -76,6 +82,16 @@ nv50_disp_chan_destroy(struct nv50_disp_chan *chan)
nouveau_namedb_destroy(&chan->base);
}
int
nv50_disp_chan_map(struct nouveau_object *object, u64 *addr, u32 *size)
{
struct nv50_disp_chan *chan = (void *)object;
*addr = nv_device_resource_start(nv_device(object), 0) +
0x640000 + (chan->chid * 0x1000);
*size = 0x001000;
return 0;
}
u32
nv50_disp_chan_rd32(struct nouveau_object *object, u64 addr)
{
@ -115,16 +131,16 @@ nv50_disp_dmac_object_detach(struct nouveau_object *parent, int cookie)
nouveau_ramht_remove(base->ramht, cookie);
}
int
static int
nv50_disp_dmac_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, u32 pushbuf, int chid,
struct nouveau_oclass *oclass, u32 pushbuf, int head,
int length, void **pobject)
{
struct nv50_disp_dmac *dmac;
int ret;
ret = nv50_disp_chan_create_(parent, engine, oclass, chid,
ret = nv50_disp_chan_create_(parent, engine, oclass, head,
length, pobject);
dmac = *pobject;
if (ret)
@ -397,27 +413,32 @@ nv50_disp_mast_mthd_chan = {
}
};
static int
int
nv50_disp_mast_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_mast_class *args = data;
union {
struct nv50_disp_core_channel_dma_v0 v0;
} *args = data;
struct nv50_disp_dmac *mast;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create disp core channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create disp core channel dma vers %d "
"pushbuf %08x\n",
args->v0.version, args->v0.pushbuf);
} else
return ret;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
0, sizeof(*mast), (void **)&mast);
*pobject = nv_object(mast);
if (ret)
return ret;
nv_parent(mast)->object_attach = nv50_disp_dmac_object_attach;
nv_parent(mast)->object_detach = nv50_disp_dmac_object_detach;
return 0;
}
@ -479,14 +500,18 @@ nv50_disp_mast_fini(struct nouveau_object *object, bool suspend)
return nv50_disp_chan_fini(&mast->base, suspend);
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nv50_disp_mast_ofuncs = {
.ctor = nv50_disp_mast_ctor,
.dtor = nv50_disp_dmac_dtor,
.init = nv50_disp_mast_init,
.fini = nv50_disp_mast_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_mast_ctor,
.base.dtor = nv50_disp_dmac_dtor,
.base.init = nv50_disp_mast_init,
.base.fini = nv50_disp_mast_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 0,
.attach = nv50_disp_dmac_object_attach,
.detach = nv50_disp_dmac_object_detach,
};
/*******************************************************************************
@ -543,39 +568,51 @@ nv50_disp_sync_mthd_chan = {
}
};
static int
int
nv50_disp_sync_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_sync_class *args = data;
union {
struct nv50_disp_base_channel_dma_v0 v0;
} *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_dmac *dmac;
int ret;
if (size < sizeof(*args) || args->head > 1)
return -EINVAL;
nv_ioctl(parent, "create disp base channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create disp base channel dma vers %d "
"pushbuf %08x head %d\n",
args->v0.version, args->v0.pushbuf, args->v0.head);
if (args->v0.head > priv->head.nr)
return -EINVAL;
} else
return ret;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
1 + args->head, sizeof(*dmac),
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
args->v0.head, sizeof(*dmac),
(void **)&dmac);
*pobject = nv_object(dmac);
if (ret)
return ret;
nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach;
nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach;
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nv50_disp_sync_ofuncs = {
.ctor = nv50_disp_sync_ctor,
.dtor = nv50_disp_dmac_dtor,
.init = nv50_disp_dmac_init,
.fini = nv50_disp_dmac_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_sync_ctor,
.base.dtor = nv50_disp_dmac_dtor,
.base.init = nv50_disp_dmac_init,
.base.fini = nv50_disp_dmac_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 1,
.attach = nv50_disp_dmac_object_attach,
.detach = nv50_disp_dmac_object_detach,
};
/*******************************************************************************
@ -620,39 +657,51 @@ nv50_disp_ovly_mthd_chan = {
}
};
static int
int
nv50_disp_ovly_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_ovly_class *args = data;
union {
struct nv50_disp_overlay_channel_dma_v0 v0;
} *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_dmac *dmac;
int ret;
if (size < sizeof(*args) || args->head > 1)
return -EINVAL;
nv_ioctl(parent, "create disp overlay channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create disp overlay channel dma vers %d "
"pushbuf %08x head %d\n",
args->v0.version, args->v0.pushbuf, args->v0.head);
if (args->v0.head > priv->head.nr)
return -EINVAL;
} else
return ret;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
3 + args->head, sizeof(*dmac),
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->v0.pushbuf,
args->v0.head, sizeof(*dmac),
(void **)&dmac);
*pobject = nv_object(dmac);
if (ret)
return ret;
nv_parent(dmac)->object_attach = nv50_disp_dmac_object_attach;
nv_parent(dmac)->object_detach = nv50_disp_dmac_object_detach;
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nv50_disp_ovly_ofuncs = {
.ctor = nv50_disp_ovly_ctor,
.dtor = nv50_disp_dmac_dtor,
.init = nv50_disp_dmac_init,
.fini = nv50_disp_dmac_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_ovly_ctor,
.base.dtor = nv50_disp_dmac_dtor,
.base.init = nv50_disp_dmac_init,
.base.fini = nv50_disp_dmac_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 3,
.attach = nv50_disp_dmac_object_attach,
.detach = nv50_disp_dmac_object_detach,
};
/*******************************************************************************
@ -662,14 +711,14 @@ nv50_disp_ovly_ofuncs = {
static int
nv50_disp_pioc_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, int chid,
struct nouveau_oclass *oclass, int head,
int length, void **pobject)
{
return nv50_disp_chan_create_(parent, engine, oclass, chid,
return nv50_disp_chan_create_(parent, engine, oclass, head,
length, pobject);
}
static void
void
nv50_disp_pioc_dtor(struct nouveau_object *object)
{
struct nv50_disp_pioc *pioc = (void *)object;
@ -727,20 +776,29 @@ nv50_disp_pioc_fini(struct nouveau_object *object, bool suspend)
* EVO immediate overlay channel objects
******************************************************************************/
static int
int
nv50_disp_oimm_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_oimm_class *args = data;
union {
struct nv50_disp_overlay_v0 v0;
} *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_pioc *pioc;
int ret;
if (size < sizeof(*args) || args->head > 1)
return -EINVAL;
nv_ioctl(parent, "create disp overlay size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create disp overlay vers %d head %d\n",
args->v0.version, args->v0.head);
if (args->v0.head > priv->head.nr)
return -EINVAL;
} else
return ret;
ret = nv50_disp_pioc_create_(parent, engine, oclass, 5 + args->head,
ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
sizeof(*pioc), (void **)&pioc);
*pobject = nv_object(pioc);
if (ret)
@ -749,34 +807,45 @@ nv50_disp_oimm_ctor(struct nouveau_object *parent,
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nv50_disp_oimm_ofuncs = {
.ctor = nv50_disp_oimm_ctor,
.dtor = nv50_disp_pioc_dtor,
.init = nv50_disp_pioc_init,
.fini = nv50_disp_pioc_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_oimm_ctor,
.base.dtor = nv50_disp_pioc_dtor,
.base.init = nv50_disp_pioc_init,
.base.fini = nv50_disp_pioc_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 5,
};
/*******************************************************************************
* EVO cursor channel objects
******************************************************************************/
static int
int
nv50_disp_curs_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_curs_class *args = data;
union {
struct nv50_disp_cursor_v0 v0;
} *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_pioc *pioc;
int ret;
if (size < sizeof(*args) || args->head > 1)
return -EINVAL;
nv_ioctl(parent, "create disp cursor size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create disp cursor vers %d head %d\n",
args->v0.version, args->v0.head);
if (args->v0.head > priv->head.nr)
return -EINVAL;
} else
return ret;
ret = nv50_disp_pioc_create_(parent, engine, oclass, 7 + args->head,
ret = nv50_disp_pioc_create_(parent, engine, oclass, args->v0.head,
sizeof(*pioc), (void **)&pioc);
*pobject = nv_object(pioc);
if (ret)
@ -785,14 +854,16 @@ nv50_disp_curs_ctor(struct nouveau_object *parent,
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nv50_disp_curs_ofuncs = {
.ctor = nv50_disp_curs_ctor,
.dtor = nv50_disp_pioc_dtor,
.init = nv50_disp_pioc_init,
.fini = nv50_disp_pioc_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_curs_ctor,
.base.dtor = nv50_disp_pioc_dtor,
.base.init = nv50_disp_pioc_init,
.base.fini = nv50_disp_pioc_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 7,
};
/*******************************************************************************
@ -800,47 +871,162 @@ nv50_disp_curs_ofuncs = {
******************************************************************************/
int
nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
{
struct nv50_disp_priv *priv = (void *)object->engine;
struct nv04_display_scanoutpos *args = data;
const int head = (mthd & NV50_DISP_MTHD_HEAD);
u32 blanke, blanks, total;
const u32 blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
const u32 blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
const u32 total = nv_rd32(priv, 0x610afc + (head * 0x540));
union {
struct nv04_disp_scanoutpos_v0 v0;
} *args = data;
int ret;
if (size < sizeof(*args) || head >= priv->head.nr)
return -EINVAL;
blanke = nv_rd32(priv, 0x610aec + (head * 0x540));
blanks = nv_rd32(priv, 0x610af4 + (head * 0x540));
total = nv_rd32(priv, 0x610afc + (head * 0x540));
nv_ioctl(object, "disp scanoutpos size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
args->v0.vblanke = (blanke & 0xffff0000) >> 16;
args->v0.hblanke = (blanke & 0x0000ffff);
args->v0.vblanks = (blanks & 0xffff0000) >> 16;
args->v0.hblanks = (blanks & 0x0000ffff);
args->v0.vtotal = ( total & 0xffff0000) >> 16;
args->v0.htotal = ( total & 0x0000ffff);
args->v0.time[0] = ktime_to_ns(ktime_get());
args->v0.vline = /* vline read locks hline */
nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
args->v0.time[1] = ktime_to_ns(ktime_get());
args->v0.hline =
nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
} else
return ret;
args->vblanke = (blanke & 0xffff0000) >> 16;
args->hblanke = (blanke & 0x0000ffff);
args->vblanks = (blanks & 0xffff0000) >> 16;
args->hblanks = (blanks & 0x0000ffff);
args->vtotal = ( total & 0xffff0000) >> 16;
args->htotal = ( total & 0x0000ffff);
args->time[0] = ktime_to_ns(ktime_get());
args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
return 0;
}
static void
nv50_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
int
nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
{
nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));
const struct nv50_disp_impl *impl = (void *)nv_oclass(object->engine);
union {
struct nv50_disp_mthd_v0 v0;
struct nv50_disp_mthd_v1 v1;
} *args = data;
struct nv50_disp_priv *priv = (void *)object->engine;
struct nvkm_output *outp = NULL;
struct nvkm_output *temp;
u16 type, mask = 0;
int head, ret;
if (mthd != NV50_DISP_MTHD)
return -EINVAL;
nv_ioctl(object, "disp mthd size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
args->v0.version, args->v0.method, args->v0.head);
mthd = args->v0.method;
head = args->v0.head;
} else
if (nvif_unpack(args->v1, 1, 1, true)) {
nv_ioctl(object, "disp mthd vers %d mthd %02x "
"type %04x mask %04x\n",
args->v1.version, args->v1.method,
args->v1.hasht, args->v1.hashm);
mthd = args->v1.method;
type = args->v1.hasht;
mask = args->v1.hashm;
head = ffs((mask >> 8) & 0x0f) - 1;
} else
return ret;
if (head < 0 || head >= priv->head.nr)
return -ENXIO;
if (mask) {
list_for_each_entry(temp, &priv->base.outp, head) {
if ((temp->info.hasht == type) &&
(temp->info.hashm & mask) == mask) {
outp = temp;
break;
}
}
if (outp == NULL)
return -ENXIO;
}
switch (mthd) {
case NV50_DISP_SCANOUTPOS:
return impl->head.scanoutpos(object, priv, data, size, head);
default:
break;
}
switch (mthd * !!outp) {
case NV50_DISP_MTHD_V1_DAC_PWR:
return priv->dac.power(object, priv, data, size, head, outp);
case NV50_DISP_MTHD_V1_DAC_LOAD:
return priv->dac.sense(object, priv, data, size, head, outp);
case NV50_DISP_MTHD_V1_SOR_PWR:
return priv->sor.power(object, priv, data, size, head, outp);
case NV50_DISP_MTHD_V1_SOR_HDA_ELD:
if (!priv->sor.hda_eld)
return -ENODEV;
return priv->sor.hda_eld(object, priv, data, size, head, outp);
case NV50_DISP_MTHD_V1_SOR_HDMI_PWR:
if (!priv->sor.hdmi)
return -ENODEV;
return priv->sor.hdmi(object, priv, data, size, head, outp);
case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
union {
struct nv50_disp_sor_lvds_script_v0 v0;
} *args = data;
nv_ioctl(object, "disp sor lvds script size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp sor lvds script "
"vers %d name %04x\n",
args->v0.version, args->v0.script);
priv->sor.lvdsconf = args->v0.script;
return 0;
} else
return ret;
}
break;
case NV50_DISP_MTHD_V1_SOR_DP_PWR: {
struct nvkm_output_dp *outpdp = (void *)outp;
union {
struct nv50_disp_sor_dp_pwr_v0 v0;
} *args = data;
nv_ioctl(object, "disp sor dp pwr size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp sor dp pwr vers %d state %d\n",
args->v0.version, args->v0.state);
if (args->v0.state == 0) {
nvkm_notify_put(&outpdp->irq);
((struct nvkm_output_dp_impl *)nv_oclass(outp))
->lnk_pwr(outpdp, 0);
atomic_set(&outpdp->lt.done, 0);
return 0;
} else
if (args->v0.state != 0) {
nvkm_output_dp_train(&outpdp->base, 0, true);
return 0;
}
} else
return ret;
}
break;
case NV50_DISP_MTHD_V1_PIOR_PWR:
if (!priv->pior.power)
return -ENODEV;
return priv->pior.power(object, priv, data, size, head, outp);
default:
break;
}
return -EINVAL;
}
static void
nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
{
nv_mask(event->priv, 0x61002c, (4 << head), 0);
}
static int
int
nv50_disp_base_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@ -856,14 +1042,11 @@ nv50_disp_base_ctor(struct nouveau_object *parent,
if (ret)
return ret;
priv->base.vblank->priv = priv;
priv->base.vblank->enable = nv50_disp_base_vblank_enable;
priv->base.vblank->disable = nv50_disp_base_vblank_disable;
return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
&base->ramht);
}
static void
void
nv50_disp_base_dtor(struct nouveau_object *object)
{
struct nv50_disp_base *base = (void *)object;
@ -958,34 +1141,23 @@ nv50_disp_base_ofuncs = {
.dtor = nv50_disp_base_dtor,
.init = nv50_disp_base_init,
.fini = nv50_disp_base_fini,
};
static struct nouveau_omthds
nv50_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
.mthd = nv50_disp_base_mthd,
.ntfy = nouveau_disp_ntfy,
};
static struct nouveau_oclass
nv50_disp_base_oclass[] = {
{ NV50_DISP_CLASS, &nv50_disp_base_ofuncs, nv50_disp_base_omthds },
{ NV50_DISP, &nv50_disp_base_ofuncs },
{}
};
static struct nouveau_oclass
nv50_disp_sclass[] = {
{ NV50_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
{ NV50_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
{ NV50_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
{ NV50_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
{ NV50_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
{ NV50_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
{ NV50_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
{ NV50_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
{ NV50_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
{ NV50_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
@ -1005,7 +1177,7 @@ nv50_disp_data_ctor(struct nouveau_object *parent,
int ret = -EBUSY;
/* no context needed for channel objects... */
if (nv_mclass(parent) != NV_DEVICE_CLASS) {
if (nv_mclass(parent) != NV_DEVICE) {
atomic_inc(&parent->refcount);
*pobject = parent;
return 1;
@ -1040,6 +1212,27 @@ nv50_disp_cclass = {
* Display engine implementation
******************************************************************************/
static void
nv50_disp_vblank_fini(struct nvkm_event *event, int type, int head)
{
struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
nv_mask(disp, 0x61002c, (4 << head), 0);
}
static void
nv50_disp_vblank_init(struct nvkm_event *event, int type, int head)
{
struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
nv_mask(disp, 0x61002c, (4 << head), (4 << head));
}
const struct nvkm_event_func
nv50_disp_vblank_func = {
.ctor = nouveau_disp_vblank_ctor,
.init = nv50_disp_vblank_init,
.fini = nv50_disp_vblank_fini,
};
static const struct nouveau_enum
nv50_disp_intr_error_type[] = {
{ 3, "ILLEGAL_MTHD" },
@ -1381,7 +1574,7 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
int TU, VTUi, VTUf, VTUa;
u64 link_data_rate, link_ratio, unk;
u32 best_diff = 64 * symbol;
u32 link_nr, link_bw, bits, r;
u32 link_nr, link_bw, bits;
/* calculate packed data rate for each lane */
if (dpctrl > 0x00030000) link_nr = 4;
@ -1401,7 +1594,7 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
/* calculate ratio of packed data rate to link symbol rate */
link_ratio = link_data_rate * symbol;
r = do_div(link_ratio, link_bw);
do_div(link_ratio, link_bw);
for (TU = 64; TU >= 32; TU--) {
/* calculate average number of valid symbols in each TU */
@ -1462,8 +1655,8 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,
/* XXX close to vbios numbers, but not right */
unk = (symbol - link_ratio) * bestTU;
unk *= link_ratio;
r = do_div(unk, symbol);
r = do_div(unk, symbol);
do_div(unk, symbol);
do_div(unk, symbol);
unk += 6;
nv_mask(priv, 0x61c10c + loff, 0x000001fc, bestTU << 2);
@ -1654,13 +1847,13 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
}
if (intr1 & 0x00000004) {
nouveau_event_trigger(priv->base.vblank, 1, 0);
nouveau_disp_vblank(&priv->base, 0);
nv_wr32(priv, 0x610024, 0x00000004);
intr1 &= ~0x00000004;
}
if (intr1 & 0x00000008) {
nouveau_event_trigger(priv->base.vblank, 1, 1);
nouveau_disp_vblank(&priv->base, 1);
nv_wr32(priv, 0x610024, 0x00000008);
intr1 &= ~0x00000008;
}
@ -1718,9 +1911,11 @@ nv50_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nv50_disp_vblank_func,
.base.outp = nv50_disp_outp_sclass,
.mthd.core = &nv50_disp_mast_mthd_chan,
.mthd.base = &nv50_disp_sync_mthd_chan,
.mthd.ovly = &nv50_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
.head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;

View File

@ -14,15 +14,10 @@
#include "outp.h"
#include "outpdp.h"
struct nv50_disp_impl {
struct nouveau_disp_impl base;
struct {
const struct nv50_disp_mthd_chan *core;
const struct nv50_disp_mthd_chan *base;
const struct nv50_disp_mthd_chan *ovly;
int prev;
} mthd;
};
#define NV50_DISP_MTHD_ struct nouveau_object *object, \
struct nv50_disp_priv *priv, void *data, u32 size
#define NV50_DISP_MTHD_V0 NV50_DISP_MTHD_, int head
#define NV50_DISP_MTHD_V1 NV50_DISP_MTHD_, int head, struct nvkm_output *outp
struct nv50_disp_priv {
struct nouveau_disp base;
@ -36,44 +31,52 @@ struct nv50_disp_priv {
} head;
struct {
int nr;
int (*power)(struct nv50_disp_priv *, int dac, u32 data);
int (*sense)(struct nv50_disp_priv *, int dac, u32 load);
int (*power)(NV50_DISP_MTHD_V1);
int (*sense)(NV50_DISP_MTHD_V1);
} dac;
struct {
int nr;
int (*power)(struct nv50_disp_priv *, int sor, u32 data);
int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);
int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);
int (*power)(NV50_DISP_MTHD_V1);
int (*hda_eld)(NV50_DISP_MTHD_V1);
int (*hdmi)(NV50_DISP_MTHD_V1);
u32 lvdsconf;
} sor;
struct {
int nr;
int (*power)(struct nv50_disp_priv *, int ext, u32 data);
int (*power)(NV50_DISP_MTHD_V1);
u8 type[3];
} pior;
};
#define HEAD_MTHD(n) (n), (n) + 0x03
struct nv50_disp_impl {
struct nouveau_disp_impl base;
struct {
const struct nv50_disp_mthd_chan *core;
const struct nv50_disp_mthd_chan *base;
const struct nv50_disp_mthd_chan *ovly;
int prev;
} mthd;
struct {
int (*scanoutpos)(NV50_DISP_MTHD_V0);
} head;
};
int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32);
int nv50_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32);
#define DAC_MTHD(n) (n), (n) + 0x03
int nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0);
int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
int nv50_dac_power(struct nv50_disp_priv *, int, u32);
int nv50_dac_sense(struct nv50_disp_priv *, int, u32);
int nv50_dac_power(NV50_DISP_MTHD_V1);
int nv50_dac_sense(NV50_DISP_MTHD_V1);
#define SOR_MTHD(n) (n), (n) + 0x3f
int nva3_hda_eld(NV50_DISP_MTHD_V1);
int nvd0_hda_eld(NV50_DISP_MTHD_V1);
int nva3_hda_eld(struct nv50_disp_priv *, int, u8 *, u32);
int nvd0_hda_eld(struct nv50_disp_priv *, int, u8 *, u32);
int nv84_hdmi_ctrl(NV50_DISP_MTHD_V1);
int nva3_hdmi_ctrl(NV50_DISP_MTHD_V1);
int nvd0_hdmi_ctrl(NV50_DISP_MTHD_V1);
int nv84_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
int nva3_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
int nvd0_hdmi_ctrl(struct nv50_disp_priv *, int, int, u32);
int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32);
int nv50_sor_power(struct nv50_disp_priv *, int, u32);
int nv50_sor_power(NV50_DISP_MTHD_V1);
int nv94_sor_dp_train_init(struct nv50_disp_priv *, int, int, int, u16, u16,
u32, struct dcb_output *);
@ -93,10 +96,7 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32,
struct dcb_output *);
#define PIOR_MTHD(n) (n), (n) + 0x03
int nv50_pior_mthd(struct nouveau_object *, u32, void *, u32);
int nv50_pior_power(struct nv50_disp_priv *, int, u32);
int nv50_pior_power(NV50_DISP_MTHD_V1);
struct nv50_disp_base {
struct nouveau_parent base;
@ -104,14 +104,19 @@ struct nv50_disp_base {
u32 chan;
};
struct nv50_disp_chan_impl {
struct nouveau_ofuncs base;
int chid;
int (*attach)(struct nouveau_object *, struct nouveau_object *, u32);
void (*detach)(struct nouveau_object *, int);
};
struct nv50_disp_chan {
struct nouveau_namedb base;
int chid;
};
int nv50_disp_chan_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, int, int, void **);
void nv50_disp_chan_destroy(struct nv50_disp_chan *);
int nv50_disp_chan_map(struct nouveau_object *, u64 *, u32 *);
u32 nv50_disp_chan_rd32(struct nouveau_object *, u64);
void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32);
@ -120,20 +125,20 @@ void nv50_disp_chan_wr32(struct nouveau_object *, u64, u32);
#define nv50_disp_chan_fini(a,b) \
nouveau_namedb_fini(&(a)->base, (b))
int nv50_disp_dmac_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, u32, int, int, void **);
void nv50_disp_dmac_dtor(struct nouveau_object *);
struct nv50_disp_dmac {
struct nv50_disp_chan base;
struct nouveau_dmaobj *pushdma;
u32 push;
};
void nv50_disp_dmac_dtor(struct nouveau_object *);
struct nv50_disp_pioc {
struct nv50_disp_chan base;
};
void nv50_disp_pioc_dtor(struct nouveau_object *);
struct nv50_disp_mthd_list {
u32 mthd;
u32 addr;
@ -154,47 +159,67 @@ struct nv50_disp_mthd_chan {
} data[];
};
extern struct nouveau_ofuncs nv50_disp_mast_ofuncs;
extern struct nv50_disp_chan_impl nv50_disp_mast_ofuncs;
int nv50_disp_mast_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_base;
extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_sor;
extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_pior;
extern struct nouveau_ofuncs nv50_disp_sync_ofuncs;
extern struct nv50_disp_chan_impl nv50_disp_sync_ofuncs;
int nv50_disp_sync_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
extern const struct nv50_disp_mthd_list nv50_disp_sync_mthd_image;
extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs;
extern struct nv50_disp_chan_impl nv50_disp_ovly_ofuncs;
int nv50_disp_ovly_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base;
extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
extern struct nv50_disp_chan_impl nv50_disp_oimm_ofuncs;
int nv50_disp_oimm_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
extern struct nv50_disp_chan_impl nv50_disp_curs_ofuncs;
int nv50_disp_curs_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
int nv50_disp_base_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
void nv50_disp_base_dtor(struct nouveau_object *);
extern struct nouveau_omthds nv50_disp_base_omthds[];
extern struct nouveau_oclass nv50_disp_cclass;
void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head,
const struct nv50_disp_mthd_chan *);
void nv50_disp_intr_supervisor(struct work_struct *);
void nv50_disp_intr(struct nouveau_subdev *);
extern const struct nvkm_event_func nv50_disp_vblank_func;
extern const struct nv50_disp_mthd_chan nv84_disp_mast_mthd_chan;
extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac;
extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head;
extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan;
extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;
extern struct nouveau_omthds nv84_disp_base_omthds[];
extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;
extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs;
extern struct nv50_disp_chan_impl nvd0_disp_mast_ofuncs;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_base;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_dac;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_sor;
extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_pior;
extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs;
extern struct nv50_disp_chan_impl nvd0_disp_sync_ofuncs;
extern struct nv50_disp_chan_impl nvd0_disp_ovly_ofuncs;
extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;
extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
extern struct nouveau_omthds nvd0_disp_base_omthds[];
extern struct nv50_disp_chan_impl nvd0_disp_oimm_ofuncs;
extern struct nv50_disp_chan_impl nvd0_disp_curs_ofuncs;
extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
extern struct nouveau_oclass nvd0_disp_cclass;
void nvd0_disp_intr_supervisor(struct work_struct *);
void nvd0_disp_intr(struct nouveau_subdev *);
extern const struct nvkm_event_func nvd0_disp_vblank_func;
extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan;
extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan;

View File

@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "nv50.h"
@ -204,31 +204,17 @@ nv84_disp_ovly_mthd_chan = {
static struct nouveau_oclass
nv84_disp_sclass[] = {
{ NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
{ NV84_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
{ NV84_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
{ NV84_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
{ NV84_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
{ G82_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
{ G82_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
{ G82_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
{ G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
{ G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
struct nouveau_omthds
nv84_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
};
static struct nouveau_oclass
nv84_disp_base_oclass[] = {
{ NV84_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
{ G82_DISP, &nv50_disp_base_ofuncs },
{}
};
@ -276,9 +262,11 @@ nv84_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nv50_disp_vblank_func,
.base.outp = nv50_disp_outp_sclass,
.mthd.core = &nv84_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
.head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;

View File

@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "nv50.h"
@ -63,32 +63,17 @@ nv94_disp_mast_mthd_chan = {
static struct nouveau_oclass
nv94_disp_sclass[] = {
{ NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
{ NV94_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
{ NV94_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
{ NV94_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
{ NV94_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
{ GT206_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
{ GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
{ GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
{ G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
{ G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
static struct nouveau_omthds
nv94_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
};
static struct nouveau_oclass
nv94_disp_base_oclass[] = {
{ NV94_DISP_CLASS, &nv50_disp_base_ofuncs, nv94_disp_base_omthds },
{ GT206_DISP, &nv50_disp_base_ofuncs },
{}
};
@ -143,9 +128,11 @@ nv94_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nv50_disp_vblank_func,
.base.outp = nv94_disp_outp_sclass,
.mthd.core = &nv94_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
.head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;

View File

@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "nv50.h"
@ -80,17 +80,17 @@ nva0_disp_ovly_mthd_chan = {
static struct nouveau_oclass
nva0_disp_sclass[] = {
{ NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
{ NVA0_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
{ NVA0_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
{ NVA0_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
{ NVA0_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
{ GT200_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
{ GT200_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
{ GT200_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
{ G82_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
{ G82_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
nva0_disp_base_oclass[] = {
{ NVA0_DISP_CLASS, &nv50_disp_base_ofuncs, nv84_disp_base_omthds },
{ GT200_DISP, &nv50_disp_base_ofuncs },
{}
};
@ -138,9 +138,11 @@ nva0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nv50_disp_vblank_func,
.base.outp = nv50_disp_outp_sclass,
.mthd.core = &nv84_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nva0_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
.head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;

View File

@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "nv50.h"
@ -35,33 +35,17 @@
static struct nouveau_oclass
nva3_disp_sclass[] = {
{ NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs },
{ NVA3_DISP_SYNC_CLASS, &nv50_disp_sync_ofuncs },
{ NVA3_DISP_OVLY_CLASS, &nv50_disp_ovly_ofuncs },
{ NVA3_DISP_OIMM_CLASS, &nv50_disp_oimm_ofuncs },
{ NVA3_DISP_CURS_CLASS, &nv50_disp_curs_ofuncs },
{ GT214_DISP_CORE_CHANNEL_DMA, &nv50_disp_mast_ofuncs.base },
{ GT214_DISP_BASE_CHANNEL_DMA, &nv50_disp_sync_ofuncs.base },
{ GT214_DISP_OVERLAY_CHANNEL_DMA, &nv50_disp_ovly_ofuncs.base },
{ GT214_DISP_OVERLAY, &nv50_disp_oimm_ofuncs.base },
{ GT214_DISP_CURSOR, &nv50_disp_curs_ofuncs.base },
{}
};
static struct nouveau_omthds
nva3_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
};
static struct nouveau_oclass
nva3_disp_base_oclass[] = {
{ NVA3_DISP_CLASS, &nv50_disp_base_ofuncs, nva3_disp_base_omthds },
{ GT214_DISP, &nv50_disp_base_ofuncs },
{}
};
@ -110,9 +94,11 @@ nva3_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nv50_disp_vblank_func,
.base.outp = nv94_disp_outp_sclass,
.mthd.core = &nv94_disp_mast_mthd_chan,
.mthd.base = &nv84_disp_sync_mthd_chan,
.mthd.ovly = &nv84_disp_ovly_mthd_chan,
.mthd.prev = 0x000004,
.head.scanoutpos = nv50_disp_base_scanoutpos,
}.base.base;

View File

@ -23,9 +23,11 @@
*/
#include <core/object.h>
#include <core/client.h>
#include <core/parent.h>
#include <core/handle.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <engine/disp.h>
@ -264,30 +266,6 @@ nvd0_disp_mast_mthd_chan = {
}
};
static int
nvd0_disp_mast_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_mast_class *args = data;
struct nv50_disp_dmac *mast;
int ret;
if (size < sizeof(*args))
return -EINVAL;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
0, sizeof(*mast), (void **)&mast);
*pobject = nv_object(mast);
if (ret)
return ret;
nv_parent(mast)->object_attach = nvd0_disp_dmac_object_attach;
nv_parent(mast)->object_detach = nvd0_disp_dmac_object_detach;
return 0;
}
static int
nvd0_disp_mast_init(struct nouveau_object *object)
{
@ -342,14 +320,18 @@ nvd0_disp_mast_fini(struct nouveau_object *object, bool suspend)
return nv50_disp_chan_fini(&mast->base, suspend);
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nvd0_disp_mast_ofuncs = {
.ctor = nvd0_disp_mast_ctor,
.dtor = nv50_disp_dmac_dtor,
.init = nvd0_disp_mast_init,
.fini = nvd0_disp_mast_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_mast_ctor,
.base.dtor = nv50_disp_dmac_dtor,
.base.init = nvd0_disp_mast_init,
.base.fini = nvd0_disp_mast_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 0,
.attach = nvd0_disp_dmac_object_attach,
.detach = nvd0_disp_dmac_object_detach,
};
/*******************************************************************************
@ -431,40 +413,18 @@ nvd0_disp_sync_mthd_chan = {
}
};
static int
nvd0_disp_sync_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_sync_class *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_dmac *dmac;
int ret;
if (size < sizeof(*args) || args->head >= priv->head.nr)
return -EINVAL;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
1 + args->head, sizeof(*dmac),
(void **)&dmac);
*pobject = nv_object(dmac);
if (ret)
return ret;
nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nvd0_disp_sync_ofuncs = {
.ctor = nvd0_disp_sync_ctor,
.dtor = nv50_disp_dmac_dtor,
.init = nvd0_disp_dmac_init,
.fini = nvd0_disp_dmac_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_sync_ctor,
.base.dtor = nv50_disp_dmac_dtor,
.base.init = nvd0_disp_dmac_init,
.base.fini = nvd0_disp_dmac_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 1,
.attach = nvd0_disp_dmac_object_attach,
.detach = nvd0_disp_dmac_object_detach,
};
/*******************************************************************************
@ -533,63 +493,24 @@ nvd0_disp_ovly_mthd_chan = {
}
};
static int
nvd0_disp_ovly_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_ovly_class *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_dmac *dmac;
int ret;
if (size < sizeof(*args) || args->head >= priv->head.nr)
return -EINVAL;
ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf,
5 + args->head, sizeof(*dmac),
(void **)&dmac);
*pobject = nv_object(dmac);
if (ret)
return ret;
nv_parent(dmac)->object_attach = nvd0_disp_dmac_object_attach;
nv_parent(dmac)->object_detach = nvd0_disp_dmac_object_detach;
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nvd0_disp_ovly_ofuncs = {
.ctor = nvd0_disp_ovly_ctor,
.dtor = nv50_disp_dmac_dtor,
.init = nvd0_disp_dmac_init,
.fini = nvd0_disp_dmac_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_ovly_ctor,
.base.dtor = nv50_disp_dmac_dtor,
.base.init = nvd0_disp_dmac_init,
.base.fini = nvd0_disp_dmac_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 5,
.attach = nvd0_disp_dmac_object_attach,
.detach = nvd0_disp_dmac_object_detach,
};
/*******************************************************************************
* EVO PIO channel base class
******************************************************************************/
static int
nvd0_disp_pioc_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, int chid,
int length, void **pobject)
{
return nv50_disp_chan_create_(parent, engine, oclass, chid,
length, pobject);
}
static void
nvd0_disp_pioc_dtor(struct nouveau_object *object)
{
struct nv50_disp_pioc *pioc = (void *)object;
nv50_disp_chan_destroy(&pioc->base);
}
static int
nvd0_disp_pioc_init(struct nouveau_object *object)
{
@ -643,152 +564,68 @@ nvd0_disp_pioc_fini(struct nouveau_object *object, bool suspend)
* EVO immediate overlay channel objects
******************************************************************************/
static int
nvd0_disp_oimm_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_oimm_class *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_pioc *pioc;
int ret;
if (size < sizeof(*args) || args->head >= priv->head.nr)
return -EINVAL;
ret = nvd0_disp_pioc_create_(parent, engine, oclass, 9 + args->head,
sizeof(*pioc), (void **)&pioc);
*pobject = nv_object(pioc);
if (ret)
return ret;
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nvd0_disp_oimm_ofuncs = {
.ctor = nvd0_disp_oimm_ctor,
.dtor = nvd0_disp_pioc_dtor,
.init = nvd0_disp_pioc_init,
.fini = nvd0_disp_pioc_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_oimm_ctor,
.base.dtor = nv50_disp_pioc_dtor,
.base.init = nvd0_disp_pioc_init,
.base.fini = nvd0_disp_pioc_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 9,
};
/*******************************************************************************
* EVO cursor channel objects
******************************************************************************/
static int
nvd0_disp_curs_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_display_curs_class *args = data;
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_pioc *pioc;
int ret;
if (size < sizeof(*args) || args->head >= priv->head.nr)
return -EINVAL;
ret = nvd0_disp_pioc_create_(parent, engine, oclass, 13 + args->head,
sizeof(*pioc), (void **)&pioc);
*pobject = nv_object(pioc);
if (ret)
return ret;
return 0;
}
struct nouveau_ofuncs
struct nv50_disp_chan_impl
nvd0_disp_curs_ofuncs = {
.ctor = nvd0_disp_curs_ctor,
.dtor = nvd0_disp_pioc_dtor,
.init = nvd0_disp_pioc_init,
.fini = nvd0_disp_pioc_fini,
.rd32 = nv50_disp_chan_rd32,
.wr32 = nv50_disp_chan_wr32,
.base.ctor = nv50_disp_curs_ctor,
.base.dtor = nv50_disp_pioc_dtor,
.base.init = nvd0_disp_pioc_init,
.base.fini = nvd0_disp_pioc_fini,
.base.map = nv50_disp_chan_map,
.base.rd32 = nv50_disp_chan_rd32,
.base.wr32 = nv50_disp_chan_wr32,
.chid = 13,
};
/*******************************************************************************
* Base display object
******************************************************************************/
static int
nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd,
void *data, u32 size)
int
nvd0_disp_base_scanoutpos(NV50_DISP_MTHD_V0)
{
struct nv50_disp_priv *priv = (void *)object->engine;
struct nv04_display_scanoutpos *args = data;
const int head = (mthd & NV50_DISP_MTHD_HEAD);
u32 blanke, blanks, total;
if (size < sizeof(*args) || head >= priv->head.nr)
return -EINVAL;
total = nv_rd32(priv, 0x640414 + (head * 0x300));
blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
args->vblanke = (blanke & 0xffff0000) >> 16;
args->hblanke = (blanke & 0x0000ffff);
args->vblanks = (blanks & 0xffff0000) >> 16;
args->hblanks = (blanks & 0x0000ffff);
args->vtotal = ( total & 0xffff0000) >> 16;
args->htotal = ( total & 0x0000ffff);
args->time[0] = ktime_to_ns(ktime_get());
args->vline = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */
args->hline = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
return 0;
}
static void
nvd0_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)
{
nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
}
static void
nvd0_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
{
nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
}
static int
nvd0_disp_base_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_disp_priv *priv = (void *)engine;
struct nv50_disp_base *base;
const u32 total = nv_rd32(priv, 0x640414 + (head * 0x300));
const u32 blanke = nv_rd32(priv, 0x64041c + (head * 0x300));
const u32 blanks = nv_rd32(priv, 0x640420 + (head * 0x300));
union {
struct nv04_disp_scanoutpos_v0 v0;
} *args = data;
int ret;
ret = nouveau_parent_create(parent, engine, oclass, 0,
priv->sclass, 0, &base);
*pobject = nv_object(base);
if (ret)
nv_ioctl(object, "disp scanoutpos size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp scanoutpos vers %d\n", args->v0.version);
args->v0.vblanke = (blanke & 0xffff0000) >> 16;
args->v0.hblanke = (blanke & 0x0000ffff);
args->v0.vblanks = (blanks & 0xffff0000) >> 16;
args->v0.hblanks = (blanks & 0x0000ffff);
args->v0.vtotal = ( total & 0xffff0000) >> 16;
args->v0.htotal = ( total & 0x0000ffff);
args->v0.time[0] = ktime_to_ns(ktime_get());
args->v0.vline = /* vline read locks hline */
nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff;
args->v0.time[1] = ktime_to_ns(ktime_get());
args->v0.hline =
nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff;
} else
return ret;
priv->base.vblank->priv = priv;
priv->base.vblank->enable = nvd0_disp_base_vblank_enable;
priv->base.vblank->disable = nvd0_disp_base_vblank_disable;
return nouveau_ramht_new(nv_object(base), nv_object(base), 0x1000, 0,
&base->ramht);
}
static void
nvd0_disp_base_dtor(struct nouveau_object *object)
{
struct nv50_disp_base *base = (void *)object;
nouveau_ramht_ref(NULL, &base->ramht);
nouveau_parent_destroy(&base->base);
return 0;
}
static int
@ -874,41 +711,27 @@ nvd0_disp_base_fini(struct nouveau_object *object, bool suspend)
struct nouveau_ofuncs
nvd0_disp_base_ofuncs = {
.ctor = nvd0_disp_base_ctor,
.dtor = nvd0_disp_base_dtor,
.ctor = nv50_disp_base_ctor,
.dtor = nv50_disp_base_dtor,
.init = nvd0_disp_base_init,
.fini = nvd0_disp_base_fini,
};
struct nouveau_omthds
nvd0_disp_base_omthds[] = {
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nvd0_disp_base_scanoutpos },
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd },
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
{ DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd },
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
{},
.mthd = nv50_disp_base_mthd,
.ntfy = nouveau_disp_ntfy,
};
static struct nouveau_oclass
nvd0_disp_base_oclass[] = {
{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
{ GF110_DISP, &nvd0_disp_base_ofuncs },
{}
};
static struct nouveau_oclass
nvd0_disp_sclass[] = {
{ NVD0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
{ NVD0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
{ NVD0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
{ NVD0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
{ NVD0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
{ GF110_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
{ GF110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
{ GF110_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
{ GF110_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
{ GF110_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
@ -916,6 +739,27 @@ nvd0_disp_sclass[] = {
* Display engine implementation
******************************************************************************/
static void
nvd0_disp_vblank_init(struct nvkm_event *event, int type, int head)
{
struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);
}
static void
nvd0_disp_vblank_fini(struct nvkm_event *event, int type, int head)
{
struct nouveau_disp *disp = container_of(event, typeof(*disp), vblank);
nv_mask(disp, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);
}
const struct nvkm_event_func
nvd0_disp_vblank_func = {
.ctor = nouveau_disp_vblank_ctor,
.init = nvd0_disp_vblank_init,
.fini = nvd0_disp_vblank_fini,
};
static struct nvkm_output *
exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
@ -1343,7 +1187,7 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
if (mask & intr) {
u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));
if (stat & 0x00000001)
nouveau_event_trigger(priv->base.vblank, 1, i);
nouveau_disp_vblank(&priv->base, i);
nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);
nv_rd32(priv, 0x6100c0 + (i * 0x800));
}
@ -1396,9 +1240,11 @@ nvd0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nvd0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nvd0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
.head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;

View File

@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "nv50.h"
@ -200,17 +200,17 @@ nve0_disp_ovly_mthd_chan = {
static struct nouveau_oclass
nve0_disp_sclass[] = {
{ NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
{ NVE0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
{ NVE0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
{ NVE0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
{ NVE0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
{ GK104_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
{ GK104_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
{ GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
{ GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
{ GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
nve0_disp_base_oclass[] = {
{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
{ GK104_DISP, &nvd0_disp_base_ofuncs },
{}
};
@ -258,9 +258,11 @@ nve0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nve0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
.head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;

View File

@ -25,7 +25,7 @@
#include <engine/software.h>
#include <engine/disp.h>
#include <core/class.h>
#include <nvif/class.h>
#include "nv50.h"
@ -35,17 +35,17 @@
static struct nouveau_oclass
nvf0_disp_sclass[] = {
{ NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
{ NVF0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
{ NVF0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
{ NVF0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
{ NVF0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
{ GK110_DISP_CORE_CHANNEL_DMA, &nvd0_disp_mast_ofuncs.base },
{ GK110_DISP_BASE_CHANNEL_DMA, &nvd0_disp_sync_ofuncs.base },
{ GK104_DISP_OVERLAY_CONTROL_DMA, &nvd0_disp_ovly_ofuncs.base },
{ GK104_DISP_OVERLAY, &nvd0_disp_oimm_ofuncs.base },
{ GK104_DISP_CURSOR, &nvd0_disp_curs_ofuncs.base },
{}
};
static struct nouveau_oclass
nvf0_disp_base_oclass[] = {
{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },
{ GK110_DISP, &nvd0_disp_base_ofuncs },
{}
};
@ -93,9 +93,11 @@ nvf0_disp_oclass = &(struct nv50_disp_impl) {
.init = _nouveau_disp_init,
.fini = _nouveau_disp_fini,
},
.base.vblank = &nvd0_disp_vblank_func,
.base.outp = nvd0_disp_outp_sclass,
.mthd.core = &nve0_disp_mast_mthd_chan,
.mthd.base = &nvd0_disp_sync_mthd_chan,
.mthd.ovly = &nve0_disp_ovly_mthd_chan,
.mthd.prev = -0x020000,
.head.scanoutpos = nvd0_disp_base_scanoutpos,
}.base.base;

View File

@ -78,6 +78,7 @@ nvkm_output_create_(struct nouveau_object *parent,
outp->info = *dcbE;
outp->index = index;
outp->or = ffs(outp->info.or) - 1;
DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n",
dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ?

View File

@ -9,6 +9,7 @@ struct nvkm_output {
struct dcb_output info;
int index;
int or;
struct nouveau_i2c_port *port;
struct nouveau_i2c_port *edid;

View File

@ -22,6 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <nvif/event.h>
#include <subdev/i2c.h>
#include "outpdp.h"
@ -86,7 +89,7 @@ done:
atomic_set(&outp->lt.done, 0);
schedule_work(&outp->lt.work);
} else {
nouveau_event_get(outp->irq);
nvkm_notify_get(&outp->irq);
}
if (wait) {
@ -133,46 +136,59 @@ nvkm_output_dp_detect(struct nvkm_output_dp *outp)
}
}
static void
nvkm_output_dp_service_work(struct work_struct *work)
static int
nvkm_output_dp_hpd(struct nvkm_notify *notify)
{
struct nvkm_output_dp *outp = container_of(work, typeof(*outp), work);
struct nouveau_disp *disp = nouveau_disp(outp);
int type = atomic_xchg(&outp->pending, 0);
u32 send = 0;
struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd);
struct nvkm_output_dp *outp;
struct nouveau_disp *disp = nouveau_disp(conn);
const struct nvkm_i2c_ntfy_rep *line = notify->data;
struct nvif_notify_conn_rep_v0 rep = {};
if (type & (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG)) {
nvkm_output_dp_detect(outp);
if (type & NVKM_I2C_UNPLUG)
send |= NVKM_HPD_UNPLUG;
if (type & NVKM_I2C_PLUG)
send |= NVKM_HPD_PLUG;
nouveau_event_get(outp->base.conn->hpd.event);
list_for_each_entry(outp, &disp->outp, base.head) {
if (outp->base.conn == conn &&
outp->info.type == DCB_OUTPUT_DP) {
DBG("HPD: %d\n", line->mask);
nvkm_output_dp_detect(outp);
if (line->mask & NVKM_I2C_UNPLUG)
rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG;
if (line->mask & NVKM_I2C_PLUG)
rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG;
nvkm_event_send(&disp->hpd, rep.mask, conn->index,
&rep, sizeof(rep));
return NVKM_NOTIFY_KEEP;
}
}
if (type & NVKM_I2C_IRQ) {
nvkm_output_dp_train(&outp->base, 0, true);
send |= NVKM_HPD_IRQ;
}
nouveau_event_trigger(disp->hpd, send, outp->base.info.connector);
WARN_ON(1);
return NVKM_NOTIFY_DROP;
}
static int
nvkm_output_dp_service(void *data, u32 type, int index)
nvkm_output_dp_irq(struct nvkm_notify *notify)
{
struct nvkm_output_dp *outp = data;
DBG("HPD: %d\n", type);
atomic_or(type, &outp->pending);
schedule_work(&outp->work);
return NVKM_EVENT_DROP;
struct nvkm_output_dp *outp = container_of(notify, typeof(*outp), irq);
struct nouveau_disp *disp = nouveau_disp(outp);
const struct nvkm_i2c_ntfy_rep *line = notify->data;
struct nvif_notify_conn_rep_v0 rep = {
.mask = NVIF_NOTIFY_CONN_V0_IRQ,
};
int index = outp->base.info.connector;
DBG("IRQ: %d\n", line->mask);
nvkm_output_dp_train(&outp->base, 0, true);
nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
return NVKM_NOTIFY_DROP;
}
int
_nvkm_output_dp_fini(struct nouveau_object *object, bool suspend)
{
struct nvkm_output_dp *outp = (void *)object;
nouveau_event_put(outp->irq);
nvkm_notify_put(&outp->irq);
nvkm_output_dp_enable(outp, false);
return nvkm_output_fini(&outp->base, suspend);
}
@ -189,7 +205,7 @@ void
_nvkm_output_dp_dtor(struct nouveau_object *object)
{
struct nvkm_output_dp *outp = (void *)object;
nouveau_event_ref(NULL, &outp->irq);
nvkm_notify_fini(&outp->irq);
nvkm_output_destroy(&outp->base);
}
@ -213,7 +229,7 @@ nvkm_output_dp_create_(struct nouveau_object *parent,
if (ret)
return ret;
nouveau_event_ref(NULL, &outp->base.conn->hpd.event);
nvkm_notify_fini(&outp->base.conn->hpd);
/* access to the aux channel is not optional... */
if (!outp->base.edid) {
@ -238,20 +254,28 @@ nvkm_output_dp_create_(struct nouveau_object *parent,
atomic_set(&outp->lt.done, 0);
/* link maintenance */
ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_IRQ, outp->base.edid->index,
nvkm_output_dp_service, outp, &outp->irq);
ret = nvkm_notify_init(&i2c->event, nvkm_output_dp_irq, true,
&(struct nvkm_i2c_ntfy_req) {
.mask = NVKM_I2C_IRQ,
.port = outp->base.edid->index,
},
sizeof(struct nvkm_i2c_ntfy_req),
sizeof(struct nvkm_i2c_ntfy_rep),
&outp->irq);
if (ret) {
ERR("error monitoring aux irq event: %d\n", ret);
return ret;
}
INIT_WORK(&outp->work, nvkm_output_dp_service_work);
/* hotplug detect, replaces gpio-based mechanism with aux events */
ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_PLUG | NVKM_I2C_UNPLUG,
outp->base.edid->index,
nvkm_output_dp_service, outp,
&outp->base.conn->hpd.event);
ret = nvkm_notify_init(&i2c->event, nvkm_output_dp_hpd, true,
&(struct nvkm_i2c_ntfy_req) {
.mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG,
.port = outp->base.edid->index,
},
sizeof(struct nvkm_i2c_ntfy_req),
sizeof(struct nvkm_i2c_ntfy_rep),
&outp->base.conn->hpd);
if (ret) {
ERR("error monitoring aux hpd events: %d\n", ret);
return ret;

View File

@ -12,10 +12,7 @@ struct nvkm_output_dp {
struct nvbios_dpout info;
u8 version;
struct nouveau_eventh *irq;
struct nouveau_eventh *hpd;
struct work_struct work;
atomic_t pending;
struct nvkm_notify irq;
bool present;
u8 dpcd[16];

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@ -143,38 +144,29 @@ nv50_pior_dp_impl = {
*****************************************************************************/
int
nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data)
nv50_pior_power(NV50_DISP_MTHD_V1)
{
const u32 stat = data & NV50_DISP_PIOR_PWR_STATE;
const u32 soff = (or * 0x800);
nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | stat);
nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
return 0;
}
int
nv50_pior_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
{
struct nv50_disp_priv *priv = (void *)object->engine;
const u8 type = (mthd & NV50_DISP_PIOR_MTHD_TYPE) >> 12;
const u8 or = (mthd & NV50_DISP_PIOR_MTHD_OR);
u32 *data = args;
const u32 soff = outp->or * 0x800;
union {
struct nv50_disp_pior_pwr_v0 v0;
} *args = data;
u32 ctrl, type;
int ret;
if (size < sizeof(u32))
return -EINVAL;
nv_ioctl(object, "disp pior pwr size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp pior pwr vers %d state %d type %x\n",
args->v0.version, args->v0.state, args->v0.type);
if (args->v0.type > 0x0f)
return -EINVAL;
ctrl = !!args->v0.state;
type = args->v0.type;
} else
return ret;
mthd &= ~NV50_DISP_PIOR_MTHD_TYPE;
mthd &= ~NV50_DISP_PIOR_MTHD_OR;
switch (mthd) {
case NV50_DISP_PIOR_PWR:
ret = priv->pior.power(priv, or, data[0]);
priv->pior.type[or] = type;
break;
default:
return -EINVAL;
}
return ret;
nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | ctrl);
nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000);
priv->pior.type[outp->or] = type;
return 0;
}

View File

@ -11,6 +11,7 @@ struct nouveau_disp_impl {
struct nouveau_oclass base;
struct nouveau_oclass **outp;
struct nouveau_oclass **conn;
const struct nvkm_event_func *vblank;
};
#define nouveau_disp_create(p,e,c,h,i,x,d) \
@ -39,4 +40,8 @@ int _nouveau_disp_fini(struct nouveau_object *, bool);
extern struct nouveau_oclass *nvkm_output_oclass;
extern struct nouveau_oclass *nvkm_connector_oclass;
int nouveau_disp_vblank_ctor(void *data, u32 size, struct nvkm_notify *);
void nouveau_disp_vblank(struct nouveau_disp *, int head);
int nouveau_disp_ntfy(struct nouveau_object *, u32, struct nvkm_event **);
#endif

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@ -32,77 +33,26 @@
#include "nv50.h"
int
nv50_sor_power(struct nv50_disp_priv *priv, int or, u32 data)
nv50_sor_power(NV50_DISP_MTHD_V1)
{
const u32 stat = data & NV50_DISP_SOR_PWR_STATE;
const u32 soff = (or * 0x800);
union {
struct nv50_disp_sor_pwr_v0 v0;
} *args = data;
const u32 soff = outp->or * 0x800;
u32 stat;
int ret;
nv_ioctl(object, "disp sor pwr size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(object, "disp sor pwr vers %d state %d\n",
args->v0.version, args->v0.state);
stat = !!args->v0.state;
} else
return ret;
nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
nv_mask(priv, 0x61c004 + soff, 0x80000001, 0x80000000 | stat);
nv_wait(priv, 0x61c004 + soff, 0x80000000, 0x00000000);
nv_wait(priv, 0x61c030 + soff, 0x10000000, 0x00000000);
return 0;
}
int
nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
{
struct nv50_disp_priv *priv = (void *)object->engine;
const u8 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12;
const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3;
const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2;
const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR);
const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or);
struct nvkm_output *outp = NULL, *temp;
u32 data;
int ret = -EINVAL;
if (size < sizeof(u32))
return -EINVAL;
data = *(u32 *)args;
list_for_each_entry(temp, &priv->base.outp, head) {
if ((temp->info.hasht & 0xff) == type &&
(temp->info.hashm & mask) == mask) {
outp = temp;
break;
}
}
switch (mthd & ~0x3f) {
case NV50_DISP_SOR_PWR:
ret = priv->sor.power(priv, or, data);
break;
case NVA3_DISP_SOR_HDA_ELD:
ret = priv->sor.hda_eld(priv, or, args, size);
break;
case NV84_DISP_SOR_HDMI_PWR:
ret = priv->sor.hdmi(priv, head, or, data);
break;
case NV50_DISP_SOR_LVDS_SCRIPT:
priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;
ret = 0;
break;
case NV94_DISP_SOR_DP_PWR:
if (outp) {
struct nvkm_output_dp *outpdp = (void *)outp;
switch (data) {
case NV94_DISP_SOR_DP_PWR_STATE_OFF:
nouveau_event_put(outpdp->irq);
((struct nvkm_output_dp_impl *)nv_oclass(outp))
->lnk_pwr(outpdp, 0);
atomic_set(&outpdp->lt.done, 0);
break;
case NV94_DISP_SOR_DP_PWR_STATE_ON:
nvkm_output_dp_train(&outpdp->base, 0, true);
break;
default:
return -EINVAL;
}
}
break;
default:
BUG_ON(1);
}
return ret;
}

View File

@ -23,7 +23,6 @@
*/
#include <core/os.h>
#include <core/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>

View File

@ -23,7 +23,6 @@
*/
#include <core/os.h>
#include <core/class.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>

View File

@ -23,98 +23,143 @@
*/
#include <core/object.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/fb.h>
#include <engine/dmaobj.h>
#include <subdev/instmem.h>
#include "priv.h"
static int
nouveau_dmaobj_ctor(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
nvkm_dmaobj_bind(struct nouveau_dmaobj *dmaobj, struct nouveau_object *parent,
struct nouveau_gpuobj **pgpuobj)
{
struct nouveau_dmaeng *dmaeng = (void *)engine;
const struct nvkm_dmaeng_impl *impl = (void *)
nv_oclass(nv_object(dmaobj)->engine);
int ret = 0;
if (nv_object(dmaobj) == parent) { /* ctor bind */
if (nv_mclass(parent->parent) == NV_DEVICE) {
/* delayed, or no, binding */
return 0;
}
ret = impl->bind(dmaobj, parent, pgpuobj);
if (ret == 0)
nouveau_object_ref(NULL, &parent);
return ret;
}
return impl->bind(dmaobj, parent, pgpuobj);
}
int
nvkm_dmaobj_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, void **pdata, u32 *psize,
int length, void **pobject)
{
union {
struct nv_dma_v0 v0;
} *args = *pdata;
struct nouveau_instmem *instmem = nouveau_instmem(parent);
struct nouveau_client *client = nouveau_client(parent);
struct nouveau_device *device = nv_device(parent);
struct nouveau_fb *pfb = nouveau_fb(parent);
struct nouveau_dmaobj *dmaobj;
struct nouveau_gpuobj *gpuobj;
struct nv_dma_class *args = data;
void *data = *pdata;
u32 size = *psize;
int ret;
if (size < sizeof(*args))
return -EINVAL;
ret = nouveau_object_create(parent, engine, oclass, 0, &dmaobj);
*pobject = nv_object(dmaobj);
ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject);
dmaobj = *pobject;
if (ret)
return ret;
switch (args->flags & NV_DMA_TARGET_MASK) {
case NV_DMA_TARGET_VM:
nv_ioctl(parent, "create dma size %d\n", *psize);
if (nvif_unpack(args->v0, 0, 0, true)) {
nv_ioctl(parent, "create dma vers %d target %d access %d "
"start %016llx limit %016llx\n",
args->v0.version, args->v0.target, args->v0.access,
args->v0.start, args->v0.limit);
dmaobj->target = args->v0.target;
dmaobj->access = args->v0.access;
dmaobj->start = args->v0.start;
dmaobj->limit = args->v0.limit;
} else
return ret;
*pdata = data;
*psize = size;
if (dmaobj->start > dmaobj->limit)
return -EINVAL;
switch (dmaobj->target) {
case NV_DMA_V0_TARGET_VM:
dmaobj->target = NV_MEM_TARGET_VM;
break;
case NV_DMA_TARGET_VRAM:
case NV_DMA_V0_TARGET_VRAM:
if (!client->super) {
if (dmaobj->limit >= pfb->ram->size - instmem->reserved)
return -EACCES;
if (device->card_type >= NV_50)
return -EACCES;
}
dmaobj->target = NV_MEM_TARGET_VRAM;
break;
case NV_DMA_TARGET_PCI:
case NV_DMA_V0_TARGET_PCI:
if (!client->super)
return -EACCES;
dmaobj->target = NV_MEM_TARGET_PCI;
break;
case NV_DMA_TARGET_PCI_US:
case NV_DMA_TARGET_AGP:
case NV_DMA_V0_TARGET_PCI_US:
case NV_DMA_V0_TARGET_AGP:
if (!client->super)
return -EACCES;
dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP;
break;
default:
return -EINVAL;
}
switch (args->flags & NV_DMA_ACCESS_MASK) {
case NV_DMA_ACCESS_VM:
switch (dmaobj->access) {
case NV_DMA_V0_ACCESS_VM:
dmaobj->access = NV_MEM_ACCESS_VM;
break;
case NV_DMA_ACCESS_RD:
case NV_DMA_V0_ACCESS_RD:
dmaobj->access = NV_MEM_ACCESS_RO;
break;
case NV_DMA_ACCESS_WR:
case NV_DMA_V0_ACCESS_WR:
dmaobj->access = NV_MEM_ACCESS_WO;
break;
case NV_DMA_ACCESS_RDWR:
case NV_DMA_V0_ACCESS_RDWR:
dmaobj->access = NV_MEM_ACCESS_RW;
break;
default:
return -EINVAL;
}
dmaobj->start = args->start;
dmaobj->limit = args->limit;
dmaobj->conf0 = args->conf0;
switch (nv_mclass(parent)) {
case NV_DEVICE_CLASS:
/* delayed, or no, binding */
break;
default:
ret = dmaeng->bind(dmaeng, *pobject, dmaobj, &gpuobj);
if (ret == 0) {
nouveau_object_ref(NULL, pobject);
*pobject = nv_object(gpuobj);
}
break;
}
return ret;
}
static struct nouveau_ofuncs
nouveau_dmaobj_ofuncs = {
.ctor = nouveau_dmaobj_ctor,
.dtor = nouveau_object_destroy,
.init = nouveau_object_init,
.fini = nouveau_object_fini,
};
int
_nvkm_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
const struct nvkm_dmaeng_impl *impl = (void *)oclass;
struct nouveau_dmaeng *dmaeng;
int ret;
struct nouveau_oclass
nouveau_dmaobj_sclass[] = {
{ NV_DMA_FROM_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
{ NV_DMA_TO_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
{ NV_DMA_IN_MEMORY_CLASS, &nouveau_dmaobj_ofuncs },
{}
};
ret = nouveau_engine_create(parent, engine, oclass, true, "DMAOBJ",
"dmaobj", &dmaeng);
*pobject = nv_object(dmaeng);
if (ret)
return ret;
nv_engine(dmaeng)->sclass = impl->sclass;
dmaeng->bind = nvkm_dmaobj_bind;
return 0;
}

View File

@ -23,121 +23,143 @@
*/
#include <core/gpuobj.h>
#include <core/class.h>
#include <nvif/class.h>
#include <subdev/fb.h>
#include <subdev/vm/nv04.h>
#include <engine/dmaobj.h>
#include "priv.h"
struct nv04_dmaeng_priv {
struct nouveau_dmaeng base;
struct nv04_dmaobj_priv {
struct nouveau_dmaobj base;
bool clone;
u32 flags0;
u32 flags2;
};
static int
nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
nv04_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaeng);
struct nv04_dmaobj_priv *priv = (void *)dmaobj;
struct nouveau_gpuobj *gpuobj;
u32 flags0 = nv_mclass(dmaobj);
u32 flags2 = 0x00000000;
u64 offset = dmaobj->start & 0xfffff000;
u64 adjust = dmaobj->start & 0x00000fff;
u32 length = dmaobj->limit - dmaobj->start;
u64 offset = priv->base.start & 0xfffff000;
u64 adjust = priv->base.start & 0x00000fff;
u32 length = priv->base.limit - priv->base.start;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
case NV03_CHANNEL_DMA_CLASS:
case NV10_CHANNEL_DMA_CLASS:
case NV17_CHANNEL_DMA_CLASS:
case NV40_CHANNEL_DMA_CLASS:
case NV03_CHANNEL_DMA:
case NV10_CHANNEL_DMA:
case NV17_CHANNEL_DMA:
case NV40_CHANNEL_DMA:
break;
default:
return -EINVAL;
}
}
if (dmaobj->target == NV_MEM_TARGET_VM) {
if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass) {
struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
if (!dmaobj->start)
return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
offset = nv_ro32(pgt, 8 + (offset >> 10));
offset &= 0xfffff000;
}
dmaobj->target = NV_MEM_TARGET_PCI;
dmaobj->access = NV_MEM_ACCESS_RW;
}
switch (dmaobj->target) {
case NV_MEM_TARGET_VRAM:
flags0 |= 0x00003000;
break;
case NV_MEM_TARGET_PCI:
flags0 |= 0x00023000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
flags0 |= 0x00033000;
break;
default:
return -EINVAL;
}
switch (dmaobj->access) {
case NV_MEM_ACCESS_RO:
flags0 |= 0x00004000;
break;
case NV_MEM_ACCESS_WO:
flags0 |= 0x00008000;
case NV_MEM_ACCESS_RW:
flags2 |= 0x00000002;
break;
default:
return -EINVAL;
if (priv->clone) {
struct nv04_vmmgr_priv *vmm = nv04_vmmgr(dmaobj);
struct nouveau_gpuobj *pgt = vmm->vm->pgt[0].obj[0];
if (!dmaobj->start)
return nouveau_gpuobj_dup(parent, pgt, pgpuobj);
offset = nv_ro32(pgt, 8 + (offset >> 10));
offset &= 0xfffff000;
}
ret = nouveau_gpuobj_new(parent, parent, 16, 16, 0, &gpuobj);
*pgpuobj = gpuobj;
if (ret == 0) {
nv_wo32(*pgpuobj, 0x00, flags0 | (adjust << 20));
nv_wo32(*pgpuobj, 0x00, priv->flags0 | (adjust << 20));
nv_wo32(*pgpuobj, 0x04, length);
nv_wo32(*pgpuobj, 0x08, flags2 | offset);
nv_wo32(*pgpuobj, 0x0c, flags2 | offset);
nv_wo32(*pgpuobj, 0x08, priv->flags2 | offset);
nv_wo32(*pgpuobj, 0x0c, priv->flags2 | offset);
}
return ret;
}
static int
nv04_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv04_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv04_dmaeng_priv *priv;
struct nouveau_dmaeng *dmaeng = (void *)engine;
struct nv04_vmmgr_priv *vmm = nv04_vmmgr(engine);
struct nv04_dmaobj_priv *priv;
int ret;
ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
*pobject = nv_object(priv);
if (ret)
if (ret || (ret = -ENOSYS, size))
return ret;
nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
priv->base.bind = nv04_dmaobj_bind;
return 0;
if (priv->base.target == NV_MEM_TARGET_VM) {
if (nv_object(vmm)->oclass == &nv04_vmmgr_oclass)
priv->clone = true;
priv->base.target = NV_MEM_TARGET_PCI;
priv->base.access = NV_MEM_ACCESS_RW;
}
priv->flags0 = nv_mclass(priv);
switch (priv->base.target) {
case NV_MEM_TARGET_VRAM:
priv->flags0 |= 0x00003000;
break;
case NV_MEM_TARGET_PCI:
priv->flags0 |= 0x00023000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
priv->flags0 |= 0x00033000;
break;
default:
return -EINVAL;
}
switch (priv->base.access) {
case NV_MEM_ACCESS_RO:
priv->flags0 |= 0x00004000;
break;
case NV_MEM_ACCESS_WO:
priv->flags0 |= 0x00008000;
case NV_MEM_ACCESS_RW:
priv->flags2 |= 0x00000002;
break;
default:
return -EINVAL;
}
return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
struct nouveau_oclass
nv04_dmaeng_oclass = {
.handle = NV_ENGINE(DMAOBJ, 0x04),
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv04_dmaeng_ctor,
.dtor = _nouveau_dmaeng_dtor,
.init = _nouveau_dmaeng_init,
.fini = _nouveau_dmaeng_fini,
},
static struct nouveau_ofuncs
nv04_dmaobj_ofuncs = {
.ctor = nv04_dmaobj_ctor,
.dtor = _nvkm_dmaobj_dtor,
.init = _nvkm_dmaobj_init,
.fini = _nvkm_dmaobj_fini,
};
static struct nouveau_oclass
nv04_dmaeng_sclass[] = {
{ NV_DMA_FROM_MEMORY, &nv04_dmaobj_ofuncs },
{ NV_DMA_TO_MEMORY, &nv04_dmaobj_ofuncs },
{ NV_DMA_IN_MEMORY, &nv04_dmaobj_ofuncs },
{}
};
struct nouveau_oclass *
nv04_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
.base.handle = NV_ENGINE(DMAOBJ, 0x04),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = _nvkm_dmaeng_ctor,
.dtor = _nvkm_dmaeng_dtor,
.init = _nvkm_dmaeng_init,
.fini = _nvkm_dmaeng_fini,
},
.sclass = nv04_dmaeng_sclass,
.bind = nv04_dmaobj_bind,
}.base;

View File

@ -22,140 +22,176 @@
* Authors: Ben Skeggs
*/
#include <core/client.h>
#include <core/gpuobj.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/fb.h>
#include <engine/dmaobj.h>
struct nv50_dmaeng_priv {
struct nouveau_dmaeng base;
#include "priv.h"
struct nv50_dmaobj_priv {
struct nouveau_dmaobj base;
u32 flags0;
u32 flags5;
};
static int
nv50_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
nv50_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
u32 flags0 = nv_mclass(dmaobj);
u32 flags5 = 0x00000000;
struct nv50_dmaobj_priv *priv = (void *)dmaobj;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
case NV50_CHANNEL_DMA_CLASS:
case NV84_CHANNEL_DMA_CLASS:
case NV50_CHANNEL_IND_CLASS:
case NV84_CHANNEL_IND_CLASS:
case NV50_DISP_MAST_CLASS:
case NV84_DISP_MAST_CLASS:
case NV94_DISP_MAST_CLASS:
case NVA0_DISP_MAST_CLASS:
case NVA3_DISP_MAST_CLASS:
case NV50_DISP_SYNC_CLASS:
case NV84_DISP_SYNC_CLASS:
case NV94_DISP_SYNC_CLASS:
case NVA0_DISP_SYNC_CLASS:
case NVA3_DISP_SYNC_CLASS:
case NV50_DISP_OVLY_CLASS:
case NV84_DISP_OVLY_CLASS:
case NV94_DISP_OVLY_CLASS:
case NVA0_DISP_OVLY_CLASS:
case NVA3_DISP_OVLY_CLASS:
case NV40_CHANNEL_DMA:
case NV50_CHANNEL_GPFIFO:
case G82_CHANNEL_GPFIFO:
case NV50_DISP_CORE_CHANNEL_DMA:
case G82_DISP_CORE_CHANNEL_DMA:
case GT206_DISP_CORE_CHANNEL_DMA:
case GT200_DISP_CORE_CHANNEL_DMA:
case GT214_DISP_CORE_CHANNEL_DMA:
case NV50_DISP_BASE_CHANNEL_DMA:
case G82_DISP_BASE_CHANNEL_DMA:
case GT200_DISP_BASE_CHANNEL_DMA:
case GT214_DISP_BASE_CHANNEL_DMA:
case NV50_DISP_OVERLAY_CHANNEL_DMA:
case G82_DISP_OVERLAY_CHANNEL_DMA:
case GT200_DISP_OVERLAY_CHANNEL_DMA:
case GT214_DISP_OVERLAY_CHANNEL_DMA:
break;
default:
return -EINVAL;
}
}
if (!(dmaobj->conf0 & NV50_DMA_CONF0_ENABLE)) {
if (dmaobj->target == NV_MEM_TARGET_VM) {
dmaobj->conf0 = NV50_DMA_CONF0_PRIV_VM;
dmaobj->conf0 |= NV50_DMA_CONF0_PART_VM;
dmaobj->conf0 |= NV50_DMA_CONF0_COMP_VM;
dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_VM;
} else {
dmaobj->conf0 = NV50_DMA_CONF0_PRIV_US;
dmaobj->conf0 |= NV50_DMA_CONF0_PART_256;
dmaobj->conf0 |= NV50_DMA_CONF0_COMP_NONE;
dmaobj->conf0 |= NV50_DMA_CONF0_TYPE_LINEAR;
}
}
flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_COMP) << 22;
flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_TYPE) << 22;
flags0 |= (dmaobj->conf0 & NV50_DMA_CONF0_PRIV);
flags5 |= (dmaobj->conf0 & NV50_DMA_CONF0_PART);
switch (dmaobj->target) {
case NV_MEM_TARGET_VM:
flags0 |= 0x00000000;
break;
case NV_MEM_TARGET_VRAM:
flags0 |= 0x00010000;
break;
case NV_MEM_TARGET_PCI:
flags0 |= 0x00020000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
flags0 |= 0x00030000;
break;
default:
return -EINVAL;
}
switch (dmaobj->access) {
case NV_MEM_ACCESS_VM:
break;
case NV_MEM_ACCESS_RO:
flags0 |= 0x00040000;
break;
case NV_MEM_ACCESS_WO:
case NV_MEM_ACCESS_RW:
flags0 |= 0x00080000;
break;
}
ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
if (ret == 0) {
nv_wo32(*pgpuobj, 0x00, flags0);
nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
upper_32_bits(dmaobj->start));
nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
upper_32_bits(priv->base.start));
nv_wo32(*pgpuobj, 0x10, 0x00000000);
nv_wo32(*pgpuobj, 0x14, flags5);
nv_wo32(*pgpuobj, 0x14, priv->flags5);
}
return ret;
}
static int
nv50_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nv50_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_dmaeng_priv *priv;
struct nouveau_dmaeng *dmaeng = (void *)engine;
union {
struct nv50_dma_v0 v0;
} *args;
struct nv50_dmaobj_priv *priv;
u32 user, part, comp, kind;
int ret;
ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
args = data;
nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
priv->base.bind = nv50_dmaobj_bind;
return 0;
nv_ioctl(parent, "create nv50 dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create nv50 dma vers %d priv %d part %d "
"comp %d kind %02x\n", args->v0.version,
args->v0.priv, args->v0.part, args->v0.comp,
args->v0.kind);
user = args->v0.priv;
part = args->v0.part;
comp = args->v0.comp;
kind = args->v0.kind;
} else
if (size == 0) {
if (priv->base.target != NV_MEM_TARGET_VM) {
user = NV50_DMA_V0_PRIV_US;
part = NV50_DMA_V0_PART_256;
comp = NV50_DMA_V0_COMP_NONE;
kind = NV50_DMA_V0_KIND_PITCH;
} else {
user = NV50_DMA_V0_PRIV_VM;
part = NV50_DMA_V0_PART_VM;
comp = NV50_DMA_V0_COMP_VM;
kind = NV50_DMA_V0_KIND_VM;
}
} else
return ret;
if (user > 2 || part > 2 || comp > 3 || kind > 0x7f)
return -EINVAL;
priv->flags0 = (comp << 29) | (kind << 22) | (user << 20);
priv->flags5 = (part << 16);
switch (priv->base.target) {
case NV_MEM_TARGET_VM:
priv->flags0 |= 0x00000000;
break;
case NV_MEM_TARGET_VRAM:
priv->flags0 |= 0x00010000;
break;
case NV_MEM_TARGET_PCI:
priv->flags0 |= 0x00020000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
priv->flags0 |= 0x00030000;
break;
default:
return -EINVAL;
}
switch (priv->base.access) {
case NV_MEM_ACCESS_VM:
break;
case NV_MEM_ACCESS_RO:
priv->flags0 |= 0x00040000;
break;
case NV_MEM_ACCESS_WO:
case NV_MEM_ACCESS_RW:
priv->flags0 |= 0x00080000;
break;
default:
return -EINVAL;
}
return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
struct nouveau_oclass
nv50_dmaeng_oclass = {
.handle = NV_ENGINE(DMAOBJ, 0x50),
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv50_dmaeng_ctor,
.dtor = _nouveau_dmaeng_dtor,
.init = _nouveau_dmaeng_init,
.fini = _nouveau_dmaeng_fini,
},
static struct nouveau_ofuncs
nv50_dmaobj_ofuncs = {
.ctor = nv50_dmaobj_ctor,
.dtor = _nvkm_dmaobj_dtor,
.init = _nvkm_dmaobj_init,
.fini = _nvkm_dmaobj_fini,
};
static struct nouveau_oclass
nv50_dmaeng_sclass[] = {
{ NV_DMA_FROM_MEMORY, &nv50_dmaobj_ofuncs },
{ NV_DMA_TO_MEMORY, &nv50_dmaobj_ofuncs },
{ NV_DMA_IN_MEMORY, &nv50_dmaobj_ofuncs },
{}
};
struct nouveau_oclass *
nv50_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
.base.handle = NV_ENGINE(DMAOBJ, 0x50),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = _nvkm_dmaeng_ctor,
.dtor = _nvkm_dmaeng_dtor,
.init = _nvkm_dmaeng_init,
.fini = _nvkm_dmaeng_fini,
},
.sclass = nv50_dmaeng_sclass,
.bind = nv50_dmaobj_bind,
}.base;

View File

@ -22,32 +22,35 @@
* Authors: Ben Skeggs
*/
#include <core/client.h>
#include <core/device.h>
#include <core/gpuobj.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/fb.h>
#include <engine/dmaobj.h>
struct nvc0_dmaeng_priv {
struct nouveau_dmaeng base;
#include "priv.h"
struct nvc0_dmaobj_priv {
struct nouveau_dmaobj base;
u32 flags0;
u32 flags5;
};
static int
nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
nvc0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
u32 flags0 = nv_mclass(dmaobj);
u32 flags5 = 0x00000000;
struct nvc0_dmaobj_priv *priv = (void *)dmaobj;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
case NVA3_DISP_MAST_CLASS:
case NVA3_DISP_SYNC_CLASS:
case NVA3_DISP_OVLY_CLASS:
case GT214_DISP_CORE_CHANNEL_DMA:
case GT214_DISP_BASE_CHANNEL_DMA:
case GT214_DISP_OVERLAY_CHANNEL_DMA:
break;
default:
return -EINVAL;
@ -55,89 +58,122 @@ nvc0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
} else
return 0;
if (!(dmaobj->conf0 & NVC0_DMA_CONF0_ENABLE)) {
if (dmaobj->target == NV_MEM_TARGET_VM) {
dmaobj->conf0 = NVC0_DMA_CONF0_PRIV_VM;
dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_VM;
} else {
dmaobj->conf0 = NVC0_DMA_CONF0_PRIV_US;
dmaobj->conf0 |= NVC0_DMA_CONF0_TYPE_LINEAR;
dmaobj->conf0 |= 0x00020000;
}
}
flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_TYPE) << 22;
flags0 |= (dmaobj->conf0 & NVC0_DMA_CONF0_PRIV);
flags5 |= (dmaobj->conf0 & NVC0_DMA_CONF0_UNKN);
switch (dmaobj->target) {
case NV_MEM_TARGET_VM:
flags0 |= 0x00000000;
break;
case NV_MEM_TARGET_VRAM:
flags0 |= 0x00010000;
break;
case NV_MEM_TARGET_PCI:
flags0 |= 0x00020000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
flags0 |= 0x00030000;
break;
default:
return -EINVAL;
}
switch (dmaobj->access) {
case NV_MEM_ACCESS_VM:
break;
case NV_MEM_ACCESS_RO:
flags0 |= 0x00040000;
break;
case NV_MEM_ACCESS_WO:
case NV_MEM_ACCESS_RW:
flags0 |= 0x00080000;
break;
}
ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
if (ret == 0) {
nv_wo32(*pgpuobj, 0x00, flags0);
nv_wo32(*pgpuobj, 0x04, lower_32_bits(dmaobj->limit));
nv_wo32(*pgpuobj, 0x08, lower_32_bits(dmaobj->start));
nv_wo32(*pgpuobj, 0x0c, upper_32_bits(dmaobj->limit) << 24 |
upper_32_bits(dmaobj->start));
nv_wo32(*pgpuobj, 0x00, priv->flags0 | nv_mclass(dmaobj));
nv_wo32(*pgpuobj, 0x04, lower_32_bits(priv->base.limit));
nv_wo32(*pgpuobj, 0x08, lower_32_bits(priv->base.start));
nv_wo32(*pgpuobj, 0x0c, upper_32_bits(priv->base.limit) << 24 |
upper_32_bits(priv->base.start));
nv_wo32(*pgpuobj, 0x10, 0x00000000);
nv_wo32(*pgpuobj, 0x14, flags5);
nv_wo32(*pgpuobj, 0x14, priv->flags5);
}
return ret;
}
static int
nvc0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nvc0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nvc0_dmaeng_priv *priv;
struct nouveau_dmaeng *dmaeng = (void *)engine;
union {
struct gf100_dma_v0 v0;
} *args;
struct nvc0_dmaobj_priv *priv;
u32 kind, user, unkn;
int ret;
ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
args = data;
nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
priv->base.bind = nvc0_dmaobj_bind;
return 0;
nv_ioctl(parent, "create gf100 dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create gf100 dma vers %d priv %d kind %02x\n",
args->v0.version, args->v0.priv, args->v0.kind);
kind = args->v0.kind;
user = args->v0.priv;
unkn = 0;
} else
if (size == 0) {
if (priv->base.target != NV_MEM_TARGET_VM) {
kind = GF100_DMA_V0_KIND_PITCH;
user = GF100_DMA_V0_PRIV_US;
unkn = 2;
} else {
kind = GF100_DMA_V0_KIND_VM;
user = GF100_DMA_V0_PRIV_VM;
unkn = 0;
}
} else
return ret;
if (user > 2)
return -EINVAL;
priv->flags0 |= (kind << 22) | (user << 20);
priv->flags5 |= (unkn << 16);
switch (priv->base.target) {
case NV_MEM_TARGET_VM:
priv->flags0 |= 0x00000000;
break;
case NV_MEM_TARGET_VRAM:
priv->flags0 |= 0x00010000;
break;
case NV_MEM_TARGET_PCI:
priv->flags0 |= 0x00020000;
break;
case NV_MEM_TARGET_PCI_NOSNOOP:
priv->flags0 |= 0x00030000;
break;
default:
return -EINVAL;
}
switch (priv->base.access) {
case NV_MEM_ACCESS_VM:
break;
case NV_MEM_ACCESS_RO:
priv->flags0 |= 0x00040000;
break;
case NV_MEM_ACCESS_WO:
case NV_MEM_ACCESS_RW:
priv->flags0 |= 0x00080000;
break;
}
return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
struct nouveau_oclass
nvc0_dmaeng_oclass = {
.handle = NV_ENGINE(DMAOBJ, 0xc0),
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvc0_dmaeng_ctor,
.dtor = _nouveau_dmaeng_dtor,
.init = _nouveau_dmaeng_init,
.fini = _nouveau_dmaeng_fini,
},
static struct nouveau_ofuncs
nvc0_dmaobj_ofuncs = {
.ctor = nvc0_dmaobj_ctor,
.dtor = _nvkm_dmaobj_dtor,
.init = _nvkm_dmaobj_init,
.fini = _nvkm_dmaobj_fini,
};
static struct nouveau_oclass
nvc0_dmaeng_sclass[] = {
{ NV_DMA_FROM_MEMORY, &nvc0_dmaobj_ofuncs },
{ NV_DMA_TO_MEMORY, &nvc0_dmaobj_ofuncs },
{ NV_DMA_IN_MEMORY, &nvc0_dmaobj_ofuncs },
{}
};
struct nouveau_oclass *
nvc0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
.base.handle = NV_ENGINE(DMAOBJ, 0xc0),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = _nvkm_dmaeng_ctor,
.dtor = _nvkm_dmaeng_dtor,
.init = _nvkm_dmaeng_init,
.fini = _nvkm_dmaeng_fini,
},
.sclass = nvc0_dmaeng_sclass,
.bind = nvc0_dmaobj_bind,
}.base;

View File

@ -22,40 +22,40 @@
* Authors: Ben Skeggs
*/
#include <core/client.h>
#include <core/device.h>
#include <core/gpuobj.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/fb.h>
#include <engine/dmaobj.h>
struct nvd0_dmaeng_priv {
struct nouveau_dmaeng base;
#include "priv.h"
struct nvd0_dmaobj_priv {
struct nouveau_dmaobj base;
u32 flags0;
};
static int
nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
nvd0_dmaobj_bind(struct nouveau_dmaobj *dmaobj,
struct nouveau_object *parent,
struct nouveau_dmaobj *dmaobj,
struct nouveau_gpuobj **pgpuobj)
{
u32 flags0 = 0x00000000;
struct nvd0_dmaobj_priv *priv = (void *)dmaobj;
int ret;
if (!nv_iclass(parent, NV_ENGCTX_CLASS)) {
switch (nv_mclass(parent->parent)) {
case NVD0_DISP_MAST_CLASS:
case NVD0_DISP_SYNC_CLASS:
case NVD0_DISP_OVLY_CLASS:
case NVE0_DISP_MAST_CLASS:
case NVE0_DISP_SYNC_CLASS:
case NVE0_DISP_OVLY_CLASS:
case NVF0_DISP_MAST_CLASS:
case NVF0_DISP_SYNC_CLASS:
case NVF0_DISP_OVLY_CLASS:
case GM107_DISP_MAST_CLASS:
case GM107_DISP_SYNC_CLASS:
case GM107_DISP_OVLY_CLASS:
case GF110_DISP_CORE_CHANNEL_DMA:
case GK104_DISP_CORE_CHANNEL_DMA:
case GK110_DISP_CORE_CHANNEL_DMA:
case GM107_DISP_CORE_CHANNEL_DMA:
case GF110_DISP_BASE_CHANNEL_DMA:
case GK104_DISP_BASE_CHANNEL_DMA:
case GK110_DISP_BASE_CHANNEL_DMA:
case GF110_DISP_OVERLAY_CONTROL_DMA:
case GK104_DISP_OVERLAY_CONTROL_DMA:
break;
default:
return -EINVAL;
@ -63,33 +63,11 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
} else
return 0;
if (!(dmaobj->conf0 & NVD0_DMA_CONF0_ENABLE)) {
if (dmaobj->target == NV_MEM_TARGET_VM) {
dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_VM;
dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_LP;
} else {
dmaobj->conf0 |= NVD0_DMA_CONF0_TYPE_LINEAR;
dmaobj->conf0 |= NVD0_DMA_CONF0_PAGE_SP;
}
}
flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_TYPE) << 20;
flags0 |= (dmaobj->conf0 & NVD0_DMA_CONF0_PAGE) >> 4;
switch (dmaobj->target) {
case NV_MEM_TARGET_VRAM:
flags0 |= 0x00000009;
break;
default:
return -EINVAL;
break;
}
ret = nouveau_gpuobj_new(parent, parent, 24, 32, 0, pgpuobj);
if (ret == 0) {
nv_wo32(*pgpuobj, 0x00, flags0);
nv_wo32(*pgpuobj, 0x04, dmaobj->start >> 8);
nv_wo32(*pgpuobj, 0x08, dmaobj->limit >> 8);
nv_wo32(*pgpuobj, 0x00, priv->flags0);
nv_wo32(*pgpuobj, 0x04, priv->base.start >> 8);
nv_wo32(*pgpuobj, 0x08, priv->base.limit >> 8);
nv_wo32(*pgpuobj, 0x0c, 0x00000000);
nv_wo32(*pgpuobj, 0x10, 0x00000000);
nv_wo32(*pgpuobj, 0x14, 0x00000000);
@ -99,30 +77,91 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
}
static int
nvd0_dmaeng_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
nvd0_dmaobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nvd0_dmaeng_priv *priv;
struct nouveau_dmaeng *dmaeng = (void *)engine;
union {
struct gf110_dma_v0 v0;
} *args;
struct nvd0_dmaobj_priv *priv;
u32 kind, page;
int ret;
ret = nouveau_dmaeng_create(parent, engine, oclass, &priv);
ret = nvkm_dmaobj_create(parent, engine, oclass, &data, &size, &priv);
*pobject = nv_object(priv);
if (ret)
return ret;
args = data;
nv_engine(priv)->sclass = nouveau_dmaobj_sclass;
priv->base.bind = nvd0_dmaobj_bind;
return 0;
nv_ioctl(parent, "create gf110 dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create gf100 dma vers %d page %d kind %02x\n",
args->v0.version, args->v0.page, args->v0.kind);
kind = args->v0.kind;
page = args->v0.page;
} else
if (size == 0) {
if (priv->base.target != NV_MEM_TARGET_VM) {
kind = GF110_DMA_V0_KIND_PITCH;
page = GF110_DMA_V0_PAGE_SP;
} else {
kind = GF110_DMA_V0_KIND_VM;
page = GF110_DMA_V0_PAGE_LP;
}
} else
return ret;
if (page > 1)
return -EINVAL;
priv->flags0 = (kind << 20) | (page << 6);
switch (priv->base.target) {
case NV_MEM_TARGET_VRAM:
priv->flags0 |= 0x00000009;
break;
case NV_MEM_TARGET_VM:
case NV_MEM_TARGET_PCI:
case NV_MEM_TARGET_PCI_NOSNOOP:
/* XXX: don't currently know how to construct a real one
* of these. we only use them to represent pushbufs
* on these chipsets, and the classes that use them
* deal with the target themselves.
*/
break;
default:
return -EINVAL;
}
return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
}
struct nouveau_oclass
nvd0_dmaeng_oclass = {
.handle = NV_ENGINE(DMAOBJ, 0xd0),
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvd0_dmaeng_ctor,
.dtor = _nouveau_dmaeng_dtor,
.init = _nouveau_dmaeng_init,
.fini = _nouveau_dmaeng_fini,
},
static struct nouveau_ofuncs
nvd0_dmaobj_ofuncs = {
.ctor = nvd0_dmaobj_ctor,
.dtor = _nvkm_dmaobj_dtor,
.init = _nvkm_dmaobj_init,
.fini = _nvkm_dmaobj_fini,
};
static struct nouveau_oclass
nvd0_dmaeng_sclass[] = {
{ NV_DMA_FROM_MEMORY, &nvd0_dmaobj_ofuncs },
{ NV_DMA_TO_MEMORY, &nvd0_dmaobj_ofuncs },
{ NV_DMA_IN_MEMORY, &nvd0_dmaobj_ofuncs },
{}
};
struct nouveau_oclass *
nvd0_dmaeng_oclass = &(struct nvkm_dmaeng_impl) {
.base.handle = NV_ENGINE(DMAOBJ, 0xd0),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = _nvkm_dmaeng_ctor,
.dtor = _nvkm_dmaeng_dtor,
.init = _nvkm_dmaeng_init,
.fini = _nvkm_dmaeng_fini,
},
.sclass = nvd0_dmaeng_sclass,
.bind = nvd0_dmaobj_bind,
}.base;

View File

@ -0,0 +1,30 @@
#ifndef __NVKM_DMAOBJ_PRIV_H__
#define __NVKM_DMAOBJ_PRIV_H__
#include <engine/dmaobj.h>
#define nvkm_dmaobj_create(p,e,c,pa,sa,d) \
nvkm_dmaobj_create_((p), (e), (c), (pa), (sa), sizeof(**d), (void **)d)
int nvkm_dmaobj_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void **, u32 *,
int, void **);
#define _nvkm_dmaobj_dtor nouveau_object_destroy
#define _nvkm_dmaobj_init nouveau_object_init
#define _nvkm_dmaobj_fini nouveau_object_fini
int _nvkm_dmaeng_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
#define _nvkm_dmaeng_dtor _nouveau_engine_dtor
#define _nvkm_dmaeng_init _nouveau_engine_init
#define _nvkm_dmaeng_fini _nouveau_engine_fini
struct nvkm_dmaeng_impl {
struct nouveau_oclass base;
struct nouveau_oclass *sclass;
int (*bind)(struct nouveau_dmaobj *, struct nouveau_object *,
struct nouveau_gpuobj **);
};
#endif

View File

@ -26,11 +26,30 @@
#include <core/object.h>
#include <core/handle.h>
#include <core/event.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <nvif/event.h>
#include <engine/dmaobj.h>
#include <engine/fifo.h>
static int
nouveau_fifo_event_ctor(void *data, u32 size, struct nvkm_notify *notify)
{
if (size == 0) {
notify->size = 0;
notify->types = 1;
notify->index = 0;
return 0;
}
return -ENOSYS;
}
static const struct nvkm_event_func
nouveau_fifo_event_func = {
.ctor = nouveau_fifo_event_ctor,
};
int
nouveau_fifo_channel_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
@ -59,14 +78,14 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
dmaeng = (void *)chan->pushdma->base.engine;
switch (chan->pushdma->base.oclass->handle) {
case NV_DMA_FROM_MEMORY_CLASS:
case NV_DMA_IN_MEMORY_CLASS:
case NV_DMA_FROM_MEMORY:
case NV_DMA_IN_MEMORY:
break;
default:
return -EINVAL;
}
ret = dmaeng->bind(dmaeng, parent, chan->pushdma, &chan->pushgpu);
ret = dmaeng->bind(chan->pushdma, parent, &chan->pushgpu);
if (ret)
return ret;
@ -85,15 +104,10 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
return -ENOSPC;
}
/* map fifo control registers */
chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
(chan->chid * size), size);
if (!chan->user)
return -EFAULT;
nouveau_event_trigger(priv->cevent, 1, 0);
chan->addr = nv_device_resource_start(device, bar) +
addr + size * chan->chid;
chan->size = size;
nvkm_event_send(&priv->cevent, 1, 0, NULL, 0);
return 0;
}
@ -103,7 +117,8 @@ nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan)
struct nouveau_fifo *priv = (void *)nv_object(chan)->engine;
unsigned long flags;
iounmap(chan->user);
if (chan->user)
iounmap(chan->user);
spin_lock_irqsave(&priv->lock, flags);
priv->channel[chan->chid] = NULL;
@ -121,10 +136,24 @@ _nouveau_fifo_channel_dtor(struct nouveau_object *object)
nouveau_fifo_channel_destroy(chan);
}
int
_nouveau_fifo_channel_map(struct nouveau_object *object, u64 *addr, u32 *size)
{
struct nouveau_fifo_chan *chan = (void *)object;
*addr = chan->addr;
*size = chan->size;
return 0;
}
u32
_nouveau_fifo_channel_rd32(struct nouveau_object *object, u64 addr)
{
struct nouveau_fifo_chan *chan = (void *)object;
if (unlikely(!chan->user)) {
chan->user = ioremap(chan->addr, chan->size);
if (WARN_ON_ONCE(chan->user == NULL))
return 0;
}
return ioread32_native(chan->user + addr);
}
@ -132,9 +161,57 @@ void
_nouveau_fifo_channel_wr32(struct nouveau_object *object, u64 addr, u32 data)
{
struct nouveau_fifo_chan *chan = (void *)object;
if (unlikely(!chan->user)) {
chan->user = ioremap(chan->addr, chan->size);
if (WARN_ON_ONCE(chan->user == NULL))
return;
}
iowrite32_native(data, chan->user + addr);
}
int
nouveau_fifo_uevent_ctor(void *data, u32 size, struct nvkm_notify *notify)
{
union {
struct nvif_notify_uevent_req none;
} *req = data;
int ret;
if (nvif_unvers(req->none)) {
notify->size = sizeof(struct nvif_notify_uevent_rep);
notify->types = 1;
notify->index = 0;
}
return ret;
}
void
nouveau_fifo_uevent(struct nouveau_fifo *fifo)
{
struct nvif_notify_uevent_rep rep = {
};
nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep));
}
int
_nouveau_fifo_channel_ntfy(struct nouveau_object *object, u32 type,
struct nvkm_event **event)
{
struct nouveau_fifo *fifo = (void *)object->engine;
switch (type) {
case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
if (nv_mclass(object) >= G82_CHANNEL_DMA) {
*event = &fifo->uevent;
return 0;
}
break;
default:
break;
}
return -EINVAL;
}
static int
nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object)
{
@ -168,8 +245,8 @@ void
nouveau_fifo_destroy(struct nouveau_fifo *priv)
{
kfree(priv->channel);
nouveau_event_destroy(&priv->uevent);
nouveau_event_destroy(&priv->cevent);
nvkm_event_fini(&priv->uevent);
nvkm_event_fini(&priv->cevent);
nouveau_engine_destroy(&priv->base);
}
@ -194,11 +271,7 @@ nouveau_fifo_create_(struct nouveau_object *parent,
if (!priv->channel)
return -ENOMEM;
ret = nouveau_event_create(1, 1, &priv->cevent);
if (ret)
return ret;
ret = nouveau_event_create(1, 1, &priv->uevent);
ret = nvkm_event_init(&nouveau_fifo_event_func, 1, 1, &priv->cevent);
if (ret)
return ret;

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h>
#include <core/namedb.h>
#include <core/handle.h>
@ -117,16 +118,23 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
0x10000, args->pushbuf,
0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR), &chan);
@ -134,13 +142,15 @@ nv04_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x10,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@ -242,13 +252,15 @@ nv04_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv04_fifo_sclass[] = {
{ NV03_CHANNEL_DMA_CLASS, &nv04_fifo_ofuncs },
{ NV03_CHANNEL_DMA, &nv04_fifo_ofuncs },
{}
};
@ -539,7 +551,7 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
}
if (status & 0x40000000) {
nouveau_event_trigger(priv->base.uevent, 1, 0);
nouveau_fifo_uevent(&priv->base);
nv_wr32(priv, 0x002100, 0x40000000);
status &= ~0x40000000;
}

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h>
#include <core/ramht.h>
@ -59,16 +60,23 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
0x10000, args->pushbuf,
0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR), &chan);
@ -76,13 +84,15 @@ nv10_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 32;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@ -100,13 +110,15 @@ nv10_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv10_fifo_sclass[] = {
{ NV10_CHANNEL_DMA_CLASS, &nv10_fifo_ofuncs },
{ NV10_CHANNEL_DMA, &nv10_fifo_ofuncs },
{}
};

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h>
#include <core/ramht.h>
@ -64,16 +65,23 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
0x10000, args->pushbuf,
0x10000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@ -83,13 +91,15 @@ nv17_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->object_attach = nv04_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
nv_parent(chan)->context_attach = nv04_fifo_context_attach;
chan->ramfc = chan->base.chid * 64;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x14,
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@ -107,13 +117,15 @@ nv17_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv17_fifo_sclass[] = {
{ NV17_CHANNEL_DMA_CLASS, &nv17_fifo_ofuncs },
{ NV17_CHANNEL_DMA, &nv17_fifo_ofuncs },
{}
};

View File

@ -22,8 +22,9 @@
* Authors: Ben Skeggs
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/engctx.h>
#include <core/ramht.h>
@ -182,16 +183,23 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nv04_fifo_priv *priv = (void *)engine;
struct nv04_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x1000, args->pushbuf,
0x1000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@ -200,14 +208,16 @@ nv40_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nv40_fifo_context_attach;
nv_parent(chan)->context_detach = nv40_fifo_context_detach;
nv_parent(chan)->object_attach = nv40_fifo_object_attach;
nv_parent(chan)->object_detach = nv04_fifo_object_detach;
chan->ramfc = chan->base.chid * 128;
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x00, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x04, args->v0.offset);
nv_wo32(priv->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
nv_wo32(priv->ramfc, chan->ramfc + 0x18, 0x30000000 |
NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
@ -226,13 +236,15 @@ nv40_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv40_fifo_sclass[] = {
{ NV40_CHANNEL_DMA_CLASS, &nv40_fifo_ofuncs },
{ NV40_CHANNEL_DMA, &nv40_fifo_ofuncs },
{}
};

View File

@ -25,7 +25,8 @@
#include <core/client.h>
#include <core/engctx.h>
#include <core/ramht.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/timer.h>
#include <subdev/bar.h>
@ -194,17 +195,24 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf,
0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@ -213,6 +221,8 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nv50_fifo_context_attach;
nv_parent(chan)->context_detach = nv50_fifo_context_detach;
nv_parent(chan)->object_attach = nv50_fifo_object_attach;
@ -223,10 +233,10 @@ nv50_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret)
return ret;
nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset));
nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset));
nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset));
nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset));
nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x3c, 0x003f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
@ -247,18 +257,26 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
struct nv50_channel_ind_class *args = data;
union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
u64 ioffset, ilength;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel gpfifo size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf,
0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@ -267,6 +285,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nv50_fifo_context_attach;
nv_parent(chan)->context_detach = nv50_fifo_context_detach;
nv_parent(chan)->object_attach = nv50_fifo_object_attach;
@ -277,8 +297,8 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret)
return ret;
ioffset = args->ioffset;
ilength = order_base_2(args->ilength / 8);
ioffset = args->v0.ioffset;
ilength = order_base_2(args->v0.ilength / 8);
nv_wo32(base->ramfc, 0x3c, 0x403f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
@ -343,8 +363,10 @@ nv50_fifo_ofuncs_dma = {
.dtor = nv50_fifo_chan_dtor,
.init = nv50_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_ofuncs
@ -353,14 +375,16 @@ nv50_fifo_ofuncs_ind = {
.dtor = nv50_fifo_chan_dtor,
.init = nv50_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv50_fifo_sclass[] = {
{ NV50_CHANNEL_DMA_CLASS, &nv50_fifo_ofuncs_dma },
{ NV50_CHANNEL_IND_CLASS, &nv50_fifo_ofuncs_ind },
{ NV50_CHANNEL_DMA, &nv50_fifo_ofuncs_dma },
{ NV50_CHANNEL_GPFIFO, &nv50_fifo_ofuncs_ind },
{}
};

View File

@ -27,7 +27,8 @@
#include <core/engctx.h>
#include <core/ramht.h>
#include <core/event.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <subdev/timer.h>
#include <subdev/bar.h>
@ -160,17 +161,24 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv03_channel_dma_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
struct nv03_channel_dma_class *args = data;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel dma size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel dma vers %d pushbuf %08x "
"offset %016llx\n", args->v0.version,
args->v0.pushbuf, args->v0.offset);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf,
0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@ -186,6 +194,8 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
&chan->ramht);
if (ret)
@ -196,10 +206,10 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,
nv_parent(chan)->object_attach = nv84_fifo_object_attach;
nv_parent(chan)->object_detach = nv50_fifo_object_detach;
nv_wo32(base->ramfc, 0x08, lower_32_bits(args->offset));
nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->offset));
nv_wo32(base->ramfc, 0x10, lower_32_bits(args->offset));
nv_wo32(base->ramfc, 0x14, upper_32_bits(args->offset));
nv_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
nv_wo32(base->ramfc, 0x3c, 0x003f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
nv_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
@ -222,18 +232,26 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nv50_fifo_base *base = (void *)parent;
struct nv50_fifo_chan *chan;
struct nv50_channel_ind_class *args = data;
u64 ioffset, ilength;
int ret;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel gpfifo size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
0x2000, args->pushbuf,
0x2000, args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_DMAOBJ) |
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
@ -249,6 +267,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
ret = nouveau_ramht_new(nv_object(chan), nv_object(chan), 0x8000, 16,
&chan->ramht);
if (ret)
@ -259,8 +279,8 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,
nv_parent(chan)->object_attach = nv84_fifo_object_attach;
nv_parent(chan)->object_detach = nv50_fifo_object_detach;
ioffset = args->ioffset;
ilength = order_base_2(args->ilength / 8);
ioffset = args->v0.ioffset;
ilength = order_base_2(args->v0.ilength / 8);
nv_wo32(base->ramfc, 0x3c, 0x403f6078);
nv_wo32(base->ramfc, 0x44, 0x01003fff);
@ -304,8 +324,10 @@ nv84_fifo_ofuncs_dma = {
.dtor = nv50_fifo_chan_dtor,
.init = nv84_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_ofuncs
@ -314,14 +336,16 @@ nv84_fifo_ofuncs_ind = {
.dtor = nv50_fifo_chan_dtor,
.init = nv84_fifo_chan_init,
.fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nv84_fifo_sclass[] = {
{ NV84_CHANNEL_DMA_CLASS, &nv84_fifo_ofuncs_dma },
{ NV84_CHANNEL_IND_CLASS, &nv84_fifo_ofuncs_ind },
{ G82_CHANNEL_DMA, &nv84_fifo_ofuncs_dma },
{ G82_CHANNEL_GPFIFO, &nv84_fifo_ofuncs_ind },
{}
};
@ -389,19 +413,26 @@ nv84_fifo_cclass = {
******************************************************************************/
static void
nv84_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
nv84_fifo_uevent_init(struct nvkm_event *event, int type, int index)
{
struct nv84_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x40000000, 0x40000000);
struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
nv_mask(fifo, 0x002140, 0x40000000, 0x40000000);
}
static void
nv84_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
nv84_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
{
struct nv84_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x40000000, 0x00000000);
struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
nv_mask(fifo, 0x002140, 0x40000000, 0x00000000);
}
static const struct nvkm_event_func
nv84_fifo_uevent_func = {
.ctor = nouveau_fifo_uevent_ctor,
.init = nv84_fifo_uevent_init,
.fini = nv84_fifo_uevent_fini,
};
static int
nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@ -425,9 +456,9 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
priv->base.uevent->enable = nv84_fifo_uevent_enable;
priv->base.uevent->disable = nv84_fifo_uevent_disable;
priv->base.uevent->priv = priv;
ret = nvkm_event_init(&nv84_fifo_uevent_func, 1, 1, &priv->base.uevent);
if (ret)
return ret;
nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nv04_fifo_intr;

View File

@ -28,7 +28,8 @@
#include <core/gpuobj.h>
#include <core/engctx.h>
#include <core/event.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/enum.h>
#include <subdev/timer.h>
@ -187,20 +188,28 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct nv50_channel_gpfifo_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nvc0_fifo_priv *priv = (void *)engine;
struct nvc0_fifo_base *base = (void *)parent;
struct nvc0_fifo_chan *chan;
struct nv50_channel_ind_class *args = data;
u64 usermem, ioffset, ilength;
int ret, i;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel gpfifo size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength);
} else
return ret;
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
priv->user.bar.offset, 0x1000,
args->pushbuf,
args->v0.pushbuf,
(1ULL << NVDEV_ENGINE_SW) |
(1ULL << NVDEV_ENGINE_GR) |
(1ULL << NVDEV_ENGINE_COPY0) |
@ -212,12 +221,14 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent,
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nvc0_fifo_context_attach;
nv_parent(chan)->context_detach = nvc0_fifo_context_detach;
usermem = chan->base.chid * 0x1000;
ioffset = args->ioffset;
ilength = order_base_2(args->ilength / 8);
ioffset = args->v0.ioffset;
ilength = order_base_2(args->v0.ilength / 8);
for (i = 0; i < 0x1000; i += 4)
nv_wo32(priv->user.mem, usermem + i, 0x00000000);
@ -291,13 +302,15 @@ nvc0_fifo_ofuncs = {
.dtor = _nouveau_fifo_channel_dtor,
.init = nvc0_fifo_chan_init,
.fini = nvc0_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nvc0_fifo_sclass[] = {
{ NVC0_CHANNEL_IND_CLASS, &nvc0_fifo_ofuncs },
{ FERMI_CHANNEL_GPFIFO, &nvc0_fifo_ofuncs },
{}
};
@ -654,7 +667,7 @@ nvc0_fifo_intr_fault(struct nvc0_fifo_priv *priv, int unit)
object = engctx;
while (object) {
switch (nv_mclass(object)) {
case NVC0_CHANNEL_IND_CLASS:
case FERMI_CHANNEL_GPFIFO:
nvc0_fifo_recover(priv, engine, (void *)object);
break;
}
@ -730,7 +743,7 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
for (unkn = 0; unkn < 8; unkn++) {
u32 ints = (intr >> (unkn * 0x04)) & inte;
if (ints & 0x1) {
nouveau_event_trigger(priv->base.uevent, 1, 0);
nouveau_fifo_uevent(&priv->base);
ints &= ~1;
}
if (ints) {
@ -827,19 +840,26 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)
}
static void
nvc0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
nvc0_fifo_uevent_init(struct nvkm_event *event, int type, int index)
{
struct nvc0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
nv_mask(fifo, 0x002140, 0x80000000, 0x80000000);
}
static void
nvc0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
nvc0_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
{
struct nvc0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
nv_mask(fifo, 0x002140, 0x80000000, 0x00000000);
}
static const struct nvkm_event_func
nvc0_fifo_uevent_func = {
.ctor = nouveau_fifo_uevent_ctor,
.init = nvc0_fifo_uevent_init,
.fini = nvc0_fifo_uevent_fini,
};
static int
nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 size,
@ -877,9 +897,9 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
priv->base.uevent->enable = nvc0_fifo_uevent_enable;
priv->base.uevent->disable = nvc0_fifo_uevent_disable;
priv->base.uevent->priv = priv;
ret = nvkm_event_init(&nvc0_fifo_uevent_func, 1, 1, &priv->base.uevent);
if (ret)
return ret;
nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nvc0_fifo_intr;

View File

@ -28,7 +28,8 @@
#include <core/gpuobj.h>
#include <core/engctx.h>
#include <core/event.h>
#include <core/class.h>
#include <nvif/unpack.h>
#include <nvif/class.h>
#include <core/enum.h>
#include <subdev/timer.h>
@ -216,46 +217,56 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent,
struct nouveau_oclass *oclass, void *data, u32 size,
struct nouveau_object **pobject)
{
union {
struct kepler_channel_gpfifo_a_v0 v0;
} *args = data;
struct nouveau_bar *bar = nouveau_bar(parent);
struct nve0_fifo_priv *priv = (void *)engine;
struct nve0_fifo_base *base = (void *)parent;
struct nve0_fifo_chan *chan;
struct nve0_channel_ind_class *args = data;
u64 usermem, ioffset, ilength;
int ret, i;
if (size < sizeof(*args))
return -EINVAL;
nv_ioctl(parent, "create channel gpfifo size %d\n", size);
if (nvif_unpack(args->v0, 0, 0, false)) {
nv_ioctl(parent, "create channel gpfifo vers %d pushbuf %08x "
"ioffset %016llx ilength %08x engine %08x\n",
args->v0.version, args->v0.pushbuf, args->v0.ioffset,
args->v0.ilength, args->v0.engine);
} else
return ret;
for (i = 0; i < FIFO_ENGINE_NR; i++) {
if (args->engine & (1 << i)) {
if (args->v0.engine & (1 << i)) {
if (nouveau_engine(parent, fifo_engine[i].subdev)) {
args->engine = (1 << i);
args->v0.engine = (1 << i);
break;
}
}
}
if (i == FIFO_ENGINE_NR) {
nv_error(priv, "unsupported engines 0x%08x\n", args->engine);
nv_error(priv, "unsupported engines 0x%08x\n", args->v0.engine);
return -ENODEV;
}
ret = nouveau_fifo_channel_create(parent, engine, oclass, 1,
priv->user.bar.offset, 0x200,
args->pushbuf,
args->v0.pushbuf,
fifo_engine[i].mask, &chan);
*pobject = nv_object(chan);
if (ret)
return ret;
args->v0.chid = chan->base.chid;
nv_parent(chan)->context_attach = nve0_fifo_context_attach;
nv_parent(chan)->context_detach = nve0_fifo_context_detach;
chan->engine = i;
usermem = chan->base.chid * 0x200;
ioffset = args->ioffset;
ilength = order_base_2(args->ilength / 8);
ioffset = args->v0.ioffset;
ilength = order_base_2(args->v0.ilength / 8);
for (i = 0; i < 0x200; i += 4)
nv_wo32(priv->user.mem, usermem + i, 0x00000000);
@ -325,13 +336,15 @@ nve0_fifo_ofuncs = {
.dtor = _nouveau_fifo_channel_dtor,
.init = nve0_fifo_chan_init,
.fini = nve0_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32,
.ntfy = _nouveau_fifo_channel_ntfy
};
static struct nouveau_oclass
nve0_fifo_sclass[] = {
{ NVE0_CHANNEL_IND_CLASS, &nve0_fifo_ofuncs },
{ KEPLER_CHANNEL_GPFIFO_A, &nve0_fifo_ofuncs },
{}
};
@ -769,7 +782,7 @@ nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit)
object = engctx;
while (object) {
switch (nv_mclass(object)) {
case NVE0_CHANNEL_IND_CLASS:
case KEPLER_CHANNEL_GPFIFO_A:
nve0_fifo_recover(priv, engine, (void *)object);
break;
}
@ -859,7 +872,7 @@ nve0_fifo_intr_runlist(struct nve0_fifo_priv *priv)
static void
nve0_fifo_intr_engine(struct nve0_fifo_priv *priv)
{
nouveau_event_trigger(priv->base.uevent, 1, 0);
nouveau_fifo_uevent(&priv->base);
}
static void
@ -952,19 +965,26 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
}
static void
nve0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)
nve0_fifo_uevent_init(struct nvkm_event *event, int type, int index)
{
struct nve0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x80000000);
struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
nv_mask(fifo, 0x002140, 0x80000000, 0x80000000);
}
static void
nve0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)
nve0_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
{
struct nve0_fifo_priv *priv = event->priv;
nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
struct nouveau_fifo *fifo = container_of(event, typeof(*fifo), uevent);
nv_mask(fifo, 0x002140, 0x80000000, 0x00000000);
}
static const struct nvkm_event_func
nve0_fifo_uevent_func = {
.ctor = nouveau_fifo_uevent_ctor,
.init = nve0_fifo_uevent_init,
.fini = nve0_fifo_uevent_fini,
};
int
nve0_fifo_fini(struct nouveau_object *object, bool suspend)
{
@ -1067,9 +1087,9 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
if (ret)
return ret;
priv->base.uevent->enable = nve0_fifo_uevent_enable;
priv->base.uevent->disable = nve0_fifo_uevent_disable;
priv->base.uevent->priv = priv;
ret = nvkm_event_init(&nve0_fifo_uevent_func, 1, 1, &priv->base.uevent);
if (ret)
return ret;
nv_subdev(priv)->unit = 0x00000100;
nv_subdev(priv)->intr = nve0_fifo_intr;

View File

@ -0,0 +1,104 @@
/*
* Copyright 2013 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include "ctxnvc0.h"
/*******************************************************************************
* PGRAPH context register lists
******************************************************************************/
static const struct nvc0_graph_init
gk110b_grctx_init_sm_0[] = {
{ 0x419e04, 1, 0x04, 0x00000000 },
{ 0x419e08, 1, 0x04, 0x0000001d },
{ 0x419e0c, 1, 0x04, 0x00000000 },
{ 0x419e10, 1, 0x04, 0x00001c02 },
{ 0x419e44, 1, 0x04, 0x0013eff2 },
{ 0x419e48, 1, 0x04, 0x00000000 },
{ 0x419e4c, 1, 0x04, 0x0000007f },
{ 0x419e50, 2, 0x04, 0x00000000 },
{ 0x419e58, 1, 0x04, 0x00000001 },
{ 0x419e5c, 3, 0x04, 0x00000000 },
{ 0x419e68, 1, 0x04, 0x00000002 },
{ 0x419e6c, 12, 0x04, 0x00000000 },
{ 0x419eac, 1, 0x04, 0x00001f8f },
{ 0x419eb0, 1, 0x04, 0x0db00d2f },
{ 0x419eb8, 1, 0x04, 0x00000000 },
{ 0x419ec8, 1, 0x04, 0x0001304f },
{ 0x419f30, 4, 0x04, 0x00000000 },
{ 0x419f40, 1, 0x04, 0x00000018 },
{ 0x419f44, 3, 0x04, 0x00000000 },
{ 0x419f58, 1, 0x04, 0x00000000 },
{ 0x419f70, 1, 0x04, 0x00006300 },
{ 0x419f78, 1, 0x04, 0x000000eb },
{ 0x419f7c, 1, 0x04, 0x00000404 },
{}
};
static const struct nvc0_graph_pack
gk110b_grctx_pack_tpc[] = {
{ nvd7_grctx_init_pe_0 },
{ nvf0_grctx_init_tex_0 },
{ nvf0_grctx_init_mpc_0 },
{ nvf0_grctx_init_l1c_0 },
{ gk110b_grctx_init_sm_0 },
{}
};
/*******************************************************************************
* PGRAPH context implementation
******************************************************************************/
struct nouveau_oclass *
gk110b_grctx_oclass = &(struct nvc0_grctx_oclass) {
.base.handle = NV_ENGCTX(GR, 0xf1),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvc0_graph_context_ctor,
.dtor = nvc0_graph_context_dtor,
.init = _nouveau_graph_context_init,
.fini = _nouveau_graph_context_fini,
.rd32 = _nouveau_graph_context_rd32,
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
.unkn = nve4_grctx_generate_unkn,
.hub = nvf0_grctx_pack_hub,
.gpc = nvf0_grctx_pack_gpc,
.zcull = nvc0_grctx_pack_zcull,
.tpc = gk110b_grctx_pack_tpc,
.ppc = nvf0_grctx_pack_ppc,
.icmd = nvf0_grctx_pack_icmd,
.mthd = nvf0_grctx_pack_mthd,
.bundle = nve4_grctx_generate_bundle,
.bundle_size = 0x3000,
.bundle_min_gpm_fifo_depth = 0x180,
.bundle_token_limit = 0x600,
.pagepool = nve4_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvd7_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
.alpha_nr_max = 0x7ff,
.alpha_nr = 0x648,
}.base;

View File

@ -41,7 +41,6 @@ gk20a_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
.mods = nve4_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nve4_grctx_pack_hub,
.gpc = nve4_grctx_pack_gpc,
@ -50,4 +49,15 @@ gk20a_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nve4_grctx_pack_ppc,
.icmd = nve4_grctx_pack_icmd,
.mthd = gk20a_grctx_pack_mthd,
.bundle = nve4_grctx_generate_bundle,
.bundle_size = 0x1800,
.bundle_min_gpm_fifo_depth = 0x62,
.bundle_token_limit = 0x100,
.pagepool = nve4_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvd7_grctx_generate_attrib,
.attrib_nr_max = 0x240,
.attrib_nr = 0x240,
.alpha_nr_max = 0x648 + (0x648 / 2),
.alpha_nr = 0x648,
}.base;

View File

@ -859,45 +859,74 @@ gm107_grctx_pack_ppc[] = {
******************************************************************************/
static void
gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
gm107_grctx_generate_bundle(struct nvc0_grctx *info)
{
mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW);
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth,
impl->bundle_size / 0x20);
const u32 token_limit = impl->bundle_token_limit;
const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
const int s = 8;
const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
mmio_refn(info, 0x408004, 0x00000000, s, b);
mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
mmio_refn(info, 0x418e24, 0x00000000, s, b);
mmio_refn(info, 0x418e28, 0x80000000 | (impl->bundle_size >> s), 0, b);
mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
}
mmio_list(0x40800c, 0x00000000, 8, 1);
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x4064cc, 0x80000000, 0, 0);
mmio_list(0x418e30, 0x80000000, 0, 0);
static void
gm107_grctx_generate_pagepool(struct nvc0_grctx *info)
{
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
const int s = 8;
const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
mmio_refn(info, 0x40800c, 0x00000000, s, b);
mmio_wr32(info, 0x408010, 0x80000000);
mmio_refn(info, 0x419004, 0x00000000, s, b);
mmio_wr32(info, 0x419008, 0x00000000);
mmio_wr32(info, 0x4064cc, 0x80000000);
mmio_wr32(info, 0x418e30, 0x80000000); /* guess at it being related */
}
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000030, 0, 0);
mmio_list(0x418e24, 0x00000000, 8, 0);
mmio_list(0x418e28, 0x80000030, 0, 0);
static void
gm107_grctx_generate_attrib(struct nvc0_grctx *info)
{
struct nvc0_graph_priv *priv = info->priv;
const struct nvc0_grctx_oclass *impl = (void *)nvc0_grctx_impl(priv);
const u32 alpha = impl->alpha_nr;
const u32 attrib = impl->attrib_nr;
const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
const u32 access = NV_MEM_ACCESS_RW;
const int s = 12;
const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
const int max_batches = 0xffff;
u32 bo = 0;
u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
int gpc, ppc, n = 0;
mmio_list(0x4064c8, 0x018002c0, 0, 0);
mmio_refn(info, 0x418810, 0x80000000, s, b);
mmio_refn(info, 0x419848, 0x10000000, s, b);
mmio_refn(info, 0x419c2c, 0x10000000, s, b);
mmio_wr32(info, 0x405830, (attrib << 16) | alpha);
mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
mmio_list(0x419c2c, 0x10000000, 12, 2);
mmio_list(0x405830, 0x0aa01000, 0, 0);
mmio_list(0x4064c4, 0x0400ffff, 0, 0);
/*XXX*/
mmio_list(0x5030c0, 0x00001540, 0, 0);
mmio_list(0x5030f4, 0x00000000, 0, 0);
mmio_list(0x5030e4, 0x00002000, 0, 0);
mmio_list(0x5030f8, 0x00003fc0, 0, 0);
mmio_list(0x418ea0, 0x07151540, 0, 0);
mmio_list(0x5032c0, 0x00001540, 0, 0);
mmio_list(0x5032f4, 0x00001fe0, 0, 0);
mmio_list(0x5032e4, 0x00002000, 0, 0);
mmio_list(0x5032f8, 0x00006fc0, 0, 0);
mmio_list(0x418ea4, 0x07151540, 0, 0);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++, n++) {
const u32 as = alpha * priv->ppc_tpc_nr[gpc][ppc];
const u32 bs = attrib * priv->ppc_tpc_nr[gpc][ppc];
const u32 u = 0x418ea0 + (n * 0x04);
const u32 o = PPC_UNIT(gpc, ppc, 0);
mmio_wr32(info, o + 0xc0, bs);
mmio_wr32(info, o + 0xf4, bo);
bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
mmio_wr32(info, o + 0xe4, as);
mmio_wr32(info, o + 0xf8, ao);
ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
mmio_wr32(info, u, (0x715 /*XXX*/ << 16) | bs);
}
}
}
static void
@ -934,7 +963,9 @@ gm107_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
oclass->mods(priv, info);
oclass->bundle(info);
oclass->pagepool(info);
oclass->attrib(info);
oclass->unkn(priv);
gm107_grctx_generate_tpcid(priv);
@ -979,7 +1010,6 @@ gm107_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = gm107_grctx_generate_main,
.mods = gm107_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = gm107_grctx_pack_hub,
.gpc = gm107_grctx_pack_gpc,
@ -988,4 +1018,15 @@ gm107_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = gm107_grctx_pack_ppc,
.icmd = gm107_grctx_pack_icmd,
.mthd = gm107_grctx_pack_mthd,
.bundle = gm107_grctx_generate_bundle,
.bundle_size = 0x3000,
.bundle_min_gpm_fifo_depth = 0x180,
.bundle_token_limit = 0x2c0,
.pagepool = gm107_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = gm107_grctx_generate_attrib,
.attrib_nr_max = 0xff0,
.attrib_nr = 0xaa0,
.alpha_nr_max = 0x1800,
.alpha_nr = 0x1000,
}.base;

View File

@ -531,50 +531,6 @@ nv108_grctx_pack_ppc[] = {
* PGRAPH context implementation
******************************************************************************/
static void
nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
{
u32 magic[GPC_MAX][2];
u32 offset;
int gpc;
mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
mmio_list(0x40800c, 0x00000000, 8, 1);
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x4064cc, 0x80000000, 0, 0);
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000030, 0, 0);
mmio_list(0x418808, 0x00000000, 8, 0);
mmio_list(0x41880c, 0x80000030, 0, 0);
mmio_list(0x4064c8, 0x00c20200, 0, 0);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
mmio_list(0x405830, 0x02180648, 0, 0);
mmio_list(0x4064c4, 0x0192ffff, 0, 0);
for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
magic[gpc][1] = 0x00000000 | (magic1 << 16);
offset += 0x0324 * priv->tpc_nr[gpc];
}
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
offset += 0x07ff * priv->tpc_nr[gpc];
}
mmio_list(0x17e91c, 0x0b040a0b, 0, 0);
mmio_list(0x17e920, 0x00090d08, 0, 0);
}
struct nouveau_oclass *
nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
.base.handle = NV_ENGCTX(GR, 0x08),
@ -587,7 +543,6 @@ nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
.mods = nv108_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nv108_grctx_pack_hub,
.gpc = nv108_grctx_pack_gpc,
@ -596,4 +551,15 @@ nv108_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nv108_grctx_pack_ppc,
.icmd = nv108_grctx_pack_icmd,
.mthd = nvf0_grctx_pack_mthd,
.bundle = nve4_grctx_generate_bundle,
.bundle_size = 0x3000,
.bundle_min_gpm_fifo_depth = 0xc2,
.bundle_token_limit = 0x200,
.pagepool = nve4_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvd7_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
.alpha_nr_max = 0x7ff,
.alpha_nr = 0x648,
}.base;

View File

@ -982,34 +982,93 @@ nvc0_grctx_pack_tpc[] = {
* PGRAPH context implementation
******************************************************************************/
void
nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
int
nvc0_grctx_mmio_data(struct nvc0_grctx *info, u32 size, u32 align, u32 access)
{
if (info->data) {
info->buffer[info->buffer_nr] = round_up(info->addr, align);
info->addr = info->buffer[info->buffer_nr] + size;
info->data->size = size;
info->data->align = align;
info->data->access = access;
info->data++;
return info->buffer_nr++;
}
return -1;
}
void
nvc0_grctx_mmio_item(struct nvc0_grctx *info, u32 addr, u32 data,
int shift, int buffer)
{
if (info->data) {
if (shift >= 0) {
info->mmio->addr = addr;
info->mmio->data = data;
info->mmio->shift = shift;
info->mmio->buffer = buffer;
if (buffer >= 0)
data |= info->buffer[buffer] >> shift;
info->mmio++;
} else
return;
} else {
if (buffer >= 0)
return;
}
nv_wr32(info->priv, addr, data);
}
void
nvc0_grctx_generate_bundle(struct nvc0_grctx *info)
{
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
const int s = 8;
const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
mmio_refn(info, 0x408004, 0x00000000, s, b);
mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
mmio_refn(info, 0x418808, 0x00000000, s, b);
mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
}
void
nvc0_grctx_generate_pagepool(struct nvc0_grctx *info)
{
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
const int s = 8;
const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
mmio_refn(info, 0x40800c, 0x00000000, s, b);
mmio_wr32(info, 0x408010, 0x80000000);
mmio_refn(info, 0x419004, 0x00000000, s, b);
mmio_wr32(info, 0x419008, 0x00000000);
}
void
nvc0_grctx_generate_attrib(struct nvc0_grctx *info)
{
struct nvc0_graph_priv *priv = info->priv;
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
const u32 attrib = impl->attrib_nr;
const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
const u32 access = NV_MEM_ACCESS_RW;
const int s = 12;
const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
int gpc, tpc;
u32 offset;
u32 bo = 0;
mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
mmio_refn(info, 0x418810, 0x80000000, s, b);
mmio_refn(info, 0x419848, 0x10000000, s, b);
mmio_wr32(info, 0x405830, (attrib << 16));
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000018, 0, 0);
mmio_list(0x40800c, 0x00000000, 8, 1);
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x418808, 0x00000000, 8, 0);
mmio_list(0x41880c, 0x80000018, 0, 0);
mmio_list(0x405830, 0x02180000, 0, 0);
for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
mmio_list(addr, 0x02180000 | offset, 0, 0);
offset += 0x0324;
const u32 o = TPC_UNIT(gpc, tpc, 0x0520);
mmio_skip(info, o, (attrib << 16) | ++bo);
mmio_wr32(info, o, (attrib << 16) | --bo);
bo += impl->attrib_nr_max;
}
}
}
@ -1170,7 +1229,7 @@ nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
{
struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_mmio(priv, oclass->hub);
nvc0_graph_mmio(priv, oclass->gpc);
@ -1180,7 +1239,9 @@ nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
oclass->mods(priv, info);
oclass->bundle(info);
oclass->pagepool(info);
oclass->attrib(info);
oclass->unkn(priv);
nvc0_grctx_generate_tpcid(priv);
@ -1192,7 +1253,7 @@ nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nvc0_graph_icmd(priv, oclass->icmd);
nv_wr32(priv, 0x404154, 0x00000400);
nvc0_graph_mthd(priv, oclass->mthd);
nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
}
int
@ -1308,7 +1369,6 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
.mods = nvc0_grctx_generate_mods,
.unkn = nvc0_grctx_generate_unkn,
.hub = nvc0_grctx_pack_hub,
.gpc = nvc0_grctx_pack_gpc,
@ -1316,4 +1376,11 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc0_grctx_pack_tpc,
.icmd = nvc0_grctx_pack_icmd,
.mthd = nvc0_grctx_pack_mthd,
.bundle = nvc0_grctx_generate_bundle,
.bundle_size = 0x1800,
.pagepool = nvc0_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvc0_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
}.base;

View File

@ -12,12 +12,19 @@ struct nvc0_grctx {
u64 addr;
};
int nvc0_grctx_mmio_data(struct nvc0_grctx *, u32 size, u32 align, u32 access);
void nvc0_grctx_mmio_item(struct nvc0_grctx *, u32 addr, u32 data, int s, int);
#define mmio_vram(a,b,c,d) nvc0_grctx_mmio_data((a), (b), (c), (d))
#define mmio_refn(a,b,c,d,e) nvc0_grctx_mmio_item((a), (b), (c), (d), (e))
#define mmio_skip(a,b,c) mmio_refn((a), (b), (c), -1, -1)
#define mmio_wr32(a,b,c) mmio_refn((a), (b), (c), 0, -1)
struct nvc0_grctx_oclass {
struct nouveau_oclass base;
/* main context generation function */
void (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *);
/* context-specific modify-on-first-load list generation function */
void (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *);
void (*unkn)(struct nvc0_graph_priv *);
/* mmio context data */
const struct nvc0_graph_pack *hub;
@ -28,30 +35,34 @@ struct nvc0_grctx_oclass {
/* indirect context data, generated with icmds/mthds */
const struct nvc0_graph_pack *icmd;
const struct nvc0_graph_pack *mthd;
/* bundle circular buffer */
void (*bundle)(struct nvc0_grctx *);
u32 bundle_size;
u32 bundle_min_gpm_fifo_depth;
u32 bundle_token_limit;
/* pagepool */
void (*pagepool)(struct nvc0_grctx *);
u32 pagepool_size;
/* attribute(/alpha) circular buffer */
void (*attrib)(struct nvc0_grctx *);
u32 attrib_nr_max;
u32 attrib_nr;
u32 alpha_nr_max;
u32 alpha_nr;
};
#define mmio_data(s,a,p) do { \
info->buffer[info->buffer_nr] = round_up(info->addr, (a)); \
info->addr = info->buffer[info->buffer_nr++] + (s); \
info->data->size = (s); \
info->data->align = (a); \
info->data->access = (p); \
info->data++; \
} while(0)
#define mmio_list(r,d,s,b) do { \
info->mmio->addr = (r); \
info->mmio->data = (d); \
info->mmio->shift = (s); \
info->mmio->buffer = (b); \
info->mmio++; \
nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0)); \
} while(0)
static inline const struct nvc0_grctx_oclass *
nvc0_grctx_impl(struct nvc0_graph_priv *priv)
{
return (void *)nv_engine(priv)->cclass;
}
extern struct nouveau_oclass *nvc0_grctx_oclass;
int nvc0_grctx_generate(struct nvc0_graph_priv *);
void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
void nvc0_grctx_generate_bundle(struct nvc0_grctx *);
void nvc0_grctx_generate_pagepool(struct nvc0_grctx *);
void nvc0_grctx_generate_attrib(struct nvc0_grctx *);
void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *);
void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *);
void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *);
@ -60,22 +71,27 @@ void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *);
void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *);
extern struct nouveau_oclass *nvc1_grctx_oclass;
void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
void nvc1_grctx_generate_attrib(struct nvc0_grctx *);
void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *);
extern struct nouveau_oclass *nvc4_grctx_oclass;
extern struct nouveau_oclass *nvc8_grctx_oclass;
extern struct nouveau_oclass *nvd7_grctx_oclass;
void nvd7_grctx_generate_attrib(struct nvc0_grctx *);
extern struct nouveau_oclass *nvd9_grctx_oclass;
extern struct nouveau_oclass *nve4_grctx_oclass;
extern struct nouveau_oclass *gk20a_grctx_oclass;
void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
void nve4_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
void nve4_grctx_generate_bundle(struct nvc0_grctx *);
void nve4_grctx_generate_pagepool(struct nvc0_grctx *);
void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
extern struct nouveau_oclass *nvf0_grctx_oclass;
extern struct nouveau_oclass *gk110b_grctx_oclass;
extern struct nouveau_oclass *nv108_grctx_oclass;
extern struct nouveau_oclass *gm107_grctx_oclass;
@ -160,16 +176,23 @@ extern const struct nvc0_graph_pack nve4_grctx_pack_ppc[];
extern const struct nvc0_graph_pack nve4_grctx_pack_icmd[];
extern const struct nvc0_graph_init nve4_grctx_init_a097_0[];
extern const struct nvc0_graph_pack nvf0_grctx_pack_icmd[];
extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[];
extern const struct nvc0_graph_pack nvf0_grctx_pack_hub[];
extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[];
extern const struct nvc0_graph_init nvf0_grctx_init_cwd_0[];
extern const struct nvc0_graph_pack nvf0_grctx_pack_gpc[];
extern const struct nvc0_graph_init nvf0_grctx_init_gpc_unk_2[];
extern const struct nvc0_graph_init nvf0_grctx_init_tex_0[];
extern const struct nvc0_graph_init nvf0_grctx_init_mpc_0[];
extern const struct nvc0_graph_init nvf0_grctx_init_l1c_0[];
extern const struct nvc0_graph_pack nvf0_grctx_pack_ppc[];
extern const struct nvc0_graph_init nv108_grctx_init_rstr2d_0[];
extern const struct nvc0_graph_init nv108_grctx_init_prop_0[];

View File

@ -727,38 +727,38 @@ nvc1_grctx_pack_tpc[] = {
******************************************************************************/
void
nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nvc1_grctx_generate_attrib(struct nvc0_grctx *info)
{
struct nvc0_graph_priv *priv = info->priv;
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
const u32 alpha = impl->alpha_nr;
const u32 beta = impl->attrib_nr;
const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
const u32 access = NV_MEM_ACCESS_RW;
const int s = 12;
const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
const int timeslice_mode = 1;
const int max_batches = 0xffff;
u32 bo = 0;
u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
int gpc, tpc;
u32 offset;
mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000018, 0, 0);
mmio_list(0x40800c, 0x00000000, 8, 1);
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x418808, 0x00000000, 8, 0);
mmio_list(0x41880c, 0x80000018, 0, 0);
mmio_refn(info, 0x418810, 0x80000000, s, b);
mmio_refn(info, 0x419848, 0x10000000, s, b);
mmio_wr32(info, 0x405830, (beta << 16) | alpha);
mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
mmio_list(0x405830, 0x02180218, 0, 0);
mmio_list(0x4064c4, 0x0086ffff, 0, 0);
for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
mmio_list(addr, 0x12180000 | offset, 0, 0);
offset += 0x0324;
}
for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
u32 addr = TPC_UNIT(gpc, tpc, 0x0544);
mmio_list(addr, 0x02180000 | offset, 0, 0);
offset += 0x0324;
const u32 a = alpha;
const u32 b = beta;
const u32 t = timeslice_mode;
const u32 o = TPC_UNIT(gpc, tpc, 0x500);
mmio_skip(info, o + 0x20, (t << 28) | (b << 16) | ++bo);
mmio_wr32(info, o + 0x20, (t << 28) | (b << 16) | --bo);
bo += impl->attrib_nr_max;
mmio_wr32(info, o + 0x44, (a << 16) | ao);
ao += impl->alpha_nr_max;
}
}
}
@ -786,7 +786,6 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
.mods = nvc1_grctx_generate_mods,
.unkn = nvc1_grctx_generate_unkn,
.hub = nvc1_grctx_pack_hub,
.gpc = nvc1_grctx_pack_gpc,
@ -794,4 +793,13 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc1_grctx_pack_tpc,
.icmd = nvc1_grctx_pack_icmd,
.mthd = nvc1_grctx_pack_mthd,
.bundle = nvc0_grctx_generate_bundle,
.bundle_size = 0x1800,
.pagepool = nvc0_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvc1_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
.alpha_nr_max = 0x324,
.alpha_nr = 0x218,
}.base;

View File

@ -92,7 +92,6 @@ nvc4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
.mods = nvc0_grctx_generate_mods,
.unkn = nvc0_grctx_generate_unkn,
.hub = nvc0_grctx_pack_hub,
.gpc = nvc0_grctx_pack_gpc,
@ -100,4 +99,11 @@ nvc4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc4_grctx_pack_tpc,
.icmd = nvc0_grctx_pack_icmd,
.mthd = nvc0_grctx_pack_mthd,
.bundle = nvc0_grctx_generate_bundle,
.bundle_size = 0x1800,
.pagepool = nvc0_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvc0_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
}.base;

View File

@ -343,7 +343,6 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
.mods = nvc0_grctx_generate_mods,
.unkn = nvc0_grctx_generate_unkn,
.hub = nvc0_grctx_pack_hub,
.gpc = nvc8_grctx_pack_gpc,
@ -351,4 +350,11 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvc0_grctx_pack_tpc,
.icmd = nvc8_grctx_pack_icmd,
.mthd = nvc8_grctx_pack_mthd,
.bundle = nvc0_grctx_generate_bundle,
.bundle_size = 0x1800,
.pagepool = nvc0_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvc0_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
}.base;

View File

@ -177,44 +177,41 @@ nvd7_grctx_pack_ppc[] = {
* PGRAPH context implementation
******************************************************************************/
static void
nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
void
nvd7_grctx_generate_attrib(struct nvc0_grctx *info)
{
u32 magic[GPC_MAX][2];
u32 offset;
int gpc;
struct nvc0_graph_priv *priv = info->priv;
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
const u32 alpha = impl->alpha_nr;
const u32 beta = impl->attrib_nr;
const u32 size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
const u32 access = NV_MEM_ACCESS_RW;
const int s = 12;
const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
const int timeslice_mode = 1;
const int max_batches = 0xffff;
u32 bo = 0;
u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
int gpc, ppc;
mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
mmio_list(0x40800c, 0x00000000, 8, 1);
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000018, 0, 0);
mmio_list(0x418808, 0x00000000, 8, 0);
mmio_list(0x41880c, 0x80000018, 0, 0);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
mmio_list(0x405830, 0x02180324, 0, 0);
mmio_list(0x4064c4, 0x00c9ffff, 0, 0);
for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
u16 magic1 = 0x0324 * priv->tpc_nr[gpc];
magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
magic[gpc][1] = 0x00000000 | (magic1 << 16);
offset += 0x0324 * priv->tpc_nr[gpc];
}
mmio_refn(info, 0x418810, 0x80000000, s, b);
mmio_refn(info, 0x419848, 0x10000000, s, b);
mmio_wr32(info, 0x405830, (beta << 16) | alpha);
mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
offset += 0x07ff * priv->tpc_nr[gpc];
for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++) {
const u32 a = alpha * priv->ppc_tpc_nr[gpc][ppc];
const u32 b = beta * priv->ppc_tpc_nr[gpc][ppc];
const u32 t = timeslice_mode;
const u32 o = PPC_UNIT(gpc, ppc, 0);
mmio_skip(info, o + 0xc0, (t << 28) | (b << 16) | ++bo);
mmio_wr32(info, o + 0xc0, (t << 28) | (b << 16) | --bo);
bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
mmio_wr32(info, o + 0xe4, (a << 16) | ao);
ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
}
}
mmio_list(0x17e91c, 0x03060609, 0, 0); /* different from kepler */
}
void
@ -223,7 +220,7 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
int i;
nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_mmio(priv, oclass->hub);
nvc0_graph_mmio(priv, oclass->gpc);
@ -233,7 +230,9 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
oclass->mods(priv, info);
oclass->bundle(info);
oclass->pagepool(info);
oclass->attrib(info);
oclass->unkn(priv);
nvc0_grctx_generate_tpcid(priv);
@ -248,7 +247,7 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nvc0_graph_icmd(priv, oclass->icmd);
nv_wr32(priv, 0x404154, 0x00000400);
nvc0_graph_mthd(priv, oclass->mthd);
nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
}
struct nouveau_oclass *
@ -263,7 +262,6 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvd7_grctx_generate_main,
.mods = nvd7_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nvd7_grctx_pack_hub,
.gpc = nvd7_grctx_pack_gpc,
@ -272,4 +270,13 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nvd7_grctx_pack_ppc,
.icmd = nvd9_grctx_pack_icmd,
.mthd = nvd9_grctx_pack_mthd,
.bundle = nvc0_grctx_generate_bundle,
.bundle_size = 0x1800,
.pagepool = nvc0_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvd7_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
.alpha_nr_max = 0x7ff,
.alpha_nr = 0x324,
}.base;

View File

@ -511,7 +511,6 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nvc0_grctx_generate_main,
.mods = nvc1_grctx_generate_mods,
.unkn = nvc1_grctx_generate_unkn,
.hub = nvd9_grctx_pack_hub,
.gpc = nvd9_grctx_pack_gpc,
@ -519,4 +518,13 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {
.tpc = nvd9_grctx_pack_tpc,
.icmd = nvd9_grctx_pack_icmd,
.mthd = nvd9_grctx_pack_mthd,
.bundle = nvc0_grctx_generate_bundle,
.bundle_size = 0x1800,
.pagepool = nvc0_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvc1_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
.alpha_nr_max = 0x324,
.alpha_nr = 0x218,
}.base;

View File

@ -839,47 +839,34 @@ nve4_grctx_pack_ppc[] = {
******************************************************************************/
void
nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nve4_grctx_generate_bundle(struct nvc0_grctx *info)
{
u32 magic[GPC_MAX][2];
u32 offset;
int gpc;
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
const u32 state_limit = min(impl->bundle_min_gpm_fifo_depth,
impl->bundle_size / 0x20);
const u32 token_limit = impl->bundle_token_limit;
const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
const int s = 8;
const int b = mmio_vram(info, impl->bundle_size, (1 << s), access);
mmio_refn(info, 0x408004, 0x00000000, s, b);
mmio_refn(info, 0x408008, 0x80000000 | (impl->bundle_size >> s), 0, b);
mmio_refn(info, 0x418808, 0x00000000, s, b);
mmio_refn(info, 0x41880c, 0x80000000 | (impl->bundle_size >> s), 0, b);
mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
}
mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
mmio_list(0x40800c, 0x00000000, 8, 1);
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x4064cc, 0x80000000, 0, 0);
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000030, 0, 0);
mmio_list(0x418808, 0x00000000, 8, 0);
mmio_list(0x41880c, 0x80000030, 0, 0);
mmio_list(0x4064c8, 0x01800600, 0, 0);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
mmio_list(0x405830, 0x02180648, 0, 0);
mmio_list(0x4064c4, 0x0192ffff, 0, 0);
for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
magic[gpc][1] = 0x00000000 | (magic1 << 16);
offset += 0x0324 * priv->tpc_nr[gpc];
}
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
offset += 0x07ff * priv->tpc_nr[gpc];
}
mmio_list(0x17e91c, 0x06060609, 0, 0);
mmio_list(0x17e920, 0x00090a05, 0, 0);
void
nve4_grctx_generate_pagepool(struct nvc0_grctx *info)
{
const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(info->priv);
const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS;
const int s = 8;
const int b = mmio_vram(info, impl->pagepool_size, (1 << s), access);
mmio_refn(info, 0x40800c, 0x00000000, s, b);
mmio_wr32(info, 0x408010, 0x80000000);
mmio_refn(info, 0x419004, 0x00000000, s, b);
mmio_wr32(info, 0x419008, 0x00000000);
mmio_wr32(info, 0x4064cc, 0x80000000);
}
void
@ -957,7 +944,7 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass;
int i;
nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_mmio(priv, oclass->hub);
nvc0_graph_mmio(priv, oclass->gpc);
@ -967,7 +954,9 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nv_wr32(priv, 0x404154, 0x00000000);
oclass->mods(priv, info);
oclass->bundle(info);
oclass->pagepool(info);
oclass->attrib(info);
oclass->unkn(priv);
nvc0_grctx_generate_tpcid(priv);
@ -991,7 +980,7 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
nvc0_graph_icmd(priv, oclass->icmd);
nv_wr32(priv, 0x404154, 0x00000400);
nvc0_graph_mthd(priv, oclass->mthd);
nv_mask(priv, 0x000260, 0x00000001, 0x00000001);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
nv_mask(priv, 0x418800, 0x00200000, 0x00200000);
nv_mask(priv, 0x41be10, 0x00800000, 0x00800000);
@ -1009,7 +998,6 @@ nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
.mods = nve4_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nve4_grctx_pack_hub,
.gpc = nve4_grctx_pack_gpc,
@ -1018,4 +1006,15 @@ nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nve4_grctx_pack_ppc,
.icmd = nve4_grctx_pack_icmd,
.mthd = nve4_grctx_pack_mthd,
.bundle = nve4_grctx_generate_bundle,
.bundle_size = 0x3000,
.bundle_min_gpm_fifo_depth = 0x180,
.bundle_token_limit = 0x600,
.pagepool = nve4_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvd7_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
.alpha_nr_max = 0x7ff,
.alpha_nr = 0x648,
}.base;

View File

@ -279,7 +279,7 @@ nvf0_grctx_init_icmd_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nvf0_grctx_pack_icmd[] = {
{ nvf0_grctx_init_icmd_0 },
{}
@ -668,7 +668,7 @@ nvf0_grctx_init_be_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nvf0_grctx_pack_hub[] = {
{ nvc0_grctx_init_main_0 },
{ nvf0_grctx_init_fe_0 },
@ -704,7 +704,7 @@ nvf0_grctx_init_gpc_unk_2[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nvf0_grctx_pack_gpc[] = {
{ nvc0_grctx_init_gpc_unk_0 },
{ nvd9_grctx_init_prop_0 },
@ -718,7 +718,7 @@ nvf0_grctx_pack_gpc[] = {
{}
};
static const struct nvc0_graph_init
const struct nvc0_graph_init
nvf0_grctx_init_tex_0[] = {
{ 0x419a00, 1, 0x04, 0x000000f0 },
{ 0x419a04, 1, 0x04, 0x00000001 },
@ -797,7 +797,7 @@ nvf0_grctx_init_cbm_0[] = {
{}
};
static const struct nvc0_graph_pack
const struct nvc0_graph_pack
nvf0_grctx_pack_ppc[] = {
{ nve4_grctx_init_pes_0 },
{ nvf0_grctx_init_cbm_0 },
@ -809,58 +809,6 @@ nvf0_grctx_pack_ppc[] = {
* PGRAPH context implementation
******************************************************************************/
static void
nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
{
u32 magic[GPC_MAX][4];
u32 offset;
int gpc;
mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
mmio_list(0x40800c, 0x00000000, 8, 1);
mmio_list(0x408010, 0x80000000, 0, 0);
mmio_list(0x419004, 0x00000000, 8, 1);
mmio_list(0x419008, 0x00000000, 0, 0);
mmio_list(0x4064cc, 0x80000000, 0, 0);
mmio_list(0x408004, 0x00000000, 8, 0);
mmio_list(0x408008, 0x80000030, 0, 0);
mmio_list(0x418808, 0x00000000, 8, 0);
mmio_list(0x41880c, 0x80000030, 0, 0);
mmio_list(0x4064c8, 0x01800600, 0, 0);
mmio_list(0x418810, 0x80000000, 12, 2);
mmio_list(0x419848, 0x10000000, 12, 2);
mmio_list(0x405830, 0x02180648, 0, 0);
mmio_list(0x4064c4, 0x0192ffff, 0, 0);
for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
u16 magic0 = 0x0218 * (priv->tpc_nr[gpc] - 1);
u16 magic1 = 0x0648 * (priv->tpc_nr[gpc] - 1);
u16 magic2 = 0x0218;
u16 magic3 = 0x0648;
magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset;
magic[gpc][1] = 0x00000000 | (magic1 << 16);
offset += 0x0324 * (priv->tpc_nr[gpc] - 1);
magic[gpc][2] = 0x10000000 | (magic2 << 16) | offset;
magic[gpc][3] = 0x00000000 | (magic3 << 16);
offset += 0x0324;
}
for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
offset += 0x07ff * (priv->tpc_nr[gpc] - 1);
mmio_list(GPC_UNIT(gpc, 0x32c0), magic[gpc][2], 0, 0);
mmio_list(GPC_UNIT(gpc, 0x32e4), magic[gpc][3] | offset, 0, 0);
offset += 0x07ff;
}
mmio_list(0x17e91c, 0x06060609, 0, 0);
mmio_list(0x17e920, 0x00090a05, 0, 0);
}
struct nouveau_oclass *
nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.base.handle = NV_ENGCTX(GR, 0xf0),
@ -873,7 +821,6 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.wr32 = _nouveau_graph_context_wr32,
},
.main = nve4_grctx_generate_main,
.mods = nvf0_grctx_generate_mods,
.unkn = nve4_grctx_generate_unkn,
.hub = nvf0_grctx_pack_hub,
.gpc = nvf0_grctx_pack_gpc,
@ -882,4 +829,15 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
.ppc = nvf0_grctx_pack_ppc,
.icmd = nvf0_grctx_pack_icmd,
.mthd = nvf0_grctx_pack_mthd,
.bundle = nve4_grctx_generate_bundle,
.bundle_size = 0x3000,
.bundle_min_gpm_fifo_depth = 0x180,
.bundle_token_limit = 0x7c0,
.pagepool = nve4_grctx_generate_pagepool,
.pagepool_size = 0x8000,
.attrib = nvd7_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
.alpha_nr_max = 0x7ff,
.alpha_nr = 0x648,
}.base;

View File

@ -0,0 +1,117 @@
/*
* Copyright 2013 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs <bskeggs@redhat.com>
*/
#include "nvc0.h"
#include "ctxnvc0.h"
/*******************************************************************************
* PGRAPH register lists
******************************************************************************/
static const struct nvc0_graph_init
gk110b_graph_init_l1c_0[] = {
{ 0x419c98, 1, 0x04, 0x00000000 },
{ 0x419ca8, 1, 0x04, 0x00000000 },
{ 0x419cb0, 1, 0x04, 0x09000000 },
{ 0x419cb4, 1, 0x04, 0x00000000 },
{ 0x419cb8, 1, 0x04, 0x00b08bea },
{ 0x419c84, 1, 0x04, 0x00010384 },
{ 0x419cbc, 1, 0x04, 0x281b3646 },
{ 0x419cc0, 2, 0x04, 0x00000000 },
{ 0x419c80, 1, 0x04, 0x00020230 },
{ 0x419ccc, 2, 0x04, 0x00000000 },
{}
};
static const struct nvc0_graph_init
gk110b_graph_init_sm_0[] = {
{ 0x419e00, 1, 0x04, 0x00000080 },
{ 0x419ea0, 1, 0x04, 0x00000000 },
{ 0x419ee4, 1, 0x04, 0x00000000 },
{ 0x419ea4, 1, 0x04, 0x00000100 },
{ 0x419ea8, 1, 0x04, 0x00000000 },
{ 0x419eb4, 1, 0x04, 0x00000000 },
{ 0x419ebc, 2, 0x04, 0x00000000 },
{ 0x419edc, 1, 0x04, 0x00000000 },
{ 0x419f00, 1, 0x04, 0x00000000 },
{ 0x419ed0, 1, 0x04, 0x00002616 },
{ 0x419f74, 1, 0x04, 0x00015555 },
{ 0x419f80, 4, 0x04, 0x00000000 },
{}
};
static const struct nvc0_graph_pack
gk110b_graph_pack_mmio[] = {
{ nve4_graph_init_main_0 },
{ nvf0_graph_init_fe_0 },
{ nvc0_graph_init_pri_0 },
{ nvc0_graph_init_rstr2d_0 },
{ nvd9_graph_init_pd_0 },
{ nvf0_graph_init_ds_0 },
{ nvc0_graph_init_scc_0 },
{ nvf0_graph_init_sked_0 },
{ nvf0_graph_init_cwd_0 },
{ nvd9_graph_init_prop_0 },
{ nvc1_graph_init_gpc_unk_0 },
{ nvc0_graph_init_setup_0 },
{ nvc0_graph_init_crstr_0 },
{ nvc1_graph_init_setup_1 },
{ nvc0_graph_init_zcull_0 },
{ nvd9_graph_init_gpm_0 },
{ nvf0_graph_init_gpc_unk_1 },
{ nvc0_graph_init_gcc_0 },
{ nve4_graph_init_tpccs_0 },
{ nvf0_graph_init_tex_0 },
{ nve4_graph_init_pe_0 },
{ gk110b_graph_init_l1c_0 },
{ nvc0_graph_init_mpc_0 },
{ gk110b_graph_init_sm_0 },
{ nvd7_graph_init_pes_0 },
{ nvd7_graph_init_wwdx_0 },
{ nvd7_graph_init_cbm_0 },
{ nve4_graph_init_be_0 },
{ nvc0_graph_init_fe_1 },
{}
};
/*******************************************************************************
* PGRAPH engine/subdev functions
******************************************************************************/
struct nouveau_oclass *
gk110b_graph_oclass = &(struct nvc0_graph_oclass) {
.base.handle = NV_ENGINE(GR, 0xf1),
.base.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nvc0_graph_ctor,
.dtor = nvc0_graph_dtor,
.init = nve4_graph_init,
.fini = nvf0_graph_fini,
},
.cclass = &gk110b_grctx_oclass,
.sclass = nvf0_graph_sclass,
.mmio = gk110b_graph_pack_mmio,
.fecs.ucode = &nvf0_graph_fecs_ucode,
.gpccs.ucode = &nvf0_graph_gpccs_ucode,
.ppc_nr = 2,
}.base;

View File

@ -27,8 +27,8 @@ static struct nouveau_oclass
gk20a_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa040, &nouveau_object_ofuncs },
{ 0xa297, &nouveau_object_ofuncs },
{ 0xa0c0, &nouveau_object_ofuncs },
{ KEPLER_C, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
{ KEPLER_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@ -39,9 +39,10 @@ gk20a_graph_oclass = &(struct nvc0_graph_oclass) {
.ctor = nvc0_graph_ctor,
.dtor = nvc0_graph_dtor,
.init = nve4_graph_init,
.fini = nve4_graph_fini,
.fini = _nouveau_graph_fini,
},
.cclass = &gk20a_grctx_oclass,
.sclass = gk20a_graph_sclass,
.mmio = nve4_graph_pack_mmio,
.ppc_nr = 1,
}.base;

View File

@ -36,8 +36,8 @@ static struct nouveau_oclass
gm107_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa140, &nouveau_object_ofuncs },
{ 0xb097, &nouveau_object_ofuncs },
{ 0xb0c0, &nouveau_object_ofuncs },
{ MAXWELL_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
{ MAXWELL_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@ -425,6 +425,9 @@ gm107_graph_init(struct nouveau_object *object)
nv_wr32(priv, 0x400134, 0xffffffff);
nv_wr32(priv, 0x400054, 0x2c350f63);
nvc0_graph_zbc_init(priv);
return nvc0_graph_init_ctxctl(priv);
}
@ -462,4 +465,5 @@ gm107_graph_oclass = &(struct nvc0_graph_oclass) {
.mmio = gm107_graph_pack_mmio,
.fecs.ucode = 0 ? &gm107_graph_fecs_ucode : NULL,
.gpccs.ucode = &gm107_graph_gpccs_ucode,
.ppc_nr = 2,
}.base;

View File

@ -24,7 +24,6 @@
#include <core/client.h>
#include <core/os.h>
#include <core/class.h>
#include <core/handle.h>
#include <core/namedb.h>

View File

@ -24,7 +24,6 @@
#include <core/client.h>
#include <core/os.h>
#include <core/class.h>
#include <core/handle.h>
#include <subdev/fb.h>

View File

@ -33,7 +33,7 @@ static struct nouveau_oclass
nv108_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0xa140, &nouveau_object_ofuncs },
{ 0xa197, &nouveau_object_ofuncs },
{ KEPLER_B, &nvc0_fermi_ofuncs },
{ 0xa1c0, &nouveau_object_ofuncs },
{}
};
@ -220,4 +220,5 @@ nv108_graph_oclass = &(struct nvc0_graph_oclass) {
.mmio = nv108_graph_pack_mmio,
.fecs.ucode = &nv108_graph_fecs_ucode,
.gpccs.ucode = &nv108_graph_gpccs_ucode,
.ppc_nr = 1,
}.base;

View File

@ -1,6 +1,5 @@
#include <core/client.h>
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
#include <core/handle.h>
#include <core/enum.h>

View File

@ -1,5 +1,4 @@
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>

View File

@ -1,5 +1,4 @@
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>

View File

@ -1,5 +1,4 @@
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>

View File

@ -1,5 +1,4 @@
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>

View File

@ -1,5 +1,4 @@
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>
#include <core/enum.h>

View File

@ -24,7 +24,6 @@
#include <core/client.h>
#include <core/os.h>
#include <core/class.h>
#include <core/handle.h>
#include <core/engctx.h>

View File

@ -23,7 +23,6 @@
*/
#include <core/os.h>
#include <core/class.h>
#include <core/client.h>
#include <core/handle.h>
#include <core/engctx.h>

View File

@ -25,16 +25,227 @@
#include "nvc0.h"
#include "ctxnvc0.h"
/*******************************************************************************
* Zero Bandwidth Clear
******************************************************************************/
static void
nvc0_graph_zbc_clear_color(struct nvc0_graph_priv *priv, int zbc)
{
if (priv->zbc_color[zbc].format) {
nv_wr32(priv, 0x405804, priv->zbc_color[zbc].ds[0]);
nv_wr32(priv, 0x405808, priv->zbc_color[zbc].ds[1]);
nv_wr32(priv, 0x40580c, priv->zbc_color[zbc].ds[2]);
nv_wr32(priv, 0x405810, priv->zbc_color[zbc].ds[3]);
}
nv_wr32(priv, 0x405814, priv->zbc_color[zbc].format);
nv_wr32(priv, 0x405820, zbc);
nv_wr32(priv, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */
}
static int
nvc0_graph_zbc_color_get(struct nvc0_graph_priv *priv, int format,
const u32 ds[4], const u32 l2[4])
{
struct nouveau_ltc *ltc = nouveau_ltc(priv);
int zbc = -ENOSPC, i;
for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
if (priv->zbc_color[i].format) {
if (priv->zbc_color[i].format != format)
continue;
if (memcmp(priv->zbc_color[i].ds, ds, sizeof(
priv->zbc_color[i].ds)))
continue;
if (memcmp(priv->zbc_color[i].l2, l2, sizeof(
priv->zbc_color[i].l2))) {
WARN_ON(1);
return -EINVAL;
}
return i;
} else {
zbc = (zbc < 0) ? i : zbc;
}
}
memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds));
memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2));
priv->zbc_color[zbc].format = format;
ltc->zbc_color_get(ltc, zbc, l2);
nvc0_graph_zbc_clear_color(priv, zbc);
return zbc;
}
static void
nvc0_graph_zbc_clear_depth(struct nvc0_graph_priv *priv, int zbc)
{
if (priv->zbc_depth[zbc].format)
nv_wr32(priv, 0x405818, priv->zbc_depth[zbc].ds);
nv_wr32(priv, 0x40581c, priv->zbc_depth[zbc].format);
nv_wr32(priv, 0x405820, zbc);
nv_wr32(priv, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */
}
static int
nvc0_graph_zbc_depth_get(struct nvc0_graph_priv *priv, int format,
const u32 ds, const u32 l2)
{
struct nouveau_ltc *ltc = nouveau_ltc(priv);
int zbc = -ENOSPC, i;
for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
if (priv->zbc_depth[i].format) {
if (priv->zbc_depth[i].format != format)
continue;
if (priv->zbc_depth[i].ds != ds)
continue;
if (priv->zbc_depth[i].l2 != l2) {
WARN_ON(1);
return -EINVAL;
}
return i;
} else {
zbc = (zbc < 0) ? i : zbc;
}
}
priv->zbc_depth[zbc].format = format;
priv->zbc_depth[zbc].ds = ds;
priv->zbc_depth[zbc].l2 = l2;
ltc->zbc_depth_get(ltc, zbc, l2);
nvc0_graph_zbc_clear_depth(priv, zbc);
return zbc;
}
/*******************************************************************************
* Graphics object classes
******************************************************************************/
static int
nvc0_fermi_mthd_zbc_color(struct nouveau_object *object, void *data, u32 size)
{
struct nvc0_graph_priv *priv = (void *)object->engine;
union {
struct fermi_a_zbc_color_v0 v0;
} *args = data;
int ret;
if (nvif_unpack(args->v0, 0, 0, false)) {
switch (args->v0.format) {
case FERMI_A_ZBC_COLOR_V0_FMT_ZERO:
case FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE:
case FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32:
case FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16:
case FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16:
case FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16:
case FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16:
case FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16:
case FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8:
case FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8:
case FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10:
case FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10:
case FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8:
case FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8:
case FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8:
case FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8:
case FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8:
case FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10:
case FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11:
ret = nvc0_graph_zbc_color_get(priv, args->v0.format,
args->v0.ds,
args->v0.l2);
if (ret >= 0) {
args->v0.index = ret;
return 0;
}
break;
default:
return -EINVAL;
}
}
return ret;
}
static int
nvc0_fermi_mthd_zbc_depth(struct nouveau_object *object, void *data, u32 size)
{
struct nvc0_graph_priv *priv = (void *)object->engine;
union {
struct fermi_a_zbc_depth_v0 v0;
} *args = data;
int ret;
if (nvif_unpack(args->v0, 0, 0, false)) {
switch (args->v0.format) {
case FERMI_A_ZBC_DEPTH_V0_FMT_FP32:
ret = nvc0_graph_zbc_depth_get(priv, args->v0.format,
args->v0.ds,
args->v0.l2);
return (ret >= 0) ? 0 : -ENOSPC;
default:
return -EINVAL;
}
}
return ret;
}
static int
nvc0_fermi_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
{
switch (mthd) {
case FERMI_A_ZBC_COLOR:
return nvc0_fermi_mthd_zbc_color(object, data, size);
case FERMI_A_ZBC_DEPTH:
return nvc0_fermi_mthd_zbc_depth(object, data, size);
default:
break;
}
return -EINVAL;
}
struct nouveau_ofuncs
nvc0_fermi_ofuncs = {
.ctor = _nouveau_object_ctor,
.dtor = nouveau_object_destroy,
.init = nouveau_object_init,
.fini = nouveau_object_fini,
.mthd = nvc0_fermi_mthd,
};
static int
nvc0_graph_set_shader_exceptions(struct nouveau_object *object, u32 mthd,
void *pdata, u32 size)
{
struct nvc0_graph_priv *priv = (void *)nv_engine(object);
if (size >= sizeof(u32)) {
u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000;
nv_wr32(priv, 0x419e44, data);
nv_wr32(priv, 0x419e4c, data);
return 0;
}
return -EINVAL;
}
struct nouveau_omthds
nvc0_graph_9097_omthds[] = {
{ 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
{}
};
struct nouveau_omthds
nvc0_graph_90c0_omthds[] = {
{ 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
{}
};
struct nouveau_oclass
nvc0_graph_sclass[] = {
{ 0x902d, &nouveau_object_ofuncs },
{ 0x9039, &nouveau_object_ofuncs },
{ 0x9097, &nouveau_object_ofuncs },
{ 0x90c0, &nouveau_object_ofuncs },
{ FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
{ FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
{}
};
@ -98,7 +309,7 @@ nvc0_graph_context_ctor(struct nouveau_object *parent,
u32 addr = mmio->addr;
u32 data = mmio->data;
if (mmio->shift) {
if (mmio->buffer >= 0) {
u64 info = chan->data[mmio->buffer].vma.offset;
data |= info >> mmio->shift;
}
@ -406,6 +617,35 @@ nvc0_graph_pack_mmio[] = {
* PGRAPH engine/subdev functions
******************************************************************************/
void
nvc0_graph_zbc_init(struct nvc0_graph_priv *priv)
{
const u32 zero[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000 };
const u32 one[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
const u32 f32_0[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000 };
const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 };
struct nouveau_ltc *ltc = nouveau_ltc(priv);
int index;
if (!priv->zbc_color[0].format) {
nvc0_graph_zbc_color_get(priv, 1, & zero[0], &zero[4]);
nvc0_graph_zbc_color_get(priv, 2, & one[0], &one[4]);
nvc0_graph_zbc_color_get(priv, 4, &f32_0[0], &f32_0[4]);
nvc0_graph_zbc_color_get(priv, 4, &f32_1[0], &f32_1[4]);
nvc0_graph_zbc_depth_get(priv, 1, 0x00000000, 0x00000000);
nvc0_graph_zbc_depth_get(priv, 1, 0x3f800000, 0x3f800000);
}
for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
nvc0_graph_zbc_clear_color(priv, index);
for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
nvc0_graph_zbc_clear_depth(priv, index);
}
void
nvc0_graph_mmio(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
{
@ -969,17 +1209,16 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
{
struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass;
struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass;
u32 r000260;
int i;
if (priv->firmware) {
/* load fuc microcode */
r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c,
&priv->fuc409d);
nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac,
&priv->fuc41ad);
nv_wr32(priv, 0x000260, r000260);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
/* start both of them running */
nv_wr32(priv, 0x409840, 0xffffffff);
@ -1066,7 +1305,7 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
}
/* load HUB microcode */
r000260 = nv_mask(priv, 0x000260, 0x00000001, 0x00000000);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
nv_wr32(priv, 0x4091c0, 0x01000000);
for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++)
nv_wr32(priv, 0x4091c4, oclass->fecs.ucode->data.data[i]);
@ -1089,7 +1328,7 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
nv_wr32(priv, 0x41a188, i >> 6);
nv_wr32(priv, 0x41a184, oclass->gpccs.ucode->code.data[i]);
}
nv_wr32(priv, 0x000260, r000260);
nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
/* load register lists */
nvc0_graph_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000);
@ -1224,6 +1463,9 @@ nvc0_graph_init(struct nouveau_object *object)
nv_wr32(priv, 0x400134, 0xffffffff);
nv_wr32(priv, 0x400054, 0x34ce3464);
nvc0_graph_zbc_init(priv);
return nvc0_graph_init_ctxctl(priv);
}
@ -1287,7 +1529,7 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_device *device = nv_device(parent);
struct nvc0_graph_priv *priv;
bool use_ext_fw, enable;
int ret, i;
int ret, i, j;
use_ext_fw = nouveau_boolopt(device->cfgopt, "NvGrUseFW",
oclass->fecs.ucode == NULL);
@ -1333,6 +1575,11 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
for (i = 0; i < priv->gpc_nr; i++) {
priv->tpc_nr[i] = nv_rd32(priv, GPC_UNIT(i, 0x2608));
priv->tpc_total += priv->tpc_nr[i];
priv->ppc_nr[i] = oclass->ppc_nr;
for (j = 0; j < priv->ppc_nr[i]; j++) {
u8 mask = nv_rd32(priv, GPC_UNIT(i, 0x0c30 + (j * 4)));
priv->ppc_tpc_nr[i][j] = hweight8(mask);
}
}
/*XXX: these need figuring out... though it might not even matter */

Some files were not shown because too many files have changed in this diff Show More