forked from Minki/linux
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:
commit
9138475862
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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(¬ify->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, ¬ify->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;
|
||||
|
@ -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))
|
||||
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;
|
||||
if (!(handler->types & types))
|
||||
continue;
|
||||
if (handler->func(handler->priv, handler->types & types, index)
|
||||
!= NVKM_EVENT_DROP)
|
||||
continue;
|
||||
nouveau_event_put(handler);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
531
drivers/gpu/drm/nouveau/core/core/ioctl.c
Normal file
531
drivers/gpu/drm/nouveau/core/core/ioctl.c
Normal 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;
|
||||
}
|
167
drivers/gpu/drm/nouveau/core/core/notify.c
Normal file
167
drivers/gpu/drm/nouveau/core/core/notify.c
Normal 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, ¬ify->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, ¬ify->flags))
|
||||
flush_work(¬ify->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, ¬ify->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, ¬ify->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, ¬ify->flags)) {
|
||||
memcpy((void *)notify->data, data, size);
|
||||
schedule_work(¬ify->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(¬ify->event->list_lock, flags);
|
||||
list_del(¬ify->head);
|
||||
spin_unlock_irqrestore(¬ify->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(¬ify->work, nvkm_notify_work);
|
||||
set_bit(NVKM_NOTIFY_WORK, ¬ify->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(¬ify->head, &event->list);
|
||||
spin_unlock_irqrestore(&event->list_lock, flags);
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
notify->event = NULL;
|
||||
return ret;
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <subdev/vm.h>
|
||||
|
||||
#include <core/client.h>
|
||||
#include <core/class.h>
|
||||
#include <core/enum.h>
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <core/os.h>
|
||||
#include <core/enum.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
|
||||
#include <engine/copy.h>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
59
drivers/gpu/drm/nouveau/core/engine/device/acpi.c
Normal file
59
drivers/gpu/drm/nouveau/core/engine/device/acpi.c
Normal 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;
|
||||
}
|
9
drivers/gpu/drm/nouveau/core/engine/device/acpi.h
Normal file
9
drivers/gpu/drm/nouveau/core/engine/device/acpi.h
Normal 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
|
@ -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;
|
||||
|
@ -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,
|
||||
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,
|
||||
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))
|
||||
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,
|
||||
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
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
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 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 -ENOSYS;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff;
|
||||
args->htotal = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff;
|
||||
args->hblanke = args->htotal - 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;
|
||||
|
||||
/*
|
||||
* 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 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)
|
||||
if (!args->v0.vtotal || !args->v0.htotal)
|
||||
return -ENOTSUPP;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
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;
|
||||
|
@ -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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)
|
||||
{
|
||||
nv_mask(event->priv, 0x61002c, (4 << head), 0);
|
||||
switch (mthd) {
|
||||
case NV50_DISP_SCANOUTPOS:
|
||||
return impl->head.scanoutpos(object, priv, data, size, head);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 ?
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
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 (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);
|
||||
|
||||
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;
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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))
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ctrl = !!args->v0.state;
|
||||
type = args->v0.type;
|
||||
} else
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/dcb.h>
|
||||
|
@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
|
||||
#include <subdev/bios.h>
|
||||
#include <subdev/bios/dcb.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -23,46 +23,46 @@
|
||||
*/
|
||||
|
||||
#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) {
|
||||
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);
|
||||
@ -70,74 +70,96 @@ nv04_dmaobj_bind(struct nouveau_dmaeng *dmaeng,
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
return dmaeng->bind(&priv->base, nv_object(priv), (void *)pobject);
|
||||
}
|
||||
|
||||
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;
|
||||
|
30
drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
Normal file
30
drivers/gpu/drm/nouveau/core/engine/dmaobj/priv.h
Normal 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
|
@ -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,6 +117,7 @@ nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan)
|
||||
struct nouveau_fifo *priv = (void *)nv_object(chan)->engine;
|
||||
unsigned long flags;
|
||||
|
||||
if (chan->user)
|
||||
iounmap(chan->user);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
104
drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
Normal file
104
drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
Normal 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;
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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[];
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
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];
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
|
117
drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c
Normal file
117
drivers/gpu/drm/nouveau/core/engine/graph/gk110b.c
Normal 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;
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <core/client.h>
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/handle.h>
|
||||
#include <core/namedb.h>
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <core/client.h>
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/handle.h>
|
||||
|
||||
#include <subdev/fb.h>
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/enum.h>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/enum.h>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/enum.h>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/enum.h>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/engctx.h>
|
||||
#include <core/enum.h>
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <core/client.h>
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/handle.h>
|
||||
#include <core/engctx.h>
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include <core/os.h>
|
||||
#include <core/class.h>
|
||||
#include <core/client.h>
|
||||
#include <core/handle.h>
|
||||
#include <core/engctx.h>
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user