Commit 02c4fb02 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'linux-4.21' of git://github.com/skeggsb/linux into drm-next

Mostly just initial support for Turing TU104/TU106 chipsets.  Support
for TU102 is missing as I don't yet have HW, but it should be trivial
to add in later in the merge window (in theory).

It's a bit of a rough first pass that'll get improved in future
releases as a finish figuring out some of the other HW changes, but
it's good enough as it stands for modesetting and suspend/resume etc.

Acceleration bring-up is incomplete due to NVIDIA not yet having
provided FW images for me to use, though command submission and copy
engines are functional already.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Ben Skeggs <skeggsb@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv7KmfcQqZcx+wh_1UKjTovp4PH_5UVMfeyxUu-M9WLZfw@mail.gmail.com
parents 29a1da27 8ff01abc
...@@ -67,7 +67,7 @@ nv04_display_create(struct drm_device *dev) ...@@ -67,7 +67,7 @@ nv04_display_create(struct drm_device *dev)
for (i = 0; i < dcb->entries; i++) { for (i = 0; i < dcb->entries; i++) {
struct dcb_output *dcbent = &dcb->entry[i]; struct dcb_output *dcbent = &dcb->entry[i];
connector = nouveau_connector_create(dev, dcbent->connector); connector = nouveau_connector_create(dev, dcbent);
if (IS_ERR(connector)) if (IS_ERR(connector))
continue; continue;
......
...@@ -7,6 +7,7 @@ nouveau-y += dispnv50/core827d.o ...@@ -7,6 +7,7 @@ nouveau-y += dispnv50/core827d.o
nouveau-y += dispnv50/core907d.o nouveau-y += dispnv50/core907d.o
nouveau-y += dispnv50/core917d.o nouveau-y += dispnv50/core917d.o
nouveau-y += dispnv50/corec37d.o nouveau-y += dispnv50/corec37d.o
nouveau-y += dispnv50/corec57d.o
nouveau-y += dispnv50/dac507d.o nouveau-y += dispnv50/dac507d.o
nouveau-y += dispnv50/dac907d.o nouveau-y += dispnv50/dac907d.o
...@@ -23,12 +24,14 @@ nouveau-y += dispnv50/head827d.o ...@@ -23,12 +24,14 @@ nouveau-y += dispnv50/head827d.o
nouveau-y += dispnv50/head907d.o nouveau-y += dispnv50/head907d.o
nouveau-y += dispnv50/head917d.o nouveau-y += dispnv50/head917d.o
nouveau-y += dispnv50/headc37d.o nouveau-y += dispnv50/headc37d.o
nouveau-y += dispnv50/headc57d.o
nouveau-y += dispnv50/wimm.o nouveau-y += dispnv50/wimm.o
nouveau-y += dispnv50/wimmc37b.o nouveau-y += dispnv50/wimmc37b.o
nouveau-y += dispnv50/wndw.o nouveau-y += dispnv50/wndw.o
nouveau-y += dispnv50/wndwc37e.o nouveau-y += dispnv50/wndwc37e.o
nouveau-y += dispnv50/wndwc57e.o
nouveau-y += dispnv50/base.o nouveau-y += dispnv50/base.o
nouveau-y += dispnv50/base507c.o nouveau-y += dispnv50/base507c.o
......
...@@ -54,9 +54,10 @@ struct nv50_head_atom { ...@@ -54,9 +54,10 @@ struct nv50_head_atom {
u64 offset:40; u64 offset:40;
u8 buffer:1; u8 buffer:1;
u8 mode:4; u8 mode:4;
u8 size:2; u16 size:11;
u8 range:2; u8 range:2;
u8 output_mode:2; u8 output_mode:2;
void (*load)(struct drm_color_lut *, int size, void __iomem *);
} olut; } olut;
struct { struct {
...@@ -169,9 +170,11 @@ struct nv50_wndw_atom { ...@@ -169,9 +170,11 @@ struct nv50_wndw_atom {
u8 buffer:1; u8 buffer:1;
u8 enable:2; u8 enable:2;
u8 mode:4; u8 mode:4;
u8 size:2; u16 size:11;
u8 range:2; u8 range:2;
u8 output_mode:2; u8 output_mode:2;
void (*load)(struct drm_color_lut *, int size,
void __iomem *);
} i; } i;
} xlut; } xlut;
......
...@@ -80,6 +80,7 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) ...@@ -80,6 +80,7 @@ base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{ {
asyw->xlut.i.mode = 7; asyw->xlut.i.mode = 7;
asyw->xlut.i.enable = 2; asyw->xlut.i.enable = 2;
asyw->xlut.i.load = head907d_olut_load;
} }
const struct nv50_wndw_func const struct nv50_wndw_func
......
...@@ -42,6 +42,7 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore) ...@@ -42,6 +42,7 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
int version; int version;
int (*new)(struct nouveau_drm *, s32, struct nv50_core **); int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
} cores[] = { } cores[] = {
{ TU104_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
{ GV100_DISP_CORE_CHANNEL_DMA, 0, corec37d_new }, { GV100_DISP_CORE_CHANNEL_DMA, 0, corec37d_new },
{ GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, { GP102_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
{ GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new }, { GP100_DISP_CORE_CHANNEL_DMA, 0, core917d_new },
......
...@@ -46,5 +46,9 @@ extern const struct nv50_outp_func sor907d; ...@@ -46,5 +46,9 @@ extern const struct nv50_outp_func sor907d;
int core917d_new(struct nouveau_drm *, s32, struct nv50_core **); int core917d_new(struct nouveau_drm *, s32, struct nv50_core **);
int corec37d_new(struct nouveau_drm *, s32, struct nv50_core **); int corec37d_new(struct nouveau_drm *, s32, struct nv50_core **);
int corec37d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
void corec37d_update(struct nv50_core *, u32 *, bool);
extern const struct nv50_outp_func sorc37d; extern const struct nv50_outp_func sorc37d;
int corec57d_new(struct nouveau_drm *, s32, struct nv50_core **);
#endif #endif
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <nouveau_bo.h> #include <nouveau_bo.h>
static void void
corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy) corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
{ {
u32 *push; u32 *push;
...@@ -71,7 +71,7 @@ corec37d_ntfy_init(struct nouveau_bo *bo, u32 offset) ...@@ -71,7 +71,7 @@ corec37d_ntfy_init(struct nouveau_bo *bo, u32 offset)
nouveau_bo_wr32(bo, offset / 4 + 3, 0x00000000); nouveau_bo_wr32(bo, offset / 4 + 3, 0x00000000);
} }
void static void
corec37d_init(struct nv50_core *core) corec37d_init(struct nv50_core *core)
{ {
const u32 windows = 8; /*XXX*/ const u32 windows = 8; /*XXX*/
......
/*
* Copyright 2018 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.
*/
#include "core.h"
#include "head.h"
static void
corec57d_init(struct nv50_core *core)
{
const u32 windows = 8; /*XXX*/
u32 *push, i;
if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) {
evo_mthd(push, 0x0208, 1);
evo_data(push, core->chan.sync.handle);
for (i = 0; i < windows; i++) {
evo_mthd(push, 0x1000 + (i * 0x080), 3);
evo_data(push, i >> 1);
evo_data(push, 0x0000000f);
evo_data(push, 0x00000000);
evo_mthd(push, 0x1010 + (i * 0x080), 1);
evo_data(push, 0x00117fff);
}
evo_mthd(push, 0x0200, 1);
evo_data(push, 0x00000001);
evo_kick(push, &core->chan);
}
}
static const struct nv50_core_func
corec57d = {
.init = corec57d_init,
.ntfy_init = corec37d_ntfy_init,
.ntfy_wait_done = corec37d_ntfy_wait_done,
.update = corec37d_update,
.head = &headc57d,
.sor = &sorc37d,
};
int
corec57d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
{
return core507d_new_(&corec57d, drm, oclass, pcore);
}
...@@ -31,6 +31,7 @@ nv50_curs_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw) ...@@ -31,6 +31,7 @@ nv50_curs_new(struct nouveau_drm *drm, int head, struct nv50_wndw **pwndw)
int version; int version;
int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **); int (*new)(struct nouveau_drm *, int, s32, struct nv50_wndw **);
} curses[] = { } curses[] = {
{ TU104_DISP_CURSOR, 0, cursc37a_new },
{ GV100_DISP_CURSOR, 0, cursc37a_new }, { GV100_DISP_CURSOR, 0, cursc37a_new },
{ GK104_DISP_CURSOR, 0, curs907a_new }, { GK104_DISP_CURSOR, 0, curs907a_new },
{ GF110_DISP_CURSOR, 0, curs907a_new }, { GF110_DISP_CURSOR, 0, curs907a_new },
......
...@@ -1255,8 +1255,16 @@ nv50_mstm_fini(struct nv50_mstm *mstm) ...@@ -1255,8 +1255,16 @@ nv50_mstm_fini(struct nv50_mstm *mstm)
static void static void
nv50_mstm_init(struct nv50_mstm *mstm) nv50_mstm_init(struct nv50_mstm *mstm)
{ {
if (mstm && mstm->mgr.mst_state) int ret;
drm_dp_mst_topology_mgr_resume(&mstm->mgr);
if (!mstm || !mstm->mgr.mst_state)
return;
ret = drm_dp_mst_topology_mgr_resume(&mstm->mgr);
if (ret == -1) {
drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false);
drm_kms_helper_hotplug_event(mstm->mgr.dev);
}
} }
static void static void
...@@ -2293,7 +2301,7 @@ nv50_display_create(struct drm_device *dev) ...@@ -2293,7 +2301,7 @@ nv50_display_create(struct drm_device *dev)
/* create encoder/connector objects based on VBIOS DCB table */ /* create encoder/connector objects based on VBIOS DCB table */
for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) { for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) {
connector = nouveau_connector_create(dev, dcbe->connector); connector = nouveau_connector_create(dev, dcbe);
if (IS_ERR(connector)) if (IS_ERR(connector))
continue; continue;
......
...@@ -45,6 +45,8 @@ struct nv50_disp_interlock { ...@@ -45,6 +45,8 @@ struct nv50_disp_interlock {
void corec37d_ntfy_init(struct nouveau_bo *, u32); void corec37d_ntfy_init(struct nouveau_bo *, u32);
void head907d_olut_load(struct drm_color_lut *, int size, void __iomem *);
struct nv50_chan { struct nv50_chan {
struct nvif_object user; struct nvif_object user;
struct nvif_device *device; struct nvif_device *device;
......
...@@ -50,9 +50,9 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -50,9 +50,9 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
if (asyh->set.core ) head->func->core_set(head, asyh); if (asyh->set.core ) head->func->core_set(head, asyh);
if (asyh->set.olut ) { if (asyh->set.olut ) {
asyh->olut.offset = nv50_lut_load(&head->olut, asyh->olut.offset = nv50_lut_load(&head->olut,
asyh->olut.mode <= 1,
asyh->olut.buffer, asyh->olut.buffer,
asyh->state.gamma_lut); asyh->state.gamma_lut,
asyh->olut.load);
head->func->olut_set(head, asyh); head->func->olut_set(head, asyh);
} }
if (asyh->set.curs ) head->func->curs_set(head, asyh); if (asyh->set.curs ) head->func->curs_set(head, asyh);
...@@ -210,7 +210,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head, ...@@ -210,7 +210,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
} }
} }
if (!olut) { if (!olut && !head->func->olut_identity) {
asyh->olut.handle = 0; asyh->olut.handle = 0;
return 0; return 0;
} }
......
...@@ -21,6 +21,7 @@ struct nv50_head_func { ...@@ -21,6 +21,7 @@ struct nv50_head_func {
void (*view)(struct nv50_head *, struct nv50_head_atom *); void (*view)(struct nv50_head *, struct nv50_head_atom *);
void (*mode)(struct nv50_head *, struct nv50_head_atom *); void (*mode)(struct nv50_head *, struct nv50_head_atom *);
void (*olut)(struct nv50_head *, struct nv50_head_atom *); void (*olut)(struct nv50_head *, struct nv50_head_atom *);
bool olut_identity;
void (*olut_set)(struct nv50_head *, struct nv50_head_atom *); void (*olut_set)(struct nv50_head *, struct nv50_head_atom *);
void (*olut_clr)(struct nv50_head *); void (*olut_clr)(struct nv50_head *);
void (*core_calc)(struct nv50_head *, struct nv50_head_atom *); void (*core_calc)(struct nv50_head *, struct nv50_head_atom *);
...@@ -75,4 +76,14 @@ int head917d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *, ...@@ -75,4 +76,14 @@ int head917d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *,
struct nv50_head_atom *); struct nv50_head_atom *);
extern const struct nv50_head_func headc37d; extern const struct nv50_head_func headc37d;
void headc37d_view(struct nv50_head *, struct nv50_head_atom *);
void headc37d_core_set(struct nv50_head *, struct nv50_head_atom *);
void headc37d_core_clr(struct nv50_head *);
int headc37d_curs_format(struct nv50_head *, struct nv50_wndw_atom *,
struct nv50_head_atom *);
void headc37d_curs_set(struct nv50_head *, struct nv50_head_atom *);
void headc37d_curs_clr(struct nv50_head *);
void headc37d_dither(struct nv50_head *, struct nv50_head_atom *);
extern const struct nv50_head_func headc57d;
#endif #endif
...@@ -254,6 +254,23 @@ head507d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -254,6 +254,23 @@ head507d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
} }
static void
head507d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
{
for (; size--; in++, mem += 8) {
writew(drm_color_lut_extract(in-> red, 11) << 3, mem + 0);
writew(drm_color_lut_extract(in->green, 11) << 3, mem + 2);
writew(drm_color_lut_extract(in-> blue, 11) << 3, mem + 4);
}
/* INTERPOLATE modes require a "next" entry to interpolate with,
* so we replicate the last entry to deal with this for now.
*/
writew(readw(mem - 8), mem + 0);
writew(readw(mem - 6), mem + 2);
writew(readw(mem - 4), mem + 4);
}
void void
head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
...@@ -261,6 +278,8 @@ head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -261,6 +278,8 @@ head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
asyh->olut.mode = 0; asyh->olut.mode = 0;
else else
asyh->olut.mode = 1; asyh->olut.mode = 1;
asyh->olut.load = head507d_olut_load;
} }
void void
......
...@@ -213,10 +213,28 @@ head907d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -213,10 +213,28 @@ head907d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
} }
void
head907d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
{
for (; size--; in++, mem += 8) {
writew(drm_color_lut_extract(in-> red, 14) + 0x6000, mem + 0);
writew(drm_color_lut_extract(in->green, 14) + 0x6000, mem + 2);
writew(drm_color_lut_extract(in-> blue, 14) + 0x6000, mem + 4);
}
/* INTERPOLATE modes require a "next" entry to interpolate with,
* so we replicate the last entry to deal with this for now.
*/
writew(readw(mem - 8), mem + 0);
writew(readw(mem - 6), mem + 2);
writew(readw(mem - 4), mem + 4);
}
void void
head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
asyh->olut.mode = 7; asyh->olut.mode = 7;
asyh->olut.load = head907d_olut_load;
} }
void void
......
...@@ -65,7 +65,7 @@ headc37d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -65,7 +65,7 @@ headc37d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
} }
static void void
headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
...@@ -79,7 +79,7 @@ headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -79,7 +79,7 @@ headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
} }
static void void
headc37d_curs_clr(struct nv50_head *head) headc37d_curs_clr(struct nv50_head *head)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
...@@ -93,7 +93,7 @@ headc37d_curs_clr(struct nv50_head *head) ...@@ -93,7 +93,7 @@ headc37d_curs_clr(struct nv50_head *head)
} }
} }
static void void
headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
...@@ -112,7 +112,7 @@ headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -112,7 +112,7 @@ headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
} }
static int int
headc37d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw, headc37d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw,
struct nv50_head_atom *asyh) struct nv50_head_atom *asyh)
{ {
...@@ -155,6 +155,7 @@ headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -155,6 +155,7 @@ headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
asyh->olut.size = 0; asyh->olut.size = 0;
asyh->olut.range = 0; asyh->olut.range = 0;
asyh->olut.output_mode = 1; asyh->olut.output_mode = 1;
asyh->olut.load = head907d_olut_load;
} }
static void static void
...@@ -181,7 +182,7 @@ headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -181,7 +182,7 @@ headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
} }
} }
static void void
headc37d_view(struct nv50_head *head, struct nv50_head_atom *asyh) headc37d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
......
/*
* Copyright 2018 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.
*/
#include "head.h"
#include "atom.h"
#include "core.h"
static void
headc57d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 2))) {
/*XXX: This is a dirty hack until OR depth handling is
* improved later for deep colour etc.
*/
switch (asyh->or.depth) {
case 6: asyh->or.depth = 5; break;
case 5: asyh->or.depth = 4; break;
case 2: asyh->or.depth = 1; break;
case 0: asyh->or.depth = 4; break;
default:
WARN_ON(1);
break;
}
evo_mthd(push, 0x2004 + (head->base.index * 0x400), 1);
evo_data(push, 0xfc000001 |
asyh->or.depth << 4 |
asyh->or.nvsync << 3 |
asyh->or.nhsync << 2);
evo_kick(push, core);
}
}
static void
headc57d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x2000 + (head->base.index * 0x400), 1);
#if 0
evo_data(push, 0x80000000 |
asyh->procamp.sat.sin << 16 |
asyh->procamp.sat.cos << 4);
#else
evo_data(push, 0);
#endif
evo_kick(push, core);
}
}
void
headc57d_olut_clr(struct nv50_head *head)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 2))) {
evo_mthd(push, 0x2288 + (head->base.index * 0x400), 1);
evo_data(push, 0x00000000);
evo_kick(push, core);
}
}
void
headc57d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
u32 *push;
if ((push = evo_wait(core, 4))) {
evo_mthd(push, 0x2280 + (head->base.index * 0x400), 4);
evo_data(push, asyh->olut.size << 8 |
asyh->olut.mode << 2 |
asyh->olut.output_mode);
evo_data(push, 0xffffffff); /* FP_NORM_SCALE. */
evo_data(push, asyh->olut.handle);
evo_data(push, asyh->olut.offset >> 8);
evo_kick(push, core);
}
}
static void
headc57d_olut_load_8(struct drm_color_lut *in, int size, void __iomem *mem)
{
memset_io(mem, 0x00, 0x20); /* VSS header. */
mem += 0x20;
while (size--) {
u16 r = drm_color_lut_extract(in-> red + 0, 16);
u16 g = drm_color_lut_extract(in->green + 0, 16);
u16 b = drm_color_lut_extract(in-> blue + 0, 16);
u16 ri = 0, gi = 0, bi = 0, i;
if (in++, size) {
ri = (drm_color_lut_extract(in-> red, 16) - r) / 4;
gi = (drm_color_lut_extract(in->green, 16) - g) / 4;
bi = (drm_color_lut_extract(in-> blue, 16) - b) / 4;
}
for (i = 0; i < 4; i++, mem += 8) {
writew(r + ri * i, mem + 0);
writew(g + gi * i, mem + 2);
writew(b + bi * i, mem + 4);
}
}
/* INTERPOLATE modes require a "next" entry to interpolate with,
* so we replicate the last entry to deal with this for now.
*/
writew(readw(mem - 8), mem + 0);
writew(readw(mem - 6), mem + 2);
writew(readw(mem - 4), mem + 4);
}
static void
headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
{
memset_io(mem, 0x00, 0x20); /* VSS header. */
mem += 0x20;
for (; size--; in++, mem += 0x08) {
writew(drm_color_lut_extract(in-> red, 16), mem + 0);
writew(drm_color_lut_extract(in->green, 16), mem + 2);
writew(drm_color_lut_extract(in-> blue, 16), mem + 4);
}
/* INTERPOLATE modes require a "next" entry to interpolate with,
* so we replicate the last entry to deal with this for now.
*/
writew(readw(mem - 8), mem + 0);
writew(readw(mem - 6), mem + 2);
writew(readw(mem - 4), mem + 4);
}
void
headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh)
{
asyh->olut.mode = 2; /* DIRECT10 */
asyh->olut.size = 4 /* VSS header. */ + 1024 + 1 /* Entries. */;
asyh->olut.output_mode = 1; /* INTERPOLATE_ENABLE. */
if (asyh->state.gamma_lut &&
asyh->state.gamma_lut->length / sizeof(struct drm_color_lut) == 256)
asyh->olut.load = headc57d_olut_load_8;
else
asyh->olut.load = headc57d_olut_load;
}
static void
headc57d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
struct nv50_head_mode *m = &asyh->mode;
u32 *push;
if ((push = evo_wait(core, 12))) {
evo_mthd(push, 0x2064 + (head->base.index * 0x400), 5);
evo_data(push, (m->v.active << 16) | m->h.active );
evo_data(push, (m->v.synce << 16) | m->h.synce );
evo_data(push, (m->v.blanke << 16) | m->h.blanke );
evo_data(push, (m->v.blanks << 16) | m->h.blanks );
evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
evo_mthd(push, 0x200c + (head->base.index * 0x400), 1);
evo_data(push, m->clock * 1000);
evo_mthd(push, 0x2028 + (head->base.index * 0x400), 1);
evo_data(push, m->clock * 1000);
/*XXX: HEAD_USAGE_BOUNDS, doesn't belong here. */
evo_mthd(push, 0x2030 + (head->base.index * 0x400), 1);
evo_data(push, 0x00001014);
evo_kick(push, core);
}
}
const struct nv50_head_func
headc57d = {
.view = headc37d_view,
.mode = headc57d_mode,
.olut = headc57d_olut,
.olut_identity = true,
.olut_set = headc57d_olut_set,
.olut_clr = headc57d_olut_clr,
.curs_layout = head917d_curs_layout,
.curs_format = headc37d_curs_format,
.curs_set = headc37d_curs_set,
.curs_clr = headc37d_curs_clr,
.dither = headc37d_dither,
.procamp = headc57d_procamp,
.or = headc57d_or,
};
...@@ -29,45 +29,29 @@ ...@@ -29,45 +29,29 @@
#include <nvif/class.h> #include <nvif/class.h>
u32 u32
nv50_lut_load(struct nv50_lut *lut, bool legacy, int buffer, nv50_lut_load(struct nv50_lut *lut, int buffer, struct drm_property_blob *blob,
struct drm_property_blob *blob) void (*load)(struct drm_color_lut *, int, void __iomem *))
{ {
struct drm_color_lut *in = (struct drm_color_lut *)blob->data; struct drm_color_lut *in = blob ? blob->data : NULL;
void __iomem *mem = lut->mem[buffer].object.map.ptr; void __iomem *mem = lut->mem[buffer].object.map.ptr;
const int size = blob->length / sizeof(*in); const u32 addr = lut->mem[buffer].addr;
int bits, shift, i; int i;
u16 zero, r, g, b;
u32 addr = lut->mem[buffer].addr;
/* This can't happen.. But it shuts the compiler up. */
if (WARN_ON(size != 256))
return 0;
if (legacy) { if (!in) {
bits = 11; in = kvmalloc_array(1024, sizeof(*in), GFP_KERNEL);
shift = 3; if (!WARN_ON(!in)) {
zero = 0x0000; for (i = 0; i < 1024; i++) {
in[i].red =
in[i].green =
in[i].blue = (i << 16) >> 10;
}
load(in, 1024, mem);
kvfree(in);
}
} else { } else {
bits = 14; load(in, blob->length / sizeof(*in), mem);
shift = 0;
zero = 0x6000;
}
for (i = 0; i < size; i++) {
r = (drm_color_lut_extract(in[i]. red, bits) + zero) << shift;
g = (drm_color_lut_extract(in[i].green, bits) + zero) << shift;
b = (drm_color_lut_extract(in[i]. blue, bits) + zero) << shift;
writew(r, mem + (i * 0x08) + 0);
writew(g, mem + (i * 0x08) + 2);
writew(b, mem + (i * 0x08) + 4);
} }
/* INTERPOLATE modes require a "next" entry to interpolate with,
* so we replicate the last entry to deal with this for now.
*/
writew(r, mem + (i * 0x08) + 0);
writew(g, mem + (i * 0x08) + 2);
writew(b, mem + (i * 0x08) + 4);
return addr; return addr;
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __NV50_KMS_LUT_H__ #define __NV50_KMS_LUT_H__
#include <nvif/mem.h> #include <nvif/mem.h>
struct drm_property_blob; struct drm_property_blob;
struct drm_color_lut;
struct nv50_disp; struct nv50_disp;
struct nv50_lut { struct nv50_lut {
...@@ -10,6 +11,6 @@ struct nv50_lut { ...@@ -10,6 +11,6 @@ struct nv50_lut {
int nv50_lut_init(struct nv50_disp *, struct nvif_mmu *, struct nv50_lut *); int nv50_lut_init(struct nv50_disp *, struct nvif_mmu *, struct nv50_lut *);
void nv50_lut_fini(struct nv50_lut *); void nv50_lut_fini(struct nv50_lut *);
u32 nv50_lut_load(struct nv50_lut *, bool legacy, int buffer, u32 nv50_lut_load(struct nv50_lut *, int buffer, struct drm_property_blob *,
struct drm_property_blob *); void (*)(struct drm_color_lut *, int size, void __iomem *));
#endif #endif
...@@ -31,6 +31,7 @@ nv50_wimm_init(struct nouveau_drm *drm, struct nv50_wndw *wndw) ...@@ -31,6 +31,7 @@ nv50_wimm_init(struct nouveau_drm *drm, struct nv50_wndw *wndw)
int version; int version;
int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *); int (*init)(struct nouveau_drm *, s32, struct nv50_wndw *);
} wimms[] = { } wimms[] = {
{ TU104_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
{ GV100_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init }, { GV100_DISP_WINDOW_IMM_CHANNEL_DMA, 0, wimmc37b_init },
{} {}
}; };
......
...@@ -139,10 +139,8 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock, ...@@ -139,10 +139,8 @@ nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 *interlock,
if (asyw->set.xlut ) { if (asyw->set.xlut ) {
if (asyw->ilut) { if (asyw->ilut) {
asyw->xlut.i.offset = asyw->xlut.i.offset =
nv50_lut_load(&wndw->ilut, nv50_lut_load(&wndw->ilut, asyw->xlut.i.buffer,
asyw->xlut.i.mode <= 1, asyw->ilut, asyw->xlut.i.load);
asyw->xlut.i.buffer,
asyw->ilut);
} }
wndw->func->xlut_set(wndw, asyw); wndw->func->xlut_set(wndw, asyw);
} }
...@@ -322,6 +320,11 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, ...@@ -322,6 +320,11 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw,
asyh->wndw.olut &= ~BIT(wndw->id); asyh->wndw.olut &= ~BIT(wndw->id);
} }
if (!ilut && wndw->func->ilut_identity) {
static struct drm_property_blob dummy = {};
ilut = &dummy;
}
/* Recalculate LUT state. */ /* Recalculate LUT state. */
memset(&asyw->xlut, 0x00, sizeof(asyw->xlut)); memset(&asyw->xlut, 0x00, sizeof(asyw->xlut));
if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) { if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) {
...@@ -623,6 +626,7 @@ nv50_wndw_new(struct nouveau_drm *drm, enum drm_plane_type type, int index, ...@@ -623,6 +626,7 @@ nv50_wndw_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
int (*new)(struct nouveau_drm *, enum drm_plane_type, int (*new)(struct nouveau_drm *, enum drm_plane_type,
int, s32, struct nv50_wndw **); int, s32, struct nv50_wndw **);
} wndws[] = { } wndws[] = {
{ TU104_DISP_WINDOW_CHANNEL_DMA, 0, wndwc57e_new },
{ GV100_DISP_WINDOW_CHANNEL_DMA, 0, wndwc37e_new }, { GV100_DISP_WINDOW_CHANNEL_DMA, 0, wndwc37e_new },
{} {}
}; };
......
...@@ -65,6 +65,7 @@ struct nv50_wndw_func { ...@@ -65,6 +65,7 @@ struct nv50_wndw_func {
int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset, int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset,
struct nvif_device *); struct nvif_device *);
void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *);
bool ilut_identity;
bool olut_core; bool olut_core;
void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
void (*xlut_clr)(struct nv50_wndw *); void (*xlut_clr)(struct nv50_wndw *);
...@@ -90,6 +91,23 @@ extern const struct nv50_wimm_func curs507a; ...@@ -90,6 +91,23 @@ extern const struct nv50_wimm_func curs507a;
int wndwc37e_new(struct nouveau_drm *, enum drm_plane_type, int, s32, int wndwc37e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
struct nv50_wndw **); struct nv50_wndw **);
int wndwc37e_new_(const struct nv50_wndw_func *, struct nouveau_drm *,
enum drm_plane_type type, int index, s32 oclass, u32 heads,
struct nv50_wndw **);
int wndwc37e_acquire(struct nv50_wndw *, struct nv50_wndw_atom *,
struct nv50_head_atom *);
void wndwc37e_release(struct nv50_wndw *, struct nv50_wndw_atom *,
struct nv50_head_atom *);
void wndwc37e_sema_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void wndwc37e_sema_clr(struct nv50_wndw *);
void wndwc37e_ntfy_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void wndwc37e_ntfy_clr(struct nv50_wndw *);
void wndwc37e_image_set(struct nv50_wndw *, struct nv50_wndw_atom *);
void wndwc37e_image_clr(struct nv50_wndw *);
void wndwc37e_update(struct nv50_wndw *, u32 *);
int wndwc57e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
struct nv50_wndw **);
int nv50_wndw_new(struct nouveau_drm *, enum drm_plane_type, int index, int nv50_wndw_new(struct nouveau_drm *, enum drm_plane_type, int index,
struct nv50_wndw **); struct nv50_wndw **);
......
...@@ -61,9 +61,10 @@ wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) ...@@ -61,9 +61,10 @@ wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
asyw->xlut.i.size = 0; asyw->xlut.i.size = 0;
asyw->xlut.i.range = 0; asyw->xlut.i.range = 0;
asyw->xlut.i.output_mode = 1; asyw->xlut.i.output_mode = 1;
asyw->xlut.i.load = head907d_olut_load;
} }
static void void
wndwc37e_image_clr(struct nv50_wndw *wndw) wndwc37e_image_clr(struct nv50_wndw *wndw)
{ {
u32 *push; u32 *push;
...@@ -76,7 +77,7 @@ wndwc37e_image_clr(struct nv50_wndw *wndw) ...@@ -76,7 +77,7 @@ wndwc37e_image_clr(struct nv50_wndw *wndw)
} }
} }
static void void
wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{ {
u32 *push; u32 *push;
...@@ -117,7 +118,7 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) ...@@ -117,7 +118,7 @@ wndwc37e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
evo_kick(push, &wndw->wndw); evo_kick(push, &wndw->wndw);
} }
static void void
wndwc37e_ntfy_clr(struct nv50_wndw *wndw) wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
{ {
u32 *push; u32 *push;
...@@ -128,7 +129,7 @@ wndwc37e_ntfy_clr(struct nv50_wndw *wndw) ...@@ -128,7 +129,7 @@ wndwc37e_ntfy_clr(struct nv50_wndw *wndw)
} }
} }
static void void
wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{ {
u32 *push; u32 *push;
...@@ -140,7 +141,7 @@ wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) ...@@ -140,7 +141,7 @@ wndwc37e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
} }
} }
static void void
wndwc37e_sema_clr(struct nv50_wndw *wndw) wndwc37e_sema_clr(struct nv50_wndw *wndw)
{ {
u32 *push; u32 *push;
...@@ -151,7 +152,7 @@ wndwc37e_sema_clr(struct nv50_wndw *wndw) ...@@ -151,7 +152,7 @@ wndwc37e_sema_clr(struct nv50_wndw *wndw)
} }
} }
static void void
wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{ {
u32 *push; u32 *push;
...@@ -165,7 +166,7 @@ wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) ...@@ -165,7 +166,7 @@ wndwc37e_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
} }
} }
static void void
wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock) wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
{ {
u32 *push; u32 *push;
...@@ -183,13 +184,13 @@ wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock) ...@@ -183,13 +184,13 @@ wndwc37e_update(struct nv50_wndw *wndw, u32 *interlock)
} }
} }
static void void
wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, wndwc37e_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
struct nv50_head_atom *asyh) struct nv50_head_atom *asyh)
{ {
} }
static int int
wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
struct nv50_head_atom *asyh) struct nv50_head_atom *asyh)
{ {
...@@ -236,7 +237,7 @@ wndwc37e = { ...@@ -236,7 +237,7 @@ wndwc37e = {
.update = wndwc37e_update, .update = wndwc37e_update,
}; };
static int int
wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm, wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm,
enum drm_plane_type type, int index, s32 oclass, u32 heads, enum drm_plane_type type, int index, s32 oclass, u32 heads,
struct nv50_wndw **pwndw) struct nv50_wndw **pwndw)
......
/*
* Copyright 2018 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.
*/
#include "wndw.h"
#include "atom.h"
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <nouveau_bo.h>
#include <nvif/clc37e.h>
static void
wndwc57e_ilut_clr(struct nv50_wndw *wndw)
{
u32 *push;
if ((push = evo_wait(&wndw->wndw, 2))) {
evo_mthd(push, 0x0444, 1);
evo_data(push, 0x00000000);
evo_kick(push, &wndw->wndw);
}
}
static void
wndwc57e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
u32 *push;
if ((push = evo_wait(&wndw->wndw, 4))) {
evo_mthd(push, 0x0440, 3);
evo_data(push, asyw->xlut.i.size << 8 |
asyw->xlut.i.mode << 2 |
asyw->xlut.i.output_mode);
evo_data(push, asyw->xlut.handle);
evo_data(push, asyw->xlut.i.offset >> 8);
evo_kick(push, &wndw->wndw);
}
}
static u16
fixedU0_16_FP16(u16 fixed)
{
int sign = 0, exp = 0, man = 0;
if (fixed) {
while (--exp && !(fixed & 0x8000))
fixed <<= 1;
man = ((fixed << 1) & 0xffc0) >> 6;
exp += 15;
}
return (sign << 15) | (exp << 10) | man;
}
static void
wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem)
{
memset_io(mem, 0x00, 0x20); /* VSS header. */
mem += 0x20;
for (; size--; in++, mem += 0x08) {
u16 r = fixedU0_16_FP16(drm_color_lut_extract(in-> red, 16));
u16 g = fixedU0_16_FP16(drm_color_lut_extract(in->green, 16));
u16 b = fixedU0_16_FP16(drm_color_lut_extract(in-> blue, 16));
writew(r, mem + 0);
writew(g, mem + 2);
writew(b, mem + 4);
}
/* INTERPOLATE modes require a "next" entry to interpolate with,
* so we replicate the last entry to deal with this for now.
*/
writew(readw(mem - 8), mem + 0);
writew(readw(mem - 6), mem + 2);
writew(readw(mem - 4), mem + 4);
}
static void
wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
u16 size = asyw->ilut->length / sizeof(struct drm_color_lut);
if (size == 256) {
asyw->xlut.i.mode = 1; /* DIRECT8. */
} else {
asyw->xlut.i.mode = 2; /* DIRECT10. */
size = 1024;
}
asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */;
asyw->xlut.i.output_mode = 0; /* INTERPOLATE_DISABLE. */
asyw->xlut.i.load = wndwc57e_ilut_load;
}
static const struct nv50_wndw_func
wndwc57e = {
.acquire = wndwc37e_acquire,
.release = wndwc37e_release,
.sema_set = wndwc37e_sema_set,
.sema_clr = wndwc37e_sema_clr,
.ntfy_set = wndwc37e_ntfy_set,
.ntfy_clr = wndwc37e_ntfy_clr,
.ntfy_reset = corec37d_ntfy_init,
.ntfy_wait_begun = base507c_ntfy_wait_begun,
.ilut = wndwc57e_ilut,
.ilut_identity = true,
.xlut_set = wndwc57e_ilut_set,
.xlut_clr = wndwc57e_ilut_clr,
.image_set = wndwc37e_image_set,
.image_clr = wndwc37e_image_clr,
.update = wndwc37e_update,
};
int
wndwc57e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
s32 oclass, struct nv50_wndw **pwndw)
{
return wndwc37e_new_(&wndwc57e, drm, type, index, oclass,
BIT(index >> 1), pwndw);
}
...@@ -32,6 +32,7 @@ struct nv_device_info_v0 { ...@@ -32,6 +32,7 @@ struct nv_device_info_v0 {
#define NV_DEVICE_INFO_V0_MAXWELL 0x09 #define NV_DEVICE_INFO_V0_MAXWELL 0x09
#define NV_DEVICE_INFO_V0_PASCAL 0x0a #define NV_DEVICE_INFO_V0_PASCAL 0x0a
#define NV_DEVICE_INFO_V0_VOLTA 0x0b #define NV_DEVICE_INFO_V0_VOLTA 0x0b
#define NV_DEVICE_INFO_V0_TURING 0x0c
__u8 family; __u8 family;
__u8 pad06[2]; __u8 pad06[2];
__u64 ram_size; __u64 ram_size;
......
...@@ -4,12 +4,13 @@ ...@@ -4,12 +4,13 @@
struct kepler_channel_gpfifo_a_v0 { struct kepler_channel_gpfifo_a_v0 {
__u8 version; __u8 version;
__u8 pad01[1]; __u8 priv;
__u16 chid; __u16 chid;
__u32 ilength; __u32 ilength;
__u64 ioffset; __u64 ioffset;
__u64 runlist; __u64 runlist;
__u64 vmm; __u64 vmm;
__u64 inst;
}; };
#define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00 #define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00
......
...@@ -68,7 +68,8 @@ ...@@ -68,7 +68,8 @@
#define KEPLER_CHANNEL_GPFIFO_B /* cla06f.h */ 0x0000a16f #define KEPLER_CHANNEL_GPFIFO_B /* cla06f.h */ 0x0000a16f
#define MAXWELL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000b06f #define MAXWELL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000b06f
#define PASCAL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c06f #define PASCAL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c06f
#define VOLTA_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c36f #define VOLTA_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c36f
#define TURING_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c46f
#define NV50_DISP /* cl5070.h */ 0x00005070 #define NV50_DISP /* cl5070.h */ 0x00005070
#define G82_DISP /* cl5070.h */ 0x00008270 #define G82_DISP /* cl5070.h */ 0x00008270
...@@ -83,6 +84,7 @@ ...@@ -83,6 +84,7 @@
#define GP100_DISP /* cl5070.h */ 0x00009770 #define GP100_DISP /* cl5070.h */ 0x00009770
#define GP102_DISP /* cl5070.h */ 0x00009870 #define GP102_DISP /* cl5070.h */ 0x00009870
#define GV100_DISP /* cl5070.h */ 0x0000c370 #define GV100_DISP /* cl5070.h */ 0x0000c370
#define TU104_DISP /* cl5070.h */ 0x0000c570
#define NV31_MPEG 0x00003174 #define NV31_MPEG 0x00003174
#define G82_MPEG 0x00008274 #define G82_MPEG 0x00008274
...@@ -95,6 +97,7 @@ ...@@ -95,6 +97,7 @@
#define GF110_DISP_CURSOR /* cl507a.h */ 0x0000907a #define GF110_DISP_CURSOR /* cl507a.h */ 0x0000907a
#define GK104_DISP_CURSOR /* cl507a.h */ 0x0000917a #define GK104_DISP_CURSOR /* cl507a.h */ 0x0000917a
#define GV100_DISP_CURSOR /* cl507a.h */ 0x0000c37a #define GV100_DISP_CURSOR /* cl507a.h */ 0x0000c37a
#define TU104_DISP_CURSOR /* cl507a.h */ 0x0000c57a
#define NV50_DISP_OVERLAY /* cl507b.h */ 0x0000507b #define NV50_DISP_OVERLAY /* cl507b.h */ 0x0000507b
#define G82_DISP_OVERLAY /* cl507b.h */ 0x0000827b #define G82_DISP_OVERLAY /* cl507b.h */ 0x0000827b
...@@ -103,6 +106,7 @@ ...@@ -103,6 +106,7 @@
#define GK104_DISP_OVERLAY /* cl507b.h */ 0x0000917b #define GK104_DISP_OVERLAY /* cl507b.h */ 0x0000917b
#define GV100_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c37b #define GV100_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c37b
#define TU104_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c57b
#define NV50_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000507c #define NV50_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000507c
#define G82_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000827c #define G82_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000827c
...@@ -125,6 +129,7 @@ ...@@ -125,6 +129,7 @@
#define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d #define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d
#define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d #define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d
#define GV100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c37d #define GV100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c37d
#define TU104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c57d
#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e #define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e
#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e #define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e
...@@ -134,6 +139,7 @@ ...@@ -134,6 +139,7 @@
#define GK104_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000917e #define GK104_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000917e
#define GV100_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c37e #define GV100_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c37e
#define TU104_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c57e
#define NV50_TESLA 0x00005097 #define NV50_TESLA 0x00005097
#define G82_TESLA 0x00008297 #define G82_TESLA 0x00008297
...@@ -183,6 +189,7 @@ ...@@ -183,6 +189,7 @@
#define PASCAL_DMA_COPY_A 0x0000c0b5 #define PASCAL_DMA_COPY_A 0x0000c0b5
#define PASCAL_DMA_COPY_B 0x0000c1b5 #define PASCAL_DMA_COPY_B 0x0000c1b5
#define VOLTA_DMA_COPY_A 0x0000c3b5 #define VOLTA_DMA_COPY_A 0x0000c3b5
#define TURING_DMA_COPY_A 0x0000c5b5
#define FERMI_DECOMPRESS 0x000090b8 #define FERMI_DECOMPRESS 0x000090b8
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NVIF_CLC36F_H__
#define __NVIF_CLC36F_H__
struct volta_channel_gpfifo_a_v0 {
__u8 version;
__u8 priv;
__u16 chid;
__u32 ilength;
__u64 ioffset;
__u64 runlist;
__u64 vmm;
__u64 inst;
__u32 token;
};
#define NVC36F_V0_NTFY_NON_STALL_INTERRUPT 0x00
#define NVC36F_V0_NTFY_KILLED 0x01
#endif
...@@ -61,7 +61,11 @@ enum nvkm_devidx { ...@@ -61,7 +61,11 @@ enum nvkm_devidx {
NVKM_ENGINE_NVENC2, NVKM_ENGINE_NVENC2,
NVKM_ENGINE_NVENC_LAST = NVKM_ENGINE_NVENC2, NVKM_ENGINE_NVENC_LAST = NVKM_ENGINE_NVENC2,
NVKM_ENGINE_NVDEC, NVKM_ENGINE_NVDEC0,
NVKM_ENGINE_NVDEC1,
NVKM_ENGINE_NVDEC2,
NVKM_ENGINE_NVDEC_LAST = NVKM_ENGINE_NVDEC2,
NVKM_ENGINE_PM, NVKM_ENGINE_PM,
NVKM_ENGINE_SEC, NVKM_ENGINE_SEC,
NVKM_ENGINE_SEC2, NVKM_ENGINE_SEC2,
...@@ -114,6 +118,7 @@ struct nvkm_device { ...@@ -114,6 +118,7 @@ struct nvkm_device {
GM100 = 0x110, GM100 = 0x110,
GP100 = 0x130, GP100 = 0x130,
GV100 = 0x140, GV100 = 0x140,
TU100 = 0x160,
} card_type; } card_type;
u32 chipset; u32 chipset;
u8 chiprev; u8 chiprev;
...@@ -163,7 +168,7 @@ struct nvkm_device { ...@@ -163,7 +168,7 @@ struct nvkm_device {
struct nvkm_engine *msppp; struct nvkm_engine *msppp;
struct nvkm_engine *msvld; struct nvkm_engine *msvld;
struct nvkm_engine *nvenc[3]; struct nvkm_engine *nvenc[3];
struct nvkm_nvdec *nvdec; struct nvkm_nvdec *nvdec[3];
struct nvkm_pm *pm; struct nvkm_pm *pm;
struct nvkm_engine *sec; struct nvkm_engine *sec;
struct nvkm_sec2 *sec2; struct nvkm_sec2 *sec2;
...@@ -235,7 +240,7 @@ struct nvkm_device_chip { ...@@ -235,7 +240,7 @@ struct nvkm_device_chip {
int (*msppp )(struct nvkm_device *, int idx, struct nvkm_engine **); int (*msppp )(struct nvkm_device *, int idx, struct nvkm_engine **);
int (*msvld )(struct nvkm_device *, int idx, struct nvkm_engine **); int (*msvld )(struct nvkm_device *, int idx, struct nvkm_engine **);
int (*nvenc[3])(struct nvkm_device *, int idx, struct nvkm_engine **); int (*nvenc[3])(struct nvkm_device *, int idx, struct nvkm_engine **);
int (*nvdec )(struct nvkm_device *, int idx, struct nvkm_nvdec **); int (*nvdec[3])(struct nvkm_device *, int idx, struct nvkm_nvdec **);
int (*pm )(struct nvkm_device *, int idx, struct nvkm_pm **); int (*pm )(struct nvkm_device *, int idx, struct nvkm_pm **);
int (*sec )(struct nvkm_device *, int idx, struct nvkm_engine **); int (*sec )(struct nvkm_device *, int idx, struct nvkm_engine **);
int (*sec2 )(struct nvkm_device *, int idx, struct nvkm_sec2 **); int (*sec2 )(struct nvkm_device *, int idx, struct nvkm_sec2 **);
......
...@@ -29,6 +29,7 @@ struct nvkm_memory_func { ...@@ -29,6 +29,7 @@ struct nvkm_memory_func {
void *(*dtor)(struct nvkm_memory *); void *(*dtor)(struct nvkm_memory *);
enum nvkm_memory_target (*target)(struct nvkm_memory *); enum nvkm_memory_target (*target)(struct nvkm_memory *);
u8 (*page)(struct nvkm_memory *); u8 (*page)(struct nvkm_memory *);
u64 (*bar2)(struct nvkm_memory *);
u64 (*addr)(struct nvkm_memory *); u64 (*addr)(struct nvkm_memory *);
u64 (*size)(struct nvkm_memory *); u64 (*size)(struct nvkm_memory *);
void (*boot)(struct nvkm_memory *, struct nvkm_vmm *); void (*boot)(struct nvkm_memory *, struct nvkm_vmm *);
...@@ -56,6 +57,7 @@ void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *, ...@@ -56,6 +57,7 @@ void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *,
#define nvkm_memory_target(p) (p)->func->target(p) #define nvkm_memory_target(p) (p)->func->target(p)
#define nvkm_memory_page(p) (p)->func->page(p) #define nvkm_memory_page(p) (p)->func->page(p)
#define nvkm_memory_bar2(p) (p)->func->bar2(p)
#define nvkm_memory_addr(p) (p)->func->addr(p) #define nvkm_memory_addr(p) (p)->func->addr(p)
#define nvkm_memory_size(p) (p)->func->size(p) #define nvkm_memory_size(p) (p)->func->size(p)
#define nvkm_memory_boot(p,v) (p)->func->boot((p),(v)) #define nvkm_memory_boot(p,v) (p)->func->boot((p),(v))
......
...@@ -11,4 +11,5 @@ int gm200_ce_new(struct nvkm_device *, int, struct nvkm_engine **); ...@@ -11,4 +11,5 @@ int gm200_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **); int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
int gp102_ce_new(struct nvkm_device *, int, struct nvkm_engine **); int gp102_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
int gv100_ce_new(struct nvkm_device *, int, struct nvkm_engine **); int gv100_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
int tu104_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
#endif #endif
...@@ -36,4 +36,5 @@ int gm200_disp_new(struct nvkm_device *, int, struct nvkm_disp **); ...@@ -36,4 +36,5 @@ int gm200_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gv100_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gv100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int tu104_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
#endif #endif
...@@ -74,4 +74,5 @@ int gm20b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); ...@@ -74,4 +74,5 @@ int gm20b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int gp100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); int gp100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int gp10b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); int gp10b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int gv100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **); int gv100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
int tu104_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
#endif #endif
...@@ -16,8 +16,10 @@ struct nvkm_bar { ...@@ -16,8 +16,10 @@ struct nvkm_bar {
}; };
struct nvkm_vmm *nvkm_bar_bar1_vmm(struct nvkm_device *); struct nvkm_vmm *nvkm_bar_bar1_vmm(struct nvkm_device *);
void nvkm_bar_bar1_reset(struct nvkm_device *);
void nvkm_bar_bar2_init(struct nvkm_device *); void nvkm_bar_bar2_init(struct nvkm_device *);
void nvkm_bar_bar2_fini(struct nvkm_device *); void nvkm_bar_bar2_fini(struct nvkm_device *);
void nvkm_bar_bar2_reset(struct nvkm_device *);
struct nvkm_vmm *nvkm_bar_bar2_vmm(struct nvkm_device *); struct nvkm_vmm *nvkm_bar_bar2_vmm(struct nvkm_device *);
void nvkm_bar_flush(struct nvkm_bar *); void nvkm_bar_flush(struct nvkm_bar *);
...@@ -27,4 +29,5 @@ int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **); ...@@ -27,4 +29,5 @@ int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **); int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
int gm107_bar_new(struct nvkm_device *, int, struct nvkm_bar **); int gm107_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
int gm20b_bar_new(struct nvkm_device *, int, struct nvkm_bar **); int gm20b_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
int tu104_bar_new(struct nvkm_device *, int, struct nvkm_bar **);
#endif #endif
...@@ -12,11 +12,14 @@ u32 nvbios_M0203Tp(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, ...@@ -12,11 +12,14 @@ u32 nvbios_M0203Tp(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
struct nvbios_M0203T *); struct nvbios_M0203T *);
struct nvbios_M0203E { struct nvbios_M0203E {
#define M0203E_TYPE_DDR2 0x0 #define M0203E_TYPE_DDR2 0x0
#define M0203E_TYPE_DDR3 0x1 #define M0203E_TYPE_DDR3 0x1
#define M0203E_TYPE_GDDR3 0x2 #define M0203E_TYPE_GDDR3 0x2
#define M0203E_TYPE_GDDR5 0x3 #define M0203E_TYPE_GDDR5 0x3
#define M0203E_TYPE_SKIP 0xf #define M0203E_TYPE_HBM2 0x6
#define M0203E_TYPE_GDDR5X 0x8
#define M0203E_TYPE_GDDR6 0x9
#define M0203E_TYPE_SKIP 0xf
u8 type; u8 type;
u8 strap; u8 strap;
u8 group; u8 group;
......
...@@ -20,6 +20,7 @@ enum dcb_connector_type { ...@@ -20,6 +20,7 @@ enum dcb_connector_type {
DCB_CONNECTOR_DMS59_DP0 = 0x64, DCB_CONNECTOR_DMS59_DP0 = 0x64,
DCB_CONNECTOR_DMS59_DP1 = 0x65, DCB_CONNECTOR_DMS59_DP1 = 0x65,
DCB_CONNECTOR_WFD = 0x70, DCB_CONNECTOR_WFD = 0x70,
DCB_CONNECTOR_USB_C = 0x71,
DCB_CONNECTOR_NONE = 0xff DCB_CONNECTOR_NONE = 0xff
}; };
......
...@@ -31,4 +31,5 @@ int gf100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); ...@@ -31,4 +31,5 @@ int gf100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
int gm107_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); int gm107_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
int gm200_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); int gm200_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
int gv100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **); int gv100_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
int tu104_devinit_new(struct nvkm_device *, int, struct nvkm_devinit **);
#endif #endif
...@@ -30,4 +30,5 @@ struct nvkm_fault_data { ...@@ -30,4 +30,5 @@ struct nvkm_fault_data {
int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **); int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
int gv100_fault_new(struct nvkm_device *, int, struct nvkm_fault **); int gv100_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
int tu104_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
#endif #endif
...@@ -105,7 +105,10 @@ enum nvkm_ram_type { ...@@ -105,7 +105,10 @@ enum nvkm_ram_type {
NVKM_RAM_TYPE_GDDR2, NVKM_RAM_TYPE_GDDR2,
NVKM_RAM_TYPE_GDDR3, NVKM_RAM_TYPE_GDDR3,
NVKM_RAM_TYPE_GDDR4, NVKM_RAM_TYPE_GDDR4,
NVKM_RAM_TYPE_GDDR5 NVKM_RAM_TYPE_GDDR5,
NVKM_RAM_TYPE_GDDR5X,
NVKM_RAM_TYPE_GDDR6,
NVKM_RAM_TYPE_HBM2,
}; };
struct nvkm_ram { struct nvkm_ram {
......
...@@ -31,4 +31,5 @@ int gk104_mc_new(struct nvkm_device *, int, struct nvkm_mc **); ...@@ -31,4 +31,5 @@ int gk104_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
int gp100_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int gp100_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
int gp10b_mc_new(struct nvkm_device *, int, struct nvkm_mc **); int gp10b_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
int tu104_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
#endif #endif
...@@ -130,4 +130,5 @@ int gm20b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); ...@@ -130,4 +130,5 @@ int gm20b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
int gp100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); int gp100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
int gp10b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); int gp10b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
int gv100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); int gv100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
int tu104_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **);
#endif #endif
...@@ -28,6 +28,18 @@ struct nvkm_timer { ...@@ -28,6 +28,18 @@ struct nvkm_timer {
u64 nvkm_timer_read(struct nvkm_timer *); u64 nvkm_timer_read(struct nvkm_timer *);
void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *); void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *);
struct nvkm_timer_wait {
struct nvkm_timer *tmr;
u64 limit;
u64 time0;
u64 time1;
int reads;
};
void nvkm_timer_wait_init(struct nvkm_device *, u64 nsec,
struct nvkm_timer_wait *);
s64 nvkm_timer_wait_test(struct nvkm_timer_wait *);
/* Delay based on GPU time (ie. PTIMER). /* Delay based on GPU time (ie. PTIMER).
* *
* Will return -ETIMEDOUT unless the loop was terminated with 'break', * Will return -ETIMEDOUT unless the loop was terminated with 'break',
...@@ -38,21 +50,17 @@ void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *); ...@@ -38,21 +50,17 @@ void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *);
*/ */
#define NVKM_DELAY _warn = false; #define NVKM_DELAY _warn = false;
#define nvkm_nsec(d,n,cond...) ({ \ #define nvkm_nsec(d,n,cond...) ({ \
struct nvkm_device *_device = (d); \ struct nvkm_timer_wait _wait; \
struct nvkm_timer *_tmr = _device->timer; \
u64 _nsecs = (n), _time0 = nvkm_timer_read(_tmr); \
s64 _taken = 0; \
bool _warn = true; \ bool _warn = true; \
s64 _taken = 0; \
\ \
nvkm_timer_wait_init((d), (n), &_wait); \
do { \ do { \
cond \ cond \
} while (_taken = nvkm_timer_read(_tmr) - _time0, _taken < _nsecs); \ } while ((_taken = nvkm_timer_wait_test(&_wait)) >= 0); \
\ \
if (_taken >= _nsecs) { \ if (_warn && _taken < 0) \
if (_warn) \ dev_WARN(_wait.tmr->subdev.device->dev, "timeout\n"); \
dev_WARN(_device->dev, "timeout\n"); \
_taken = -ETIMEDOUT; \
} \
_taken; \ _taken; \
}) })
#define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond) #define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond)
......
...@@ -306,7 +306,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) ...@@ -306,7 +306,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
/* create channel object and initialise dma and fence management */ /* create channel object and initialise dma and fence management */
ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle, ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
init->tt_ctxdma_handle, &chan->chan); init->tt_ctxdma_handle, false, &chan->chan);
if (ret) if (ret)
goto done; goto done;
......
...@@ -1141,6 +1141,8 @@ nouveau_bo_move_init(struct nouveau_drm *drm) ...@@ -1141,6 +1141,8 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
struct ttm_mem_reg *, struct ttm_mem_reg *); struct ttm_mem_reg *, struct ttm_mem_reg *);
int (*init)(struct nouveau_channel *, u32 handle); int (*init)(struct nouveau_channel *, u32 handle);
} _methods[] = { } _methods[] = {
{ "COPY", 4, 0xc5b5, nve0_bo_move_copy, nve0_bo_move_init },
{ "GRCE", 0, 0xc5b5, nve0_bo_move_copy, nvc0_bo_move_init },
{ "COPY", 4, 0xc3b5, nve0_bo_move_copy, nve0_bo_move_init }, { "COPY", 4, 0xc3b5, nve0_bo_move_copy, nve0_bo_move_init },
{ "GRCE", 0, 0xc3b5, nve0_bo_move_copy, nvc0_bo_move_init }, { "GRCE", 0, 0xc3b5, nve0_bo_move_copy, nvc0_bo_move_init },
{ "COPY", 4, 0xc1b5, nve0_bo_move_copy, nve0_bo_move_init }, { "COPY", 4, 0xc1b5, nve0_bo_move_copy, nve0_bo_move_init },
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <nvif/cl506f.h> #include <nvif/cl506f.h>
#include <nvif/cl906f.h> #include <nvif/cl906f.h>
#include <nvif/cla06f.h> #include <nvif/cla06f.h>
#include <nvif/clc36f.h>
#include <nvif/ioctl.h> #include <nvif/ioctl.h>
/*XXX*/ /*XXX*/
...@@ -217,10 +218,11 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -217,10 +218,11 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
static int static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
u64 runlist, struct nouveau_channel **pchan) u64 runlist, bool priv, struct nouveau_channel **pchan)
{ {
struct nouveau_cli *cli = (void *)device->object.client; struct nouveau_cli *cli = (void *)device->object.client;
static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A, static const u16 oclasses[] = { TURING_CHANNEL_GPFIFO_A,
VOLTA_CHANNEL_GPFIFO_A,
PASCAL_CHANNEL_GPFIFO_A, PASCAL_CHANNEL_GPFIFO_A,
MAXWELL_CHANNEL_GPFIFO_A, MAXWELL_CHANNEL_GPFIFO_A,
KEPLER_CHANNEL_GPFIFO_B, KEPLER_CHANNEL_GPFIFO_B,
...@@ -234,6 +236,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -234,6 +236,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
struct nv50_channel_gpfifo_v0 nv50; struct nv50_channel_gpfifo_v0 nv50;
struct fermi_channel_gpfifo_v0 fermi; struct fermi_channel_gpfifo_v0 fermi;
struct kepler_channel_gpfifo_a_v0 kepler; struct kepler_channel_gpfifo_a_v0 kepler;
struct volta_channel_gpfifo_a_v0 volta;
} args; } args;
struct nouveau_channel *chan; struct nouveau_channel *chan;
u32 size; u32 size;
...@@ -247,12 +250,22 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -247,12 +250,22 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
/* create channel object */ /* create channel object */
do { do {
if (oclass[0] >= VOLTA_CHANNEL_GPFIFO_A) {
args.volta.version = 0;
args.volta.ilength = 0x02000;
args.volta.ioffset = 0x10000 + chan->push.addr;
args.volta.runlist = runlist;
args.volta.vmm = nvif_handle(&cli->vmm.vmm.object);
args.volta.priv = priv;
size = sizeof(args.volta);
} else
if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) { if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
args.kepler.version = 0; args.kepler.version = 0;
args.kepler.ilength = 0x02000; args.kepler.ilength = 0x02000;
args.kepler.ioffset = 0x10000 + chan->push.addr; args.kepler.ioffset = 0x10000 + chan->push.addr;
args.kepler.runlist = runlist; args.kepler.runlist = runlist;
args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object); args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
args.kepler.priv = priv;
size = sizeof(args.kepler); size = sizeof(args.kepler);
} else } else
if (oclass[0] >= FERMI_CHANNEL_GPFIFO) { if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
...@@ -273,13 +286,20 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -273,13 +286,20 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
ret = nvif_object_init(&device->object, 0, *oclass++, ret = nvif_object_init(&device->object, 0, *oclass++,
&args, size, &chan->user); &args, size, &chan->user);
if (ret == 0) { if (ret == 0) {
if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) if (chan->user.oclass >= VOLTA_CHANNEL_GPFIFO_A) {
chan->chid = args.volta.chid;
chan->inst = args.volta.inst;
chan->token = args.volta.token;
} else
if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) {
chan->chid = args.kepler.chid; chan->chid = args.kepler.chid;
else chan->inst = args.kepler.inst;
if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) } else
if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
chan->chid = args.fermi.chid; chan->chid = args.fermi.chid;
else } else {
chan->chid = args.nv50.chid; chan->chid = args.nv50.chid;
}
return ret; return ret;
} }
} while (*oclass); } while (*oclass);
...@@ -448,7 +468,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) ...@@ -448,7 +468,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
int int
nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
u32 arg0, u32 arg1, struct nouveau_channel **pchan) u32 arg0, u32 arg1, bool priv,
struct nouveau_channel **pchan)
{ {
struct nouveau_cli *cli = (void *)device->object.client; struct nouveau_cli *cli = (void *)device->object.client;
bool super; bool super;
...@@ -458,7 +479,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, ...@@ -458,7 +479,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
super = cli->base.super; super = cli->base.super;
cli->base.super = true; cli->base.super = true;
ret = nouveau_channel_ind(drm, device, arg0, pchan); ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
if (ret) { if (ret) {
NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
ret = nouveau_channel_dma(drm, device, pchan); ret = nouveau_channel_dma(drm, device, pchan);
......
...@@ -10,6 +10,8 @@ struct nouveau_channel { ...@@ -10,6 +10,8 @@ struct nouveau_channel {
struct nouveau_drm *drm; struct nouveau_drm *drm;
int chid; int chid;
u64 inst;
u32 token;
struct nvif_object vram; struct nvif_object vram;
struct nvif_object gart; struct nvif_object gart;
...@@ -48,7 +50,8 @@ struct nouveau_channel { ...@@ -48,7 +50,8 @@ struct nouveau_channel {
int nouveau_channels_init(struct nouveau_drm *); int nouveau_channels_init(struct nouveau_drm *);
int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
u32 arg0, u32 arg1, struct nouveau_channel **); u32 arg0, u32 arg1, bool priv,
struct nouveau_channel **);
void nouveau_channel_del(struct nouveau_channel **); void nouveau_channel_del(struct nouveau_channel **);
int nouveau_channel_idle(struct nouveau_channel *); int nouveau_channel_idle(struct nouveau_channel *);
......
...@@ -403,6 +403,7 @@ nouveau_connector_destroy(struct drm_connector *connector) ...@@ -403,6 +403,7 @@ nouveau_connector_destroy(struct drm_connector *connector)
if (nv_connector->aux.transfer) { if (nv_connector->aux.transfer) {
drm_dp_cec_unregister_connector(&nv_connector->aux); drm_dp_cec_unregister_connector(&nv_connector->aux);
drm_dp_aux_unregister(&nv_connector->aux); drm_dp_aux_unregister(&nv_connector->aux);
kfree(nv_connector->aux.name);
} }
kfree(connector); kfree(connector);
} }
...@@ -1218,7 +1219,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb) ...@@ -1218,7 +1219,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS; case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS;
case DCB_CONNECTOR_DMS59_DP0: case DCB_CONNECTOR_DMS59_DP0:
case DCB_CONNECTOR_DMS59_DP1: case DCB_CONNECTOR_DMS59_DP1:
case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort; case DCB_CONNECTOR_DP :
case DCB_CONNECTOR_USB_C : return DRM_MODE_CONNECTOR_DisplayPort;
case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP;
case DCB_CONNECTOR_HDMI_0 : case DCB_CONNECTOR_HDMI_0 :
case DCB_CONNECTOR_HDMI_1 : case DCB_CONNECTOR_HDMI_1 :
...@@ -1232,7 +1234,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb) ...@@ -1232,7 +1234,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
} }
struct drm_connector * struct drm_connector *
nouveau_connector_create(struct drm_device *dev, int index) nouveau_connector_create(struct drm_device *dev,
const struct dcb_output *dcbe)
{ {
const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
...@@ -1240,6 +1243,8 @@ nouveau_connector_create(struct drm_device *dev, int index) ...@@ -1240,6 +1243,8 @@ nouveau_connector_create(struct drm_device *dev, int index)
struct nouveau_connector *nv_connector = NULL; struct nouveau_connector *nv_connector = NULL;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_list_iter conn_iter; struct drm_connector_list_iter conn_iter;
char aux_name[48] = {0};
int index = dcbe->connector;
int type, ret = 0; int type, ret = 0;
bool dummy; bool dummy;
...@@ -1342,6 +1347,9 @@ nouveau_connector_create(struct drm_device *dev, int index) ...@@ -1342,6 +1347,9 @@ nouveau_connector_create(struct drm_device *dev, int index)
case DRM_MODE_CONNECTOR_eDP: case DRM_MODE_CONNECTOR_eDP:
nv_connector->aux.dev = dev->dev; nv_connector->aux.dev = dev->dev;
nv_connector->aux.transfer = nouveau_connector_aux_xfer; nv_connector->aux.transfer = nouveau_connector_aux_xfer;
snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x",
dcbe->hasht, dcbe->hashm);
nv_connector->aux.name = kstrdup(aux_name, GFP_KERNEL);
ret = drm_dp_aux_register(&nv_connector->aux); ret = drm_dp_aux_register(&nv_connector->aux);
if (ret) { if (ret) {
NV_ERROR(drm, "failed to register aux channel\n"); NV_ERROR(drm, "failed to register aux channel\n");
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "nouveau_encoder.h" #include "nouveau_encoder.h"
struct nvkm_i2c_port; struct nvkm_i2c_port;
struct dcb_output;
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
struct nouveau_backlight; struct nouveau_backlight;
...@@ -113,7 +114,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) ...@@ -113,7 +114,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
} }
struct drm_connector * struct drm_connector *
nouveau_connector_create(struct drm_device *, int index); nouveau_connector_create(struct drm_device *, const struct dcb_output *);
extern int nouveau_tv_disable; extern int nouveau_tv_disable;
extern int nouveau_ignorelid; extern int nouveau_ignorelid;
......
...@@ -46,6 +46,26 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data) ...@@ -46,6 +46,26 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
return 0; return 0;
} }
static int
nouveau_debugfs_strap_peek(struct seq_file *m, void *data)
{
struct drm_info_node *node = m->private;
struct nouveau_drm *drm = nouveau_drm(node->minor->dev);
int ret;
ret = pm_runtime_get_sync(drm->dev->dev);
if (ret < 0 && ret != -EACCES)
return ret;
seq_printf(m, "0x%08x\n",
nvif_rd32(&drm->client.device.object, 0x101000));
pm_runtime_mark_last_busy(drm->dev->dev);
pm_runtime_put_autosuspend(drm->dev->dev);
return 0;
}
static int static int
nouveau_debugfs_pstate_get(struct seq_file *m, void *data) nouveau_debugfs_pstate_get(struct seq_file *m, void *data)
{ {
...@@ -185,7 +205,8 @@ static const struct file_operations nouveau_pstate_fops = { ...@@ -185,7 +205,8 @@ static const struct file_operations nouveau_pstate_fops = {
}; };
static struct drm_info_list nouveau_debugfs_list[] = { static struct drm_info_list nouveau_debugfs_list[] = {
{ "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
{ "strap_peek", nouveau_debugfs_strap_peek, 0, NULL },
}; };
#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list) #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
...@@ -199,8 +220,9 @@ static const struct nouveau_debugfs_files { ...@@ -199,8 +220,9 @@ static const struct nouveau_debugfs_files {
int int
nouveau_drm_debugfs_init(struct drm_minor *minor) nouveau_drm_debugfs_init(struct drm_minor *minor)
{ {
struct nouveau_drm *drm = nouveau_drm(minor->dev);
struct dentry *dentry; struct dentry *dentry;
int i; int i, ret;
for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) { for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
dentry = debugfs_create_file(nouveau_debugfs_files[i].name, dentry = debugfs_create_file(nouveau_debugfs_files[i].name,
...@@ -211,9 +233,23 @@ nouveau_drm_debugfs_init(struct drm_minor *minor) ...@@ -211,9 +233,23 @@ nouveau_drm_debugfs_init(struct drm_minor *minor)
return -ENOMEM; return -ENOMEM;
} }
return drm_debugfs_create_files(nouveau_debugfs_list, ret = drm_debugfs_create_files(nouveau_debugfs_list,
NOUVEAU_DEBUGFS_ENTRIES, NOUVEAU_DEBUGFS_ENTRIES,
minor->debugfs_root, minor); minor->debugfs_root, minor);
if (ret)
return ret;
/* Set the size of the vbios since we know it, and it's confusing to
* userspace if it wants to seek() but the file has a length of 0
*/
dentry = debugfs_lookup("vbios.rom", minor->debugfs_root);
if (!dentry)
return 0;
d_inode(dentry)->i_size = drm->vbios.length;
dput(dentry);
return 0;
} }
int int
......
...@@ -101,7 +101,7 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length) ...@@ -101,7 +101,7 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put); nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put);
if (user->func && user->func->doorbell) if (user->func && user->func->doorbell)
user->func->doorbell(user, chan->chid); user->func->doorbell(user, chan->token);
chan->dma.ib_free--; chan->dma.ib_free--;
} }
......
...@@ -353,6 +353,7 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -353,6 +353,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
case MAXWELL_CHANNEL_GPFIFO_A: case MAXWELL_CHANNEL_GPFIFO_A:
case PASCAL_CHANNEL_GPFIFO_A: case PASCAL_CHANNEL_GPFIFO_A:
case VOLTA_CHANNEL_GPFIFO_A: case VOLTA_CHANNEL_GPFIFO_A:
case TURING_CHANNEL_GPFIFO_A:
ret = nvc0_fence_create(drm); ret = nvc0_fence_create(drm);
break; break;
default: default:
...@@ -370,7 +371,7 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -370,7 +371,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
ret = nouveau_channel_new(drm, &drm->client.device, ret = nouveau_channel_new(drm, &drm->client.device,
nvif_fifo_runlist_ce(device), 0, nvif_fifo_runlist_ce(device), 0,
&drm->cechan); true, &drm->cechan);
if (ret) if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret); NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
...@@ -381,7 +382,8 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -381,7 +382,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
device->info.chipset != 0xaa && device->info.chipset != 0xaa &&
device->info.chipset != 0xac) { device->info.chipset != 0xac) {
ret = nouveau_channel_new(drm, &drm->client.device, ret = nouveau_channel_new(drm, &drm->client.device,
NvDmaFB, NvDmaTT, &drm->cechan); NvDmaFB, NvDmaTT, false,
&drm->cechan);
if (ret) if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret); NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
...@@ -393,7 +395,7 @@ nouveau_accel_init(struct nouveau_drm *drm) ...@@ -393,7 +395,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
} }
ret = nouveau_channel_new(drm, &drm->client.device, ret = nouveau_channel_new(drm, &drm->client.device,
arg0, arg1, &drm->channel); arg0, arg1, false, &drm->channel);
if (ret) { if (ret) {
NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
nouveau_accel_fini(drm); nouveau_accel_fini(drm);
......
...@@ -25,7 +25,6 @@ void nouveau_vma_unmap(struct nouveau_vma *); ...@@ -25,7 +25,6 @@ void nouveau_vma_unmap(struct nouveau_vma *);
struct nouveau_vmm { struct nouveau_vmm {
struct nouveau_cli *cli; struct nouveau_cli *cli;
struct nvif_vmm vmm; struct nvif_vmm vmm;
struct nvkm_vm *vm;
}; };
int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *); int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *);
......
...@@ -34,6 +34,7 @@ int ...@@ -34,6 +34,7 @@ int
nvif_disp_ctor(struct nvif_device *device, s32 oclass, struct nvif_disp *disp) nvif_disp_ctor(struct nvif_device *device, s32 oclass, struct nvif_disp *disp)
{ {
static const struct nvif_mclass disps[] = { static const struct nvif_mclass disps[] = {
{ TU104_DISP, -1 },
{ GV100_DISP, -1 }, { GV100_DISP, -1 },
{ GP102_DISP, -1 }, { GP102_DISP, -1 },
{ GP100_DISP, -1 }, { GP100_DISP, -1 },
......
...@@ -79,7 +79,9 @@ nvkm_subdev_name[NVKM_SUBDEV_NR] = { ...@@ -79,7 +79,9 @@ nvkm_subdev_name[NVKM_SUBDEV_NR] = {
[NVKM_ENGINE_NVENC0 ] = "nvenc0", [NVKM_ENGINE_NVENC0 ] = "nvenc0",
[NVKM_ENGINE_NVENC1 ] = "nvenc1", [NVKM_ENGINE_NVENC1 ] = "nvenc1",
[NVKM_ENGINE_NVENC2 ] = "nvenc2", [NVKM_ENGINE_NVENC2 ] = "nvenc2",
[NVKM_ENGINE_NVDEC ] = "nvdec", [NVKM_ENGINE_NVDEC0 ] = "nvdec0",
[NVKM_ENGINE_NVDEC1 ] = "nvdec1",
[NVKM_ENGINE_NVDEC2 ] = "nvdec2",
[NVKM_ENGINE_PM ] = "pm", [NVKM_ENGINE_PM ] = "pm",
[NVKM_ENGINE_SEC ] = "sec", [NVKM_ENGINE_SEC ] = "sec",
[NVKM_ENGINE_SEC2 ] = "sec2", [NVKM_ENGINE_SEC2 ] = "sec2",
......
...@@ -6,3 +6,4 @@ nvkm-y += nvkm/engine/ce/gm200.o ...@@ -6,3 +6,4 @@ nvkm-y += nvkm/engine/ce/gm200.o
nvkm-y += nvkm/engine/ce/gp100.o nvkm-y += nvkm/engine/ce/gp100.o
nvkm-y += nvkm/engine/ce/gp102.o nvkm-y += nvkm/engine/ce/gp102.o
nvkm-y += nvkm/engine/ce/gv100.o nvkm-y += nvkm/engine/ce/gv100.o
nvkm-y += nvkm/engine/ce/tu104.o
/*
* Copyright 2018 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.
*/
#include "priv.h"
#include <nvif/class.h>
static const struct nvkm_engine_func
tu104_ce = {
.intr = gp100_ce_intr,
.sclass = {
{ -1, -1, TURING_DMA_COPY_A },
{}
}
};
int
tu104_ce_new(struct nvkm_device *device, int index,
struct nvkm_engine **pengine)
{
return nvkm_engine_new_(&tu104_ce, device, index, true, pengine);
}
...@@ -2221,7 +2221,7 @@ nv132_chipset = { ...@@ -2221,7 +2221,7 @@ nv132_chipset = {
.dma = gf119_dma_new, .dma = gf119_dma_new,
.fifo = gp100_fifo_new, .fifo = gp100_fifo_new,
.gr = gp102_gr_new, .gr = gp102_gr_new,
.nvdec = gp102_nvdec_new, .nvdec[0] = gp102_nvdec_new,
.sec2 = gp102_sec2_new, .sec2 = gp102_sec2_new,
.sw = gf100_sw_new, .sw = gf100_sw_new,
}; };
...@@ -2257,7 +2257,7 @@ nv134_chipset = { ...@@ -2257,7 +2257,7 @@ nv134_chipset = {
.dma = gf119_dma_new, .dma = gf119_dma_new,
.fifo = gp100_fifo_new, .fifo = gp100_fifo_new,
.gr = gp104_gr_new, .gr = gp104_gr_new,
.nvdec = gp102_nvdec_new, .nvdec[0] = gp102_nvdec_new,
.sec2 = gp102_sec2_new, .sec2 = gp102_sec2_new,
.sw = gf100_sw_new, .sw = gf100_sw_new,
}; };
...@@ -2293,7 +2293,7 @@ nv136_chipset = { ...@@ -2293,7 +2293,7 @@ nv136_chipset = {
.dma = gf119_dma_new, .dma = gf119_dma_new,
.fifo = gp100_fifo_new, .fifo = gp100_fifo_new,
.gr = gp104_gr_new, .gr = gp104_gr_new,
.nvdec = gp102_nvdec_new, .nvdec[0] = gp102_nvdec_new,
.sec2 = gp102_sec2_new, .sec2 = gp102_sec2_new,
.sw = gf100_sw_new, .sw = gf100_sw_new,
}; };
...@@ -2329,7 +2329,7 @@ nv137_chipset = { ...@@ -2329,7 +2329,7 @@ nv137_chipset = {
.dma = gf119_dma_new, .dma = gf119_dma_new,
.fifo = gp100_fifo_new, .fifo = gp100_fifo_new,
.gr = gp107_gr_new, .gr = gp107_gr_new,
.nvdec = gp102_nvdec_new, .nvdec[0] = gp102_nvdec_new,
.sec2 = gp102_sec2_new, .sec2 = gp102_sec2_new,
.sw = gf100_sw_new, .sw = gf100_sw_new,
}; };
...@@ -2365,7 +2365,7 @@ nv138_chipset = { ...@@ -2365,7 +2365,7 @@ nv138_chipset = {
.dma = gf119_dma_new, .dma = gf119_dma_new,
.fifo = gp100_fifo_new, .fifo = gp100_fifo_new,
.gr = gp107_gr_new, .gr = gp107_gr_new,
.nvdec = gp102_nvdec_new, .nvdec[0] = gp102_nvdec_new,
.sec2 = gp102_sec2_new, .sec2 = gp102_sec2_new,
.sw = gf100_sw_new, .sw = gf100_sw_new,
}; };
...@@ -2430,10 +2430,74 @@ nv140_chipset = { ...@@ -2430,10 +2430,74 @@ nv140_chipset = {
.dma = gv100_dma_new, .dma = gv100_dma_new,
.fifo = gv100_fifo_new, .fifo = gv100_fifo_new,
.gr = gv100_gr_new, .gr = gv100_gr_new,
.nvdec = gp102_nvdec_new, .nvdec[0] = gp102_nvdec_new,
.sec2 = gp102_sec2_new, .sec2 = gp102_sec2_new,
}; };
static const struct nvkm_device_chip
nv164_chipset = {
.name = "TU104",
.bar = tu104_bar_new,
.bios = nvkm_bios_new,
.bus = gf100_bus_new,
.devinit = tu104_devinit_new,
.fault = tu104_fault_new,
.fb = gv100_fb_new,
.fuse = gm107_fuse_new,
.gpio = gk104_gpio_new,
.i2c = gm200_i2c_new,
.ibus = gm200_ibus_new,
.imem = nv50_instmem_new,
.ltc = gp102_ltc_new,
.mc = tu104_mc_new,
.mmu = tu104_mmu_new,
.pci = gp100_pci_new,
.pmu = gp102_pmu_new,
.therm = gp100_therm_new,
.timer = gk20a_timer_new,
.top = gk104_top_new,
.ce[0] = tu104_ce_new,
.ce[1] = tu104_ce_new,
.ce[2] = tu104_ce_new,
.ce[3] = tu104_ce_new,
.ce[4] = tu104_ce_new,
.disp = tu104_disp_new,
.dma = gv100_dma_new,
.fifo = tu104_fifo_new,
};
static const struct nvkm_device_chip
nv166_chipset = {
.name = "TU106",
.bar = tu104_bar_new,
.bios = nvkm_bios_new,
.bus = gf100_bus_new,
.devinit = tu104_devinit_new,
.fault = tu104_fault_new,
.fb = gv100_fb_new,
.fuse = gm107_fuse_new,
.gpio = gk104_gpio_new,
.i2c = gm200_i2c_new,
.ibus = gm200_ibus_new,
.imem = nv50_instmem_new,
.ltc = gp102_ltc_new,
.mc = tu104_mc_new,
.mmu = tu104_mmu_new,
.pci = gp100_pci_new,
.pmu = gp102_pmu_new,
.therm = gp100_therm_new,
.timer = gk20a_timer_new,
.top = gk104_top_new,
.ce[0] = tu104_ce_new,
.ce[1] = tu104_ce_new,
.ce[2] = tu104_ce_new,
.ce[3] = tu104_ce_new,
.ce[4] = tu104_ce_new,
.disp = tu104_disp_new,
.dma = gv100_dma_new,
.fifo = tu104_fifo_new,
};
static int static int
nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size, nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
struct nvkm_notify *notify) struct nvkm_notify *notify)
...@@ -2529,7 +2593,9 @@ nvkm_device_engine(struct nvkm_device *device, int index) ...@@ -2529,7 +2593,9 @@ nvkm_device_engine(struct nvkm_device *device, int index)
_(NVENC0 , device->nvenc[0], device->nvenc[0]); _(NVENC0 , device->nvenc[0], device->nvenc[0]);
_(NVENC1 , device->nvenc[1], device->nvenc[1]); _(NVENC1 , device->nvenc[1], device->nvenc[1]);
_(NVENC2 , device->nvenc[2], device->nvenc[2]); _(NVENC2 , device->nvenc[2], device->nvenc[2]);
_(NVDEC , device->nvdec , &device->nvdec->engine); _(NVDEC0 , device->nvdec[0], &device->nvdec[0]->engine);
_(NVDEC1 , device->nvdec[1], &device->nvdec[1]->engine);
_(NVDEC2 , device->nvdec[2], &device->nvdec[2]->engine);
_(PM , device->pm , &device->pm->engine); _(PM , device->pm , &device->pm->engine);
_(SEC , device->sec , device->sec); _(SEC , device->sec , device->sec);
_(SEC2 , device->sec2 , &device->sec2->engine); _(SEC2 , device->sec2 , &device->sec2->engine);
...@@ -2791,6 +2857,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, ...@@ -2791,6 +2857,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x120: device->card_type = GM100; break; case 0x120: device->card_type = GM100; break;
case 0x130: device->card_type = GP100; break; case 0x130: device->card_type = GP100; break;
case 0x140: device->card_type = GV100; break; case 0x140: device->card_type = GV100; break;
case 0x160: device->card_type = TU100; break;
default: default:
break; break;
} }
...@@ -2883,6 +2950,8 @@ nvkm_device_ctor(const struct nvkm_device_func *func, ...@@ -2883,6 +2950,8 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x138: device->chip = &nv138_chipset; break; case 0x138: device->chip = &nv138_chipset; break;
case 0x13b: device->chip = &nv13b_chipset; break; case 0x13b: device->chip = &nv13b_chipset; break;
case 0x140: device->chip = &nv140_chipset; break; case 0x140: device->chip = &nv140_chipset; break;
case 0x164: device->chip = &nv164_chipset; break;
case 0x166: device->chip = &nv166_chipset; break;
default: default:
nvdev_error(device, "unknown chipset (%08x)\n", boot0); nvdev_error(device, "unknown chipset (%08x)\n", boot0);
goto done; goto done;
...@@ -2988,7 +3057,9 @@ nvkm_device_ctor(const struct nvkm_device_func *func, ...@@ -2988,7 +3057,9 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
_(NVKM_ENGINE_NVENC0 , nvenc[0]); _(NVKM_ENGINE_NVENC0 , nvenc[0]);
_(NVKM_ENGINE_NVENC1 , nvenc[1]); _(NVKM_ENGINE_NVENC1 , nvenc[1]);
_(NVKM_ENGINE_NVENC2 , nvenc[2]); _(NVKM_ENGINE_NVENC2 , nvenc[2]);
_(NVKM_ENGINE_NVDEC , nvdec); _(NVKM_ENGINE_NVDEC0 , nvdec[0]);
_(NVKM_ENGINE_NVDEC1 , nvdec[1]);
_(NVKM_ENGINE_NVDEC2 , nvdec[2]);
_(NVKM_ENGINE_PM , pm); _(NVKM_ENGINE_PM , pm);
_(NVKM_ENGINE_SEC , sec); _(NVKM_ENGINE_SEC , sec);
_(NVKM_ENGINE_SEC2 , sec2); _(NVKM_ENGINE_SEC2 , sec2);
......
...@@ -91,7 +91,7 @@ nvkm_udevice_info_v1(struct nvkm_device *device, ...@@ -91,7 +91,7 @@ nvkm_udevice_info_v1(struct nvkm_device *device,
case ENGINE_A(MSENC ); break; case ENGINE_A(MSENC ); break;
case ENGINE_A(VIC ); break; case ENGINE_A(VIC ); break;
case ENGINE_A(SEC2 ); break; case ENGINE_A(SEC2 ); break;
case ENGINE_A(NVDEC ); break; case ENGINE_B(NVDEC ); break;
case ENGINE_B(NVENC ); break; case ENGINE_B(NVENC ); break;
default: default:
args->mthd = NV_DEVICE_INFO_INVALID; args->mthd = NV_DEVICE_INFO_INVALID;
...@@ -175,6 +175,7 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size) ...@@ -175,6 +175,7 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break; case GM100: args->v0.family = NV_DEVICE_INFO_V0_MAXWELL; break;
case GP100: args->v0.family = NV_DEVICE_INFO_V0_PASCAL; break; case GP100: args->v0.family = NV_DEVICE_INFO_V0_PASCAL; break;
case GV100: args->v0.family = NV_DEVICE_INFO_V0_VOLTA; break; case GV100: args->v0.family = NV_DEVICE_INFO_V0_VOLTA; break;
case TU100: args->v0.family = NV_DEVICE_INFO_V0_TURING; break;
default: default:
args->v0.family = 0; args->v0.family = 0;
break; break;
......
...@@ -15,6 +15,7 @@ nvkm-y += nvkm/engine/disp/gm200.o ...@@ -15,6 +15,7 @@ nvkm-y += nvkm/engine/disp/gm200.o
nvkm-y += nvkm/engine/disp/gp100.o nvkm-y += nvkm/engine/disp/gp100.o
nvkm-y += nvkm/engine/disp/gp102.o nvkm-y += nvkm/engine/disp/gp102.o
nvkm-y += nvkm/engine/disp/gv100.o nvkm-y += nvkm/engine/disp/gv100.o
nvkm-y += nvkm/engine/disp/tu104.o
nvkm-y += nvkm/engine/disp/vga.o nvkm-y += nvkm/engine/disp/vga.o
nvkm-y += nvkm/engine/disp/head.o nvkm-y += nvkm/engine/disp/head.o
...@@ -38,6 +39,7 @@ nvkm-y += nvkm/engine/disp/sorgk104.o ...@@ -38,6 +39,7 @@ nvkm-y += nvkm/engine/disp/sorgk104.o
nvkm-y += nvkm/engine/disp/sorgm107.o nvkm-y += nvkm/engine/disp/sorgm107.o
nvkm-y += nvkm/engine/disp/sorgm200.o nvkm-y += nvkm/engine/disp/sorgm200.o
nvkm-y += nvkm/engine/disp/sorgv100.o nvkm-y += nvkm/engine/disp/sorgv100.o
nvkm-y += nvkm/engine/disp/sortu104.o
nvkm-y += nvkm/engine/disp/outp.o nvkm-y += nvkm/engine/disp/outp.o
nvkm-y += nvkm/engine/disp/dp.o nvkm-y += nvkm/engine/disp/dp.o
...@@ -69,6 +71,7 @@ nvkm-y += nvkm/engine/disp/rootgm200.o ...@@ -69,6 +71,7 @@ nvkm-y += nvkm/engine/disp/rootgm200.o
nvkm-y += nvkm/engine/disp/rootgp100.o nvkm-y += nvkm/engine/disp/rootgp100.o
nvkm-y += nvkm/engine/disp/rootgp102.o nvkm-y += nvkm/engine/disp/rootgp102.o
nvkm-y += nvkm/engine/disp/rootgv100.o nvkm-y += nvkm/engine/disp/rootgv100.o
nvkm-y += nvkm/engine/disp/roottu104.o
nvkm-y += nvkm/engine/disp/channv50.o nvkm-y += nvkm/engine/disp/channv50.o
nvkm-y += nvkm/engine/disp/changf119.o nvkm-y += nvkm/engine/disp/changf119.o
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <subdev/timer.h> #include <subdev/timer.h>
static int int
gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask) gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask)
{ {
struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_device *device = disp->engine.subdev.device;
...@@ -36,7 +36,7 @@ gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask) ...@@ -36,7 +36,7 @@ gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask)
return (nvkm_rd32(device, 0x610074) & 0x03f00000) >> 20; return (nvkm_rd32(device, 0x610074) & 0x03f00000) >> 20;
} }
static void void
gv100_disp_super(struct work_struct *work) gv100_disp_super(struct work_struct *work)
{ {
struct nv50_disp *disp = struct nv50_disp *disp =
...@@ -257,7 +257,7 @@ gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) ...@@ -257,7 +257,7 @@ gv100_disp_intr_head_timing(struct nv50_disp *disp, int head)
} }
} }
static void void
gv100_disp_intr(struct nv50_disp *disp) gv100_disp_intr(struct nv50_disp *disp)
{ {
struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_subdev *subdev = &disp->base.engine.subdev;
...@@ -297,7 +297,7 @@ gv100_disp_intr(struct nv50_disp *disp) ...@@ -297,7 +297,7 @@ gv100_disp_intr(struct nv50_disp *disp)
nvkm_warn(subdev, "intr %08x\n", stat); nvkm_warn(subdev, "intr %08x\n", stat);
} }
static void void
gv100_disp_fini(struct nv50_disp *disp) gv100_disp_fini(struct nv50_disp *disp)
{ {
struct nvkm_device *device = disp->base.engine.subdev.device; struct nvkm_device *device = disp->base.engine.subdev.device;
......
...@@ -144,6 +144,11 @@ void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *); ...@@ -144,6 +144,11 @@ void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *);
int gm200_sor_route_get(struct nvkm_outp *, int *); int gm200_sor_route_get(struct nvkm_outp *, int *);
void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int); void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
void gv100_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
void gv100_sor_dp_audio(struct nvkm_ior *, int, bool);
void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32);
void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8);
void g84_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void g84_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
void gt215_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gt215_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
...@@ -195,4 +200,6 @@ int gm200_sor_new(struct nvkm_disp *, int); ...@@ -195,4 +200,6 @@ int gm200_sor_new(struct nvkm_disp *, int);
int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); int gv100_sor_cnt(struct nvkm_disp *, unsigned long *);
int gv100_sor_new(struct nvkm_disp *, int); int gv100_sor_new(struct nvkm_disp *, int);
int tu104_sor_new(struct nvkm_disp *, int);
#endif #endif
...@@ -78,6 +78,11 @@ void gf119_disp_intr(struct nv50_disp *); ...@@ -78,6 +78,11 @@ void gf119_disp_intr(struct nv50_disp *);
void gf119_disp_super(struct work_struct *); void gf119_disp_super(struct work_struct *);
void gf119_disp_intr_error(struct nv50_disp *, int); void gf119_disp_intr_error(struct nv50_disp *, int);
void gv100_disp_fini(struct nv50_disp *);
void gv100_disp_intr(struct nv50_disp *);
void gv100_disp_super(struct work_struct *);
int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *);
void nv50_disp_dptmds_war_2(struct nv50_disp *, struct dcb_output *); void nv50_disp_dptmds_war_2(struct nv50_disp *, struct dcb_output *);
void nv50_disp_dptmds_war_3(struct nv50_disp *, struct dcb_output *); void nv50_disp_dptmds_war_3(struct nv50_disp *, struct dcb_output *);
void nv50_disp_update_sppll1(struct nv50_disp *); void nv50_disp_update_sppll1(struct nv50_disp *);
......
...@@ -37,4 +37,5 @@ extern const struct nvkm_disp_oclass gm200_disp_root_oclass; ...@@ -37,4 +37,5 @@ extern const struct nvkm_disp_oclass gm200_disp_root_oclass;
extern const struct nvkm_disp_oclass gp100_disp_root_oclass; extern const struct nvkm_disp_oclass gp100_disp_root_oclass;
extern const struct nvkm_disp_oclass gp102_disp_root_oclass; extern const struct nvkm_disp_oclass gp102_disp_root_oclass;
extern const struct nvkm_disp_oclass gv100_disp_root_oclass; extern const struct nvkm_disp_oclass gv100_disp_root_oclass;
extern const struct nvkm_disp_oclass tu104_disp_root_oclass;
#endif #endif
/*
* Copyright 2018 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.
*/
#include "rootnv50.h"
#include "channv50.h"
#include <nvif/class.h>
static const struct nv50_disp_root_func
tu104_disp_root = {
.user = {
{{0,0,TU104_DISP_CURSOR }, gv100_disp_curs_new },
{{0,0,TU104_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new },
{{0,0,TU104_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new },
{{0,0,TU104_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new },
{}
},
};
static int
tu104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
void *data, u32 size, struct nvkm_object **pobject)
{
return nv50_disp_root_new_(&tu104_disp_root, disp, oclass,
data, size, pobject);
}
const struct nvkm_disp_oclass
tu104_disp_root_oclass = {
.base.oclass = TU104_DISP,
.base.minver = -1,
.base.maxver = -1,
.ctor = tu104_disp_root_new,
};
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <subdev/timer.h> #include <subdev/timer.h>
static void void
gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark)
{ {
struct nvkm_device *device = sor->disp->engine.subdev.device; struct nvkm_device *device = sor->disp->engine.subdev.device;
...@@ -31,7 +31,7 @@ gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) ...@@ -31,7 +31,7 @@ gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark)
nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark); nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark);
} }
static void void
gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v)
{ {
struct nvkm_device *device = sor->disp->engine.subdev.device; struct nvkm_device *device = sor->disp->engine.subdev.device;
...@@ -40,7 +40,7 @@ gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) ...@@ -40,7 +40,7 @@ gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v)
nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v); nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v);
} }
static void void
gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable)
{ {
struct nvkm_device *device = sor->disp->engine.subdev.device; struct nvkm_device *device = sor->disp->engine.subdev.device;
...@@ -54,7 +54,7 @@ gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) ...@@ -54,7 +54,7 @@ gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable)
); );
} }
static void void
gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
{ {
struct nvkm_device *device = sor->disp->engine.subdev.device; struct nvkm_device *device = sor->disp->engine.subdev.device;
......
/*
* Copyright 2018 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.
*/
#include "ior.h"
#include <subdev/timer.h>
static void
tu104_sor_dp_vcpi(struct nvkm_ior *sor, int head,
u8 slot, u8 slot_nr, u16 pbn, u16 aligned)
{
struct nvkm_device *device = sor->disp->engine.subdev.device;
const u32 hoff = head * 0x800;
nvkm_mask(device, 0x61657c + hoff, 0xffffffff, (aligned << 16) | pbn);
nvkm_mask(device, 0x616578 + hoff, 0x00003f3f, (slot_nr << 8) | slot);
}
static int
tu104_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux)
{
struct nvkm_device *device = sor->disp->engine.subdev.device;
const u32 soff = nv50_ior_base(sor);
const u32 loff = nv50_sor_link(sor);
u32 dpctrl = 0x00000000;
u32 clksor = 0x00000000;
clksor |= sor->dp.bw << 18;
dpctrl |= ((1 << sor->dp.nr) - 1) << 16;
if (sor->dp.mst)
dpctrl |= 0x40000000;
if (sor->dp.ef)
dpctrl |= 0x00004000;
nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
/*XXX*/
nvkm_msec(device, 40, NVKM_DELAY);
nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000);
nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001);
nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
return 0;
}
static const struct nvkm_ior_func
tu104_sor = {
.route = {
.get = gm200_sor_route_get,
.set = gm200_sor_route_set,
},
.state = gv100_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
.hdmi = {
.ctrl = gv100_hdmi_ctrl,
},
.dp = {
.lanes = { 0, 1, 2, 3 },
.links = tu104_sor_dp_links,
.power = g94_sor_dp_power,
.pattern = gm107_sor_dp_pattern,
.drive = gm200_sor_dp_drive,
.vcpi = tu104_sor_dp_vcpi,
.audio = gv100_sor_dp_audio,
.audio_sym = gv100_sor_dp_audio_sym,
.watermark = gv100_sor_dp_watermark,
},
.hda = {
.hpd = gf119_hda_hpd,
.eld = gf119_hda_eld,
},
};
int
tu104_sor_new(struct nvkm_disp *disp, int id)
{
return nvkm_ior_new_(&tu104_sor, disp, SOR, id);
}
/*
* Copyright 2018 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.
*/
#include "nv50.h"
#include "head.h"
#include "ior.h"
#include "channv50.h"
#include "rootnv50.h"
#include <core/gpuobj.h>
#include <subdev/timer.h>
static int
tu104_disp_init(struct nv50_disp *disp)
{
struct nvkm_device *device = disp->base.engine.subdev.device;
struct nvkm_head *head;
int i, j;
u32 tmp;
/* Claim ownership of display. */
if (nvkm_rd32(device, 0x6254e8) & 0x00000002) {
nvkm_mask(device, 0x6254e8, 0x00000001, 0x00000000);
if (nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x6254e8) & 0x00000002))
break;
) < 0)
return -EBUSY;
}
/* Lock pin capabilities. */
tmp = 0x00000021; /*XXX*/
nvkm_wr32(device, 0x640008, tmp);
/* SOR capabilities. */
for (i = 0; i < disp->sor.nr; i++) {
tmp = nvkm_rd32(device, 0x61c000 + (i * 0x800));
nvkm_mask(device, 0x640000, 0x00000100 << i, 0x00000100 << i);
nvkm_wr32(device, 0x640144 + (i * 0x08), tmp);
}
/* Head capabilities. */
list_for_each_entry(head, &disp->base.head, head) {
const int id = head->id;
/* RG. */
tmp = nvkm_rd32(device, 0x616300 + (id * 0x800));
nvkm_wr32(device, 0x640048 + (id * 0x020), tmp);
/* POSTCOMP. */
for (j = 0; j < 5 * 4; j += 4) {
tmp = nvkm_rd32(device, 0x616140 + (id * 0x800) + j);
nvkm_wr32(device, 0x640680 + (id * 0x20) + j, tmp);
}
}
/* Window capabilities. */
for (i = 0; i < disp->wndw.nr; i++) {
nvkm_mask(device, 0x640004, 1 << i, 1 << i);
for (j = 0; j < 6 * 4; j += 4) {
tmp = nvkm_rd32(device, 0x630100 + (i * 0x800) + j);
nvkm_mask(device, 0x640780 + (i * 0x20) + j, 0xffffffff, tmp);
}
nvkm_mask(device, 0x64000c, 0x00000100, 0x00000100);
}
/* IHUB capabilities. */
for (i = 0; i < 3; i++) {
tmp = nvkm_rd32(device, 0x62e000 + (i * 0x04));
nvkm_wr32(device, 0x640010 + (i * 0x04), tmp);
}
nvkm_mask(device, 0x610078, 0x00000001, 0x00000001);
/* Setup instance memory. */
switch (nvkm_memory_target(disp->inst->memory)) {
case NVKM_MEM_TARGET_VRAM: tmp = 0x00000001; break;
case NVKM_MEM_TARGET_NCOH: tmp = 0x00000002; break;
case NVKM_MEM_TARGET_HOST: tmp = 0x00000003; break;
default:
break;
}
nvkm_wr32(device, 0x610010, 0x00000008 | tmp);
nvkm_wr32(device, 0x610014, disp->inst->addr >> 16);
/* CTRL_DISP: AWAKEN, ERROR, SUPERVISOR[1-3]. */
nvkm_wr32(device, 0x611cf0, 0x00000187); /* MSK. */
nvkm_wr32(device, 0x611db0, 0x00000187); /* EN. */
/* EXC_OTHER: CURSn, CORE. */
nvkm_wr32(device, 0x611cec, disp->head.mask << 16 |
0x00000001); /* MSK. */
nvkm_wr32(device, 0x611dac, 0x00000000); /* EN. */
/* EXC_WINIM. */
nvkm_wr32(device, 0x611ce8, disp->wndw.mask); /* MSK. */
nvkm_wr32(device, 0x611da8, 0x00000000); /* EN. */
/* EXC_WIN. */
nvkm_wr32(device, 0x611ce4, disp->wndw.mask); /* MSK. */
nvkm_wr32(device, 0x611da4, 0x00000000); /* EN. */
/* HEAD_TIMING(n): VBLANK. */
list_for_each_entry(head, &disp->base.head, head) {
const u32 hoff = head->id * 4;
nvkm_wr32(device, 0x611cc0 + hoff, 0x00000004); /* MSK. */
nvkm_wr32(device, 0x611d80 + hoff, 0x00000000); /* EN. */
}
/* OR. */
nvkm_wr32(device, 0x611cf4, 0x00000000); /* MSK. */
nvkm_wr32(device, 0x611db4, 0x00000000); /* EN. */
return 0;
}
static const struct nv50_disp_func
tu104_disp = {
.init = tu104_disp_init,
.fini = gv100_disp_fini,
.intr = gv100_disp_intr,
.uevent = &gv100_disp_chan_uevent,
.super = gv100_disp_super,
.root = &tu104_disp_root_oclass,
.wndw = { .cnt = gv100_disp_wndw_cnt },
.head = { .cnt = gv100_head_cnt, .new = gv100_head_new },
.sor = { .cnt = gv100_sor_cnt, .new = tu104_sor_new },
.ramht_size = 0x2000,
};
int
tu104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
{
return nv50_disp_new_(&tu104_disp, device, index, pdisp);
}
...@@ -118,7 +118,7 @@ gv100_disp_wndw_mthd_base = { ...@@ -118,7 +118,7 @@ gv100_disp_wndw_mthd_base = {
const struct nv50_disp_chan_mthd const struct nv50_disp_chan_mthd
gv100_disp_wndw_mthd = { gv100_disp_wndw_mthd = {
.name = "Base", .name = "Window",
.addr = 0x001000, .addr = 0x001000,
.prev = 0x000800, .prev = 0x000800,
.data = { .data = {
......
...@@ -16,6 +16,7 @@ nvkm-y += nvkm/engine/fifo/gm20b.o ...@@ -16,6 +16,7 @@ nvkm-y += nvkm/engine/fifo/gm20b.o
nvkm-y += nvkm/engine/fifo/gp100.o nvkm-y += nvkm/engine/fifo/gp100.o
nvkm-y += nvkm/engine/fifo/gp10b.o nvkm-y += nvkm/engine/fifo/gp10b.o
nvkm-y += nvkm/engine/fifo/gv100.o nvkm-y += nvkm/engine/fifo/gv100.o
nvkm-y += nvkm/engine/fifo/tu104.o
nvkm-y += nvkm/engine/fifo/chan.o nvkm-y += nvkm/engine/fifo/chan.o
nvkm-y += nvkm/engine/fifo/channv50.o nvkm-y += nvkm/engine/fifo/channv50.o
...@@ -33,5 +34,7 @@ nvkm-y += nvkm/engine/fifo/gpfifog84.o ...@@ -33,5 +34,7 @@ nvkm-y += nvkm/engine/fifo/gpfifog84.o
nvkm-y += nvkm/engine/fifo/gpfifogf100.o nvkm-y += nvkm/engine/fifo/gpfifogf100.o
nvkm-y += nvkm/engine/fifo/gpfifogk104.o nvkm-y += nvkm/engine/fifo/gpfifogk104.o
nvkm-y += nvkm/engine/fifo/gpfifogv100.o nvkm-y += nvkm/engine/fifo/gpfifogv100.o
nvkm-y += nvkm/engine/fifo/gpfifotu104.o
nvkm-y += nvkm/engine/fifo/usergv100.o nvkm-y += nvkm/engine/fifo/usergv100.o
nvkm-y += nvkm/engine/fifo/usertu104.o
...@@ -17,6 +17,7 @@ struct nvkm_fifo_chan_func { ...@@ -17,6 +17,7 @@ struct nvkm_fifo_chan_func {
bool suspend); bool suspend);
int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *); int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *);
void (*object_dtor)(struct nvkm_fifo_chan *, int); void (*object_dtor)(struct nvkm_fifo_chan *, int);
u32 (*submit_token)(struct nvkm_fifo_chan *);
}; };
int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *, int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *,
......
...@@ -14,6 +14,8 @@ struct gk104_fifo_chan { ...@@ -14,6 +14,8 @@ struct gk104_fifo_chan {
struct list_head head; struct list_head head;
bool killed; bool killed;
struct nvkm_memory *mthd;
struct { struct {
struct nvkm_gpuobj *inst; struct nvkm_gpuobj *inst;
struct nvkm_vma *vma; struct nvkm_vma *vma;
...@@ -36,4 +38,15 @@ int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *); ...@@ -36,4 +38,15 @@ int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *);
int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *, int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
void *data, u32 size, struct nvkm_object **); void *data, u32 size, struct nvkm_object **);
int gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *,
struct gk104_fifo *, u64 *, u16 *, u64, u64, u64,
u64 *, bool, u32 *, const struct nvkm_oclass *,
struct nvkm_object **);
int gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *,
struct nvkm_engine *);
int gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *,
struct nvkm_engine *, bool);
int tu104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
void *data, u32 size, struct nvkm_object **);
#endif #endif
...@@ -346,10 +346,10 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit) ...@@ -346,10 +346,10 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
if (eu && eu->data2) { if (eu && eu->data2) {
switch (eu->data2) { switch (eu->data2) {
case NVKM_SUBDEV_BAR: case NVKM_SUBDEV_BAR:
nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); nvkm_bar_bar1_reset(device);
break; break;
case NVKM_SUBDEV_INSTMEM: case NVKM_SUBDEV_INSTMEM:
nvkm_mask(device, 0x001714, 0x00000000, 0x00000000); nvkm_bar_bar2_reset(device);
break; break;
case NVKM_ENGINE_IFB: case NVKM_ENGINE_IFB:
nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
......
...@@ -149,16 +149,41 @@ gk104_fifo_uevent_init(struct nvkm_fifo *fifo) ...@@ -149,16 +149,41 @@ gk104_fifo_uevent_init(struct nvkm_fifo *fifo)
} }
void void
gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
struct nvkm_memory *mem, int nr)
{
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
int target;
switch (nvkm_memory_target(mem)) {
case NVKM_MEM_TARGET_VRAM: target = 0; break;
case NVKM_MEM_TARGET_NCOH: target = 3; break;
default:
WARN_ON(1);
return;
}
nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) |
(target << 28));
nvkm_wr32(device, 0x002274, (runl << 20) | nr);
if (nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000))
break;
) < 0)
nvkm_error(subdev, "runlist %d update timeout\n", runl);
}
void
gk104_fifo_runlist_update(struct gk104_fifo *fifo, int runl)
{ {
const struct gk104_fifo_runlist_func *func = fifo->func->runlist; const struct gk104_fifo_runlist_func *func = fifo->func->runlist;
struct gk104_fifo_chan *chan; struct gk104_fifo_chan *chan;
struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_memory *mem; struct nvkm_memory *mem;
struct nvkm_fifo_cgrp *cgrp; struct nvkm_fifo_cgrp *cgrp;
int nr = 0; int nr = 0;
int target;
mutex_lock(&subdev->mutex); mutex_lock(&subdev->mutex);
mem = fifo->runlist[runl].mem[fifo->runlist[runl].next]; mem = fifo->runlist[runl].mem[fifo->runlist[runl].next];
...@@ -177,24 +202,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl) ...@@ -177,24 +202,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl)
} }
nvkm_done(mem); nvkm_done(mem);
switch (nvkm_memory_target(mem)) { func->commit(fifo, runl, mem, nr);
case NVKM_MEM_TARGET_VRAM: target = 0; break;
case NVKM_MEM_TARGET_NCOH: target = 3; break;
default:
WARN_ON(1);
goto unlock;
}
nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) |
(target << 28));
nvkm_wr32(device, 0x002274, (runl << 20) | nr);
if (nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000))
break;
) < 0)
nvkm_error(subdev, "runlist %d update timeout\n", runl);
unlock:
mutex_unlock(&subdev->mutex); mutex_unlock(&subdev->mutex);
} }
...@@ -238,6 +246,29 @@ const struct gk104_fifo_runlist_func ...@@ -238,6 +246,29 @@ const struct gk104_fifo_runlist_func
gk104_fifo_runlist = { gk104_fifo_runlist = {
.size = 8, .size = 8,
.chan = gk104_fifo_runlist_chan, .chan = gk104_fifo_runlist_chan,
.commit = gk104_fifo_runlist_commit,
};
void
gk104_fifo_pbdma_init(struct gk104_fifo *fifo)
{
struct nvkm_device *device = fifo->base.engine.subdev.device;
nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1);
}
int
gk104_fifo_pbdma_nr(struct gk104_fifo *fifo)
{
struct nvkm_device *device = fifo->base.engine.subdev.device;
/* Determine number of PBDMAs by checking valid enable bits. */
nvkm_wr32(device, 0x000204, 0xffffffff);
return hweight32(nvkm_rd32(device, 0x000204));
}
const struct gk104_fifo_pbdma_func
gk104_fifo_pbdma = {
.nr = gk104_fifo_pbdma_nr,
.init = gk104_fifo_pbdma_init,
}; };
static void static void
...@@ -267,7 +298,7 @@ gk104_fifo_recover_work(struct work_struct *w) ...@@ -267,7 +298,7 @@ gk104_fifo_recover_work(struct work_struct *w)
} }
for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl)) for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl))
gk104_fifo_runlist_commit(fifo, runl); gk104_fifo_runlist_update(fifo, runl);
nvkm_wr32(device, 0x00262c, runm); nvkm_wr32(device, 0x00262c, runm);
nvkm_mask(device, 0x002630, runm, 0x00000000); nvkm_mask(device, 0x002630, runm, 0x00000000);
...@@ -456,10 +487,10 @@ gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) ...@@ -456,10 +487,10 @@ gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
if (ee && ee->data2) { if (ee && ee->data2) {
switch (ee->data2) { switch (ee->data2) {
case NVKM_SUBDEV_BAR: case NVKM_SUBDEV_BAR:
nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); nvkm_bar_bar1_reset(device);
break; break;
case NVKM_SUBDEV_INSTMEM: case NVKM_SUBDEV_INSTMEM:
nvkm_mask(device, 0x001714, 0x00000000, 0x00000000); nvkm_bar_bar2_reset(device);
break; break;
case NVKM_ENGINE_IFB: case NVKM_ENGINE_IFB:
nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
...@@ -904,9 +935,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) ...@@ -904,9 +935,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
enum nvkm_devidx engidx; enum nvkm_devidx engidx;
u32 *map; u32 *map;
/* Determine number of PBDMAs by checking valid enable bits. */ fifo->pbdma_nr = fifo->func->pbdma->nr(fifo);
nvkm_wr32(device, 0x000204, 0xffffffff);
fifo->pbdma_nr = hweight32(nvkm_rd32(device, 0x000204));
nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr); nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr);
/* Read PBDMA->runlist(s) mapping from HW. */ /* Read PBDMA->runlist(s) mapping from HW. */
...@@ -978,7 +1007,7 @@ gk104_fifo_init(struct nvkm_fifo *base) ...@@ -978,7 +1007,7 @@ gk104_fifo_init(struct nvkm_fifo *base)
int i; int i;
/* Enable PBDMAs. */ /* Enable PBDMAs. */
nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1); fifo->func->pbdma->init(fifo);
/* PBDMA[n] */ /* PBDMA[n] */
for (i = 0; i < fifo->pbdma_nr; i++) { for (i = 0; i < fifo->pbdma_nr; i++) {
...@@ -995,8 +1024,8 @@ gk104_fifo_init(struct nvkm_fifo *base) ...@@ -995,8 +1024,8 @@ gk104_fifo_init(struct nvkm_fifo *base)
nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12);
if (fifo->func->init_pbdma_timeout) if (fifo->func->pbdma->init_timeout)
fifo->func->init_pbdma_timeout(fifo); fifo->func->pbdma->init_timeout(fifo);
nvkm_wr32(device, 0x002100, 0xffffffff); nvkm_wr32(device, 0x002100, 0xffffffff);
nvkm_wr32(device, 0x002140, 0x7fffffff); nvkm_wr32(device, 0x002140, 0x7fffffff);
...@@ -1175,6 +1204,7 @@ gk104_fifo_fault_gpcclient[] = { ...@@ -1175,6 +1204,7 @@ gk104_fifo_fault_gpcclient[] = {
static const struct gk104_fifo_func static const struct gk104_fifo_func
gk104_fifo = { gk104_fifo = {
.pbdma = &gk104_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine, .fault.engine = gk104_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -45,7 +45,11 @@ struct gk104_fifo { ...@@ -45,7 +45,11 @@ struct gk104_fifo {
}; };
struct gk104_fifo_func { struct gk104_fifo_func {
void (*init_pbdma_timeout)(struct gk104_fifo *); const struct gk104_fifo_pbdma_func {
int (*nr)(struct gk104_fifo *);
void (*init)(struct gk104_fifo *);
void (*init_timeout)(struct gk104_fifo *);
} *pbdma;
struct { struct {
const struct nvkm_enum *access; const struct nvkm_enum *access;
...@@ -61,6 +65,8 @@ struct gk104_fifo_func { ...@@ -61,6 +65,8 @@ struct gk104_fifo_func {
struct nvkm_memory *, u32 offset); struct nvkm_memory *, u32 offset);
void (*chan)(struct gk104_fifo_chan *, void (*chan)(struct gk104_fifo_chan *,
struct nvkm_memory *, u32 offset); struct nvkm_memory *, u32 offset);
void (*commit)(struct gk104_fifo *, int runl,
struct nvkm_memory *, int entries);
} *runlist; } *runlist;
struct gk104_fifo_user_user { struct gk104_fifo_user_user {
...@@ -81,8 +87,11 @@ int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, ...@@ -81,8 +87,11 @@ int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *,
int index, int nr, struct nvkm_fifo **); int index, int nr, struct nvkm_fifo **);
void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *);
void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *); void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl); void gk104_fifo_runlist_update(struct gk104_fifo *, int runl);
extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma;
int gk104_fifo_pbdma_nr(struct gk104_fifo *);
void gk104_fifo_pbdma_init(struct gk104_fifo *);
extern const struct nvkm_enum gk104_fifo_fault_access[]; extern const struct nvkm_enum gk104_fifo_fault_access[];
extern const struct nvkm_enum gk104_fifo_fault_engine[]; extern const struct nvkm_enum gk104_fifo_fault_engine[];
extern const struct nvkm_enum gk104_fifo_fault_reason[]; extern const struct nvkm_enum gk104_fifo_fault_reason[];
...@@ -91,15 +100,30 @@ extern const struct nvkm_enum gk104_fifo_fault_gpcclient[]; ...@@ -91,15 +100,30 @@ extern const struct nvkm_enum gk104_fifo_fault_gpcclient[];
extern const struct gk104_fifo_runlist_func gk104_fifo_runlist; extern const struct gk104_fifo_runlist_func gk104_fifo_runlist;
void gk104_fifo_runlist_chan(struct gk104_fifo_chan *, void gk104_fifo_runlist_chan(struct gk104_fifo_chan *,
struct nvkm_memory *, u32); struct nvkm_memory *, u32);
void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl,
struct nvkm_memory *, int);
extern const struct gk104_fifo_runlist_func gk110_fifo_runlist; extern const struct gk104_fifo_runlist_func gk110_fifo_runlist;
void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *, void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *,
struct nvkm_memory *, u32); struct nvkm_memory *, u32);
void gk208_fifo_init_pbdma_timeout(struct gk104_fifo *); extern const struct gk104_fifo_pbdma_func gk208_fifo_pbdma;
void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *);
extern const struct nvkm_enum gm107_fifo_fault_engine[]; extern const struct nvkm_enum gm107_fifo_fault_engine[];
extern const struct gk104_fifo_runlist_func gm107_fifo_runlist; extern const struct gk104_fifo_runlist_func gm107_fifo_runlist;
extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma;
int gm200_fifo_pbdma_nr(struct gk104_fifo *);
extern const struct nvkm_enum gp100_fifo_fault_engine[]; extern const struct nvkm_enum gp100_fifo_fault_engine[];
extern const struct nvkm_enum gv100_fifo_fault_access[];
extern const struct nvkm_enum gv100_fifo_fault_reason[];
extern const struct nvkm_enum gv100_fifo_fault_hubclient[];
extern const struct nvkm_enum gv100_fifo_fault_gpcclient[];
void gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *,
struct nvkm_memory *, u32);
void gv100_fifo_runlist_chan(struct gk104_fifo_chan *,
struct nvkm_memory *, u32);
#endif #endif
...@@ -43,10 +43,12 @@ gk110_fifo_runlist = { ...@@ -43,10 +43,12 @@ gk110_fifo_runlist = {
.size = 8, .size = 8,
.cgrp = gk110_fifo_runlist_cgrp, .cgrp = gk110_fifo_runlist_cgrp,
.chan = gk104_fifo_runlist_chan, .chan = gk104_fifo_runlist_chan,
.commit = gk104_fifo_runlist_commit,
}; };
static const struct gk104_fifo_func static const struct gk104_fifo_func
gk110_fifo = { gk110_fifo = {
.pbdma = &gk104_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine, .fault.engine = gk104_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <nvif/class.h> #include <nvif/class.h>
void void
gk208_fifo_init_pbdma_timeout(struct gk104_fifo *fifo) gk208_fifo_pbdma_init_timeout(struct gk104_fifo *fifo)
{ {
struct nvkm_device *device = fifo->base.engine.subdev.device; struct nvkm_device *device = fifo->base.engine.subdev.device;
int i; int i;
...@@ -36,9 +36,16 @@ gk208_fifo_init_pbdma_timeout(struct gk104_fifo *fifo) ...@@ -36,9 +36,16 @@ gk208_fifo_init_pbdma_timeout(struct gk104_fifo *fifo)
nvkm_wr32(device, 0x04012c + (i * 0x2000), 0x0000ffff); nvkm_wr32(device, 0x04012c + (i * 0x2000), 0x0000ffff);
} }
const struct gk104_fifo_pbdma_func
gk208_fifo_pbdma = {
.nr = gk104_fifo_pbdma_nr,
.init = gk104_fifo_pbdma_init,
.init_timeout = gk208_fifo_pbdma_init_timeout,
};
static const struct gk104_fifo_func static const struct gk104_fifo_func
gk208_fifo = { gk208_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gk208_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine, .fault.engine = gk104_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
static const struct gk104_fifo_func static const struct gk104_fifo_func
gk20a_fifo = { gk20a_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gk208_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gk104_fifo_fault_engine, .fault.engine = gk104_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -41,6 +41,7 @@ gm107_fifo_runlist = { ...@@ -41,6 +41,7 @@ gm107_fifo_runlist = {
.size = 8, .size = 8,
.cgrp = gk110_fifo_runlist_cgrp, .cgrp = gk110_fifo_runlist_cgrp,
.chan = gm107_fifo_runlist_chan, .chan = gm107_fifo_runlist_chan,
.commit = gk104_fifo_runlist_commit,
}; };
const struct nvkm_enum const struct nvkm_enum
...@@ -68,7 +69,7 @@ gm107_fifo_fault_engine[] = { ...@@ -68,7 +69,7 @@ gm107_fifo_fault_engine[] = {
static const struct gk104_fifo_func static const struct gk104_fifo_func
gm107_fifo = { gm107_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gk208_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gm107_fifo_fault_engine, .fault.engine = gm107_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -26,9 +26,23 @@ ...@@ -26,9 +26,23 @@
#include <nvif/class.h> #include <nvif/class.h>
int
gm200_fifo_pbdma_nr(struct gk104_fifo *fifo)
{
struct nvkm_device *device = fifo->base.engine.subdev.device;
return nvkm_rd32(device, 0x002004) & 0x000000ff;
}
const struct gk104_fifo_pbdma_func
gm200_fifo_pbdma = {
.nr = gm200_fifo_pbdma_nr,
.init = gk104_fifo_pbdma_init,
.init_timeout = gk208_fifo_pbdma_init_timeout,
};
static const struct gk104_fifo_func static const struct gk104_fifo_func
gm200_fifo = { gm200_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gm107_fifo_fault_engine, .fault.engine = gm107_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
static const struct gk104_fifo_func static const struct gk104_fifo_func
gm20b_fifo = { gm20b_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gm107_fifo_fault_engine, .fault.engine = gm107_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -52,7 +52,7 @@ gp100_fifo_fault_engine[] = { ...@@ -52,7 +52,7 @@ gp100_fifo_fault_engine[] = {
static const struct gk104_fifo_func static const struct gk104_fifo_func
gp100_fifo = { gp100_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gp100_fifo_fault_engine, .fault.engine = gp100_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
static const struct gk104_fifo_func static const struct gk104_fifo_func
gp10b_fifo = { gp10b_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gm200_fifo_pbdma,
.fault.access = gk104_fifo_fault_access, .fault.access = gk104_fifo_fault_access,
.fault.engine = gp100_fifo_fault_engine, .fault.engine = gp100_fifo_fault_engine,
.fault.reason = gk104_fifo_fault_reason, .fault.reason = gk104_fifo_fault_reason,
......
...@@ -85,7 +85,7 @@ gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine) ...@@ -85,7 +85,7 @@ gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
case NVKM_ENGINE_MSVLD : return 0x0270; case NVKM_ENGINE_MSVLD : return 0x0270;
case NVKM_ENGINE_VIC : return 0x0280; case NVKM_ENGINE_VIC : return 0x0280;
case NVKM_ENGINE_MSENC : return 0x0290; case NVKM_ENGINE_MSENC : return 0x0290;
case NVKM_ENGINE_NVDEC : return 0x02100270; case NVKM_ENGINE_NVDEC0: return 0x02100270;
case NVKM_ENGINE_NVENC0: return 0x02100290; case NVKM_ENGINE_NVENC0: return 0x02100290;
case NVKM_ENGINE_NVENC1: return 0x0210; case NVKM_ENGINE_NVENC1: return 0x0210;
default: default:
...@@ -192,7 +192,7 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base) ...@@ -192,7 +192,7 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
gk104_fifo_runlist_remove(fifo, chan); gk104_fifo_runlist_remove(fifo, chan);
nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800); nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800);
gk104_fifo_gpfifo_kick(chan); gk104_fifo_gpfifo_kick(chan);
gk104_fifo_runlist_commit(fifo, chan->runl); gk104_fifo_runlist_update(fifo, chan->runl);
} }
nvkm_wr32(device, 0x800000 + coff, 0x00000000); nvkm_wr32(device, 0x800000 + coff, 0x00000000);
...@@ -213,7 +213,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) ...@@ -213,7 +213,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
if (list_empty(&chan->head) && !chan->killed) { if (list_empty(&chan->head) && !chan->killed) {
gk104_fifo_runlist_insert(fifo, chan); gk104_fifo_runlist_insert(fifo, chan);
nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400); nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
gk104_fifo_runlist_commit(fifo, chan->runl); gk104_fifo_runlist_update(fifo, chan->runl);
nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400); nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
} }
} }
...@@ -222,6 +222,7 @@ void * ...@@ -222,6 +222,7 @@ void *
gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
{ {
struct gk104_fifo_chan *chan = gk104_fifo_chan(base); struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
nvkm_memory_unref(&chan->mthd);
kfree(chan->cgrp); kfree(chan->cgrp);
return chan; return chan;
} }
...@@ -240,7 +241,7 @@ gk104_fifo_gpfifo_func = { ...@@ -240,7 +241,7 @@ gk104_fifo_gpfifo_func = {
static int static int
gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
u64 vmm, u64 ioffset, u64 ilength, u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
const struct nvkm_oclass *oclass, const struct nvkm_oclass *oclass,
struct nvkm_object **pobject) struct nvkm_object **pobject)
{ {
...@@ -279,6 +280,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ...@@ -279,6 +280,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
return ret; return ret;
*chid = chan->base.chid; *chid = chan->base.chid;
*inst = chan->base.inst->addr;
/* Hack to support GPUs where even individual channels should be /* Hack to support GPUs where even individual channels should be
* part of a channel group. * part of a channel group.
...@@ -315,6 +317,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ...@@ -315,6 +317,7 @@ gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
nvkm_wo32(chan->base.inst, 0x94, 0x30000001); nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
nvkm_wo32(chan->base.inst, 0x9c, 0x00000100); nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
nvkm_wo32(chan->base.inst, 0xac, 0x0000001f); nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
nvkm_wo32(chan->base.inst, 0xe4, priv ? 0x00000020 : 0x00000000);
nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid); nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000); nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */ nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
...@@ -337,15 +340,19 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, ...@@ -337,15 +340,19 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
"ioffset %016llx ilength %08x " "ioffset %016llx ilength %08x "
"runlist %016llx\n", "runlist %016llx priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset, args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist); args->v0.ilength, args->v0.runlist, args->v0.priv);
if (args->v0.priv && !oclass->client->super)
return -EINVAL;
return gk104_fifo_gpfifo_new_(fifo, return gk104_fifo_gpfifo_new_(fifo,
&args->v0.runlist, &args->v0.runlist,
&args->v0.chid, &args->v0.chid,
args->v0.vmm, args->v0.vmm,
args->v0.ioffset, args->v0.ioffset,
args->v0.ilength, args->v0.ilength,
&args->v0.inst,
args->v0.priv,
oclass, pobject); oclass, pobject);
} }
......
...@@ -25,9 +25,15 @@ ...@@ -25,9 +25,15 @@
#include <core/client.h> #include <core/client.h>
#include <core/gpuobj.h> #include <core/gpuobj.h>
#include <nvif/cla06f.h> #include <nvif/clc36f.h>
#include <nvif/unpack.h> #include <nvif/unpack.h>
static u32
gv100_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *chan)
{
return chan->chid;
}
static int static int
gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid) gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid)
{ {
...@@ -56,7 +62,7 @@ gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid ...@@ -56,7 +62,7 @@ gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid
return ret; return ret;
} }
static int int
gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
struct nvkm_engine *engine, bool suspend) struct nvkm_engine *engine, bool suspend)
{ {
...@@ -79,7 +85,7 @@ gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base, ...@@ -79,7 +85,7 @@ gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
return ret; return ret;
} }
static int int
gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
struct nvkm_engine *engine) struct nvkm_engine *engine)
{ {
...@@ -100,8 +106,8 @@ gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, ...@@ -100,8 +106,8 @@ gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
return gv100_fifo_gpfifo_engine_valid(chan, false, true); return gv100_fifo_gpfifo_engine_valid(chan, false, true);
} }
const struct nvkm_fifo_chan_func static const struct nvkm_fifo_chan_func
gv100_fifo_gpfifo_func = { gv100_fifo_gpfifo = {
.dtor = gk104_fifo_gpfifo_dtor, .dtor = gk104_fifo_gpfifo_dtor,
.init = gk104_fifo_gpfifo_init, .init = gk104_fifo_gpfifo_init,
.fini = gk104_fifo_gpfifo_fini, .fini = gk104_fifo_gpfifo_fini,
...@@ -110,19 +116,23 @@ gv100_fifo_gpfifo_func = { ...@@ -110,19 +116,23 @@ gv100_fifo_gpfifo_func = {
.engine_dtor = gk104_fifo_gpfifo_engine_dtor, .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
.engine_init = gv100_fifo_gpfifo_engine_init, .engine_init = gv100_fifo_gpfifo_engine_init,
.engine_fini = gv100_fifo_gpfifo_engine_fini, .engine_fini = gv100_fifo_gpfifo_engine_fini,
.submit_token = gv100_fifo_gpfifo_submit_token,
}; };
static int int
gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func,
u64 vmm, u64 ioffset, u64 ilength, struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
const struct nvkm_oclass *oclass, u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
u32 *token, const struct nvkm_oclass *oclass,
struct nvkm_object **pobject) struct nvkm_object **pobject)
{ {
struct nvkm_device *device = fifo->base.engine.subdev.device;
struct gk104_fifo_chan *chan; struct gk104_fifo_chan *chan;
int runlist = ffs(*runlists) -1, ret, i; int runlist = ffs(*runlists) -1, ret, i;
unsigned long engm; unsigned long engm;
u64 subdevs = 0; u64 subdevs = 0;
u64 usermem; u64 usermem, mthd;
u32 size;
if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr) if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
return -EINVAL; return -EINVAL;
...@@ -142,14 +152,15 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ...@@ -142,14 +152,15 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
chan->runl = runlist; chan->runl = runlist;
INIT_LIST_HEAD(&chan->head); INIT_LIST_HEAD(&chan->head);
ret = nvkm_fifo_chan_ctor(&gv100_fifo_gpfifo_func, &fifo->base, ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm,
0x1000, 0x1000, true, vmm, 0, subdevs, 0, subdevs, 1, fifo->user.bar->addr, 0x200,
1, fifo->user.bar->addr, 0x200,
oclass, &chan->base); oclass, &chan->base);
if (ret) if (ret)
return ret; return ret;
*chid = chan->base.chid; *chid = chan->base.chid;
*inst = chan->base.inst->addr;
*token = chan->base.func->submit_token(&chan->base);
/* Hack to support GPUs where even individual channels should be /* Hack to support GPUs where even individual channels should be
* part of a channel group. * part of a channel group.
...@@ -173,6 +184,20 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ...@@ -173,6 +184,20 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
nvkm_done(fifo->user.mem); nvkm_done(fifo->user.mem);
usermem = nvkm_memory_addr(fifo->user.mem) + usermem; usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
/* Allocate fault method buffer (magics come from nvgpu). */
size = nvkm_rd32(device, 0x104028); /* NV_PCE_PCE_MAP */
size = 27 * 5 * (((9 + 1 + 3) * hweight32(size)) + 2);
size = roundup(size, PAGE_SIZE);
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000, true,
&chan->mthd);
if (ret)
return ret;
mthd = nvkm_memory_bar2(chan->mthd);
if (mthd == ~0ULL)
return -EFAULT;
/* RAMFC */ /* RAMFC */
nvkm_kmap(chan->base.inst); nvkm_kmap(chan->base.inst);
nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem)); nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem));
...@@ -184,13 +209,13 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid, ...@@ -184,13 +209,13 @@ gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
(ilength << 16)); (ilength << 16));
nvkm_wo32(chan->base.inst, 0x084, 0x20400000); nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
nvkm_wo32(chan->base.inst, 0x094, 0x30000001); nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020); nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid); nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100); nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000);
nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080); nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000); nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
nvkm_wo32(chan->base.inst, 0x220, 0x020a1000); nvkm_wo32(chan->base.inst, 0x220, lower_32_bits(mthd));
nvkm_wo32(chan->base.inst, 0x224, 0x00000000); nvkm_wo32(chan->base.inst, 0x224, upper_32_bits(mthd));
nvkm_done(chan->base.inst); nvkm_done(chan->base.inst);
return gv100_fifo_gpfifo_engine_valid(chan, true, true); return gv100_fifo_gpfifo_engine_valid(chan, true, true);
} }
...@@ -201,7 +226,7 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, ...@@ -201,7 +226,7 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
{ {
struct nvkm_object *parent = oclass->parent; struct nvkm_object *parent = oclass->parent;
union { union {
struct kepler_channel_gpfifo_a_v0 v0; struct volta_channel_gpfifo_a_v0 v0;
} *args = data; } *args = data;
int ret = -ENOSYS; int ret = -ENOSYS;
...@@ -209,15 +234,20 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass, ...@@ -209,15 +234,20 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
"ioffset %016llx ilength %08x " "ioffset %016llx ilength %08x "
"runlist %016llx\n", "runlist %016llx priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset, args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist); args->v0.ilength, args->v0.runlist, args->v0.priv);
return gv100_fifo_gpfifo_new_(fifo, if (args->v0.priv && !oclass->client->super)
return -EINVAL;
return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo,
&args->v0.runlist, &args->v0.runlist,
&args->v0.chid, &args->v0.chid,
args->v0.vmm, args->v0.vmm,
args->v0.ioffset, args->v0.ioffset,
args->v0.ilength, args->v0.ilength,
&args->v0.inst,
args->v0.priv,
&args->v0.token,
oclass, pobject); oclass, pobject);
} }
......
/*
* Copyright 2018 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.
*/
#include "changk104.h"
#include "cgrp.h"
#include <core/client.h>
#include <core/gpuobj.h>
#include <nvif/clc36f.h>
#include <nvif/unpack.h>
static u32
tu104_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *base)
{
struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
return (chan->runl << 16) | chan->base.chid;
}
static const struct nvkm_fifo_chan_func
tu104_fifo_gpfifo = {
.dtor = gk104_fifo_gpfifo_dtor,
.init = gk104_fifo_gpfifo_init,
.fini = gk104_fifo_gpfifo_fini,
.ntfy = gf100_fifo_chan_ntfy,
.engine_ctor = gk104_fifo_gpfifo_engine_ctor,
.engine_dtor = gk104_fifo_gpfifo_engine_dtor,
.engine_init = gv100_fifo_gpfifo_engine_init,
.engine_fini = gv100_fifo_gpfifo_engine_fini,
.submit_token = tu104_fifo_gpfifo_submit_token,
};
int
tu104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
void *data, u32 size, struct nvkm_object **pobject)
{
struct nvkm_object *parent = oclass->parent;
union {
struct volta_channel_gpfifo_a_v0 v0;
} *args = data;
int ret = -ENOSYS;
nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
"ioffset %016llx ilength %08x "
"runlist %016llx priv %d\n",
args->v0.version, args->v0.vmm, args->v0.ioffset,
args->v0.ilength, args->v0.runlist, args->v0.priv);
if (args->v0.priv && !oclass->client->super)
return -EINVAL;
return gv100_fifo_gpfifo_new_(&tu104_fifo_gpfifo, fifo,
&args->v0.runlist,
&args->v0.chid,
args->v0.vmm,
args->v0.ioffset,
args->v0.ilength,
&args->v0.inst,
args->v0.priv,
&args->v0.token,
oclass, pobject);
}
return ret;
}
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <nvif/class.h> #include <nvif/class.h>
static void void
gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan, gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan,
struct nvkm_memory *memory, u32 offset) struct nvkm_memory *memory, u32 offset)
{ {
...@@ -42,7 +42,7 @@ gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan, ...@@ -42,7 +42,7 @@ gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan,
nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst)); nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst));
} }
static void void
gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp, gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
struct nvkm_memory *memory, u32 offset) struct nvkm_memory *memory, u32 offset)
{ {
...@@ -57,9 +57,10 @@ gv100_fifo_runlist = { ...@@ -57,9 +57,10 @@ gv100_fifo_runlist = {
.size = 16, .size = 16,
.cgrp = gv100_fifo_runlist_cgrp, .cgrp = gv100_fifo_runlist_cgrp,
.chan = gv100_fifo_runlist_chan, .chan = gv100_fifo_runlist_chan,
.commit = gk104_fifo_runlist_commit,
}; };
static const struct nvkm_enum const struct nvkm_enum
gv100_fifo_fault_gpcclient[] = { gv100_fifo_fault_gpcclient[] = {
{ 0x00, "T1_0" }, { 0x00, "T1_0" },
{ 0x01, "T1_1" }, { 0x01, "T1_1" },
...@@ -161,7 +162,7 @@ gv100_fifo_fault_gpcclient[] = { ...@@ -161,7 +162,7 @@ gv100_fifo_fault_gpcclient[] = {
{} {}
}; };
static const struct nvkm_enum const struct nvkm_enum
gv100_fifo_fault_hubclient[] = { gv100_fifo_fault_hubclient[] = {
{ 0x00, "VIP" }, { 0x00, "VIP" },
{ 0x01, "CE0" }, { 0x01, "CE0" },
...@@ -223,7 +224,7 @@ gv100_fifo_fault_hubclient[] = { ...@@ -223,7 +224,7 @@ gv100_fifo_fault_hubclient[] = {
{} {}
}; };
static const struct nvkm_enum const struct nvkm_enum
gv100_fifo_fault_reason[] = { gv100_fifo_fault_reason[] = {
{ 0x00, "PDE" }, { 0x00, "PDE" },
{ 0x01, "PDE_SIZE" }, { 0x01, "PDE_SIZE" },
...@@ -271,7 +272,7 @@ gv100_fifo_fault_engine[] = { ...@@ -271,7 +272,7 @@ gv100_fifo_fault_engine[] = {
{} {}
}; };
static const struct nvkm_enum const struct nvkm_enum
gv100_fifo_fault_access[] = { gv100_fifo_fault_access[] = {
{ 0x0, "VIRT_READ" }, { 0x0, "VIRT_READ" },
{ 0x1, "VIRT_WRITE" }, { 0x1, "VIRT_WRITE" },
...@@ -287,7 +288,7 @@ gv100_fifo_fault_access[] = { ...@@ -287,7 +288,7 @@ gv100_fifo_fault_access[] = {
static const struct gk104_fifo_func static const struct gk104_fifo_func
gv100_fifo = { gv100_fifo = {
.init_pbdma_timeout = gk208_fifo_init_pbdma_timeout, .pbdma = &gm200_fifo_pbdma,
.fault.access = gv100_fifo_fault_access, .fault.access = gv100_fifo_fault_access,
.fault.engine = gv100_fifo_fault_engine, .fault.engine = gv100_fifo_fault_engine,
.fault.reason = gv100_fifo_fault_reason, .fault.reason = gv100_fifo_fault_reason,
......
/*
* Copyright 2018 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.
*/
#include "gk104.h"
#include "cgrp.h"
#include "changk104.h"
#include "user.h"
#include <core/gpuobj.h>
#include <nvif/class.h>
static void
tu104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
struct nvkm_memory *mem, int nr)
{
struct nvkm_device *device = fifo->base.engine.subdev.device;
u64 addr = nvkm_memory_addr(mem);
/*XXX: target? */
nvkm_wr32(device, 0x002b00 + (runl * 0x10), lower_32_bits(addr));
nvkm_wr32(device, 0x002b04 + (runl * 0x10), upper_32_bits(addr));
nvkm_wr32(device, 0x002b08 + (runl * 0x10), nr);
/*XXX: how to wait? can you even wait? */
}
const struct gk104_fifo_runlist_func
tu104_fifo_runlist = {
.size = 16,
.cgrp = gv100_fifo_runlist_cgrp,
.chan = gv100_fifo_runlist_chan,
.commit = tu104_fifo_runlist_commit,
};
static const struct nvkm_enum
tu104_fifo_fault_engine[] = {
{ 0x01, "DISPLAY" },
{ 0x03, "PTP" },
{ 0x06, "PWR_PMU" },
{ 0x08, "IFB", NULL, NVKM_ENGINE_IFB },
{ 0x09, "PERF" },
{ 0x1f, "PHYSICAL" },
{ 0x20, "HOST0" },
{ 0x21, "HOST1" },
{ 0x22, "HOST2" },
{ 0x23, "HOST3" },
{ 0x24, "HOST4" },
{ 0x25, "HOST5" },
{ 0x26, "HOST6" },
{ 0x27, "HOST7" },
{ 0x28, "HOST8" },
{ 0x29, "HOST9" },
{ 0x2a, "HOST10" },
{ 0x2b, "HOST11" },
{ 0x2c, "HOST12" },
{ 0x2d, "HOST13" },
{ 0x2e, "HOST14" },
{ 0x80, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0xc0, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
{}
};
static void
tu104_fifo_pbdma_init(struct gk104_fifo *fifo)
{
struct nvkm_device *device = fifo->base.engine.subdev.device;
const u32 mask = (1 << fifo->pbdma_nr) - 1;
/*XXX: this is a bit of a guess at this point in time. */
nvkm_mask(device, 0xb65000, 0x80000fff, 0x80000000 | mask);
}
static const struct gk104_fifo_pbdma_func
tu104_fifo_pbdma = {
.nr = gm200_fifo_pbdma_nr,
.init = tu104_fifo_pbdma_init,
.init_timeout = gk208_fifo_pbdma_init_timeout,
};
static const struct gk104_fifo_func
tu104_fifo = {
.pbdma = &tu104_fifo_pbdma,
.fault.access = gv100_fifo_fault_access,
.fault.engine = tu104_fifo_fault_engine,
.fault.reason = gv100_fifo_fault_reason,
.fault.hubclient = gv100_fifo_fault_hubclient,
.fault.gpcclient = gv100_fifo_fault_gpcclient,
.runlist = &tu104_fifo_runlist,
.user = {{-1,-1,VOLTA_USERMODE_A }, tu104_fifo_user_new },
.chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu104_fifo_gpfifo_new },
.cgrp_force = true,
};
int
tu104_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
{
return gk104_fifo_new_(&tu104_fifo, device, index, 4096, pfifo);
}
...@@ -3,4 +3,6 @@ ...@@ -3,4 +3,6 @@
#include "priv.h" #include "priv.h"
int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32, int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32,
struct nvkm_object **); struct nvkm_object **);
int tu104_fifo_user_new(const struct nvkm_oclass *, void *, u32,
struct nvkm_object **);
#endif #endif
/*
* Copyright 2018 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.
*/
#include "user.h"
static int
tu104_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc,
enum nvkm_object_map *type, u64 *addr, u64 *size)
{
struct nvkm_device *device = object->engine->subdev.device;
*addr = 0xbb0000 + device->func->resource_addr(device, 0);
*size = 0x010000;
*type = NVKM_OBJECT_MAP_IO;
return 0;
}
static const struct nvkm_object_func
tu104_fifo_user = {
.map = tu104_fifo_user_map,
};
int
tu104_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
struct nvkm_object **pobject)
{
return nvkm_object_new_(&tu104_fifo_user, oclass, argv, argc, pobject);
}
...@@ -197,7 +197,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func, ...@@ -197,7 +197,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
case NVKM_SUBDEV_PMU: case NVKM_SUBDEV_PMU:
debug_reg = 0xc08; debug_reg = 0xc08;
break; break;
case NVKM_ENGINE_NVDEC: case NVKM_ENGINE_NVDEC0:
debug_reg = 0xd00; debug_reg = 0xd00;
break; break;
case NVKM_ENGINE_SEC2: case NVKM_ENGINE_SEC2:
......
...@@ -5,3 +5,4 @@ nvkm-y += nvkm/subdev/bar/gf100.o ...@@ -5,3 +5,4 @@ nvkm-y += nvkm/subdev/bar/gf100.o
nvkm-y += nvkm/subdev/bar/gk20a.o nvkm-y += nvkm/subdev/bar/gk20a.o
nvkm-y += nvkm/subdev/bar/gm107.o nvkm-y += nvkm/subdev/bar/gm107.o
nvkm-y += nvkm/subdev/bar/gm20b.o nvkm-y += nvkm/subdev/bar/gm20b.o
nvkm-y += nvkm/subdev/bar/tu104.o
...@@ -36,6 +36,16 @@ nvkm_bar_bar1_vmm(struct nvkm_device *device) ...@@ -36,6 +36,16 @@ nvkm_bar_bar1_vmm(struct nvkm_device *device)
return device->bar->func->bar1.vmm(device->bar); return device->bar->func->bar1.vmm(device->bar);
} }
void
nvkm_bar_bar1_reset(struct nvkm_device *device)
{
struct nvkm_bar *bar = device->bar;
if (bar) {
bar->func->bar1.init(bar);
bar->func->bar1.wait(bar);
}
}
struct nvkm_vmm * struct nvkm_vmm *
nvkm_bar_bar2_vmm(struct nvkm_device *device) nvkm_bar_bar2_vmm(struct nvkm_device *device)
{ {
...@@ -48,6 +58,16 @@ nvkm_bar_bar2_vmm(struct nvkm_device *device) ...@@ -48,6 +58,16 @@ nvkm_bar_bar2_vmm(struct nvkm_device *device)
return NULL; return NULL;
} }
void
nvkm_bar_bar2_reset(struct nvkm_device *device)
{
struct nvkm_bar *bar = device->bar;
if (bar && bar->bar2) {
bar->func->bar2.init(bar);
bar->func->bar2.wait(bar);
}
}
void void
nvkm_bar_bar2_fini(struct nvkm_device *device) nvkm_bar_bar2_fini(struct nvkm_device *device)
{ {
......
/*
* Copyright 2018 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.
*/
#include "gf100.h"
#include <core/memory.h>
#include <subdev/timer.h>
static void
tu104_bar_bar2_wait(struct nvkm_bar *bar)
{
struct nvkm_device *device = bar->subdev.device;
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0xb80f50) & 0x0000000c))
break;
);
}
static void
tu104_bar_bar2_fini(struct nvkm_bar *bar)
{
nvkm_mask(bar->subdev.device, 0xb80f48, 0x80000000, 0x00000000);
}
static void
tu104_bar_bar2_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct gf100_bar *bar = gf100_bar(base);
u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12;
if (bar->bar2_halve)
addr |= 0x40000000;
nvkm_wr32(device, 0xb80f48, 0x80000000 | addr);
}
static void
tu104_bar_bar1_wait(struct nvkm_bar *bar)
{
struct nvkm_device *device = bar->subdev.device;
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0xb80f50) & 0x00000003))
break;
);
}
static void
tu104_bar_bar1_fini(struct nvkm_bar *bar)
{
nvkm_mask(bar->subdev.device, 0xb80f40, 0x80000000, 0x00000000);
}
static void
tu104_bar_bar1_init(struct nvkm_bar *base)
{
struct nvkm_device *device = base->subdev.device;
struct gf100_bar *bar = gf100_bar(base);
const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12;
nvkm_wr32(device, 0xb80f40, 0x80000000 | addr);
}
static const struct nvkm_bar_func
tu104_bar = {
.dtor = gf100_bar_dtor,
.oneinit = gf100_bar_oneinit,
.bar1.init = tu104_bar_bar1_init,
.bar1.fini = tu104_bar_bar1_fini,
.bar1.wait = tu104_bar_bar1_wait,
.bar1.vmm = gf100_bar_bar1_vmm,
.bar2.init = tu104_bar_bar2_init,
.bar2.fini = tu104_bar_bar2_fini,
.bar2.wait = tu104_bar_bar2_wait,
.bar2.vmm = gf100_bar_bar2_vmm,
.flush = g84_bar_flush,
};
int
tu104_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar)
{
return gf100_bar_new_(&tu104_bar, device, index, pbar);
}
...@@ -13,3 +13,4 @@ nvkm-y += nvkm/subdev/devinit/gf100.o ...@@ -13,3 +13,4 @@ nvkm-y += nvkm/subdev/devinit/gf100.o
nvkm-y += nvkm/subdev/devinit/gm107.o nvkm-y += nvkm/subdev/devinit/gm107.o
nvkm-y += nvkm/subdev/devinit/gm200.o nvkm-y += nvkm/subdev/devinit/gm200.o
nvkm-y += nvkm/subdev/devinit/gv100.o nvkm-y += nvkm/subdev/devinit/gv100.o
nvkm-y += nvkm/subdev/devinit/tu104.o
...@@ -105,6 +105,15 @@ pmu_load(struct nv50_devinit *init, u8 type, bool post, ...@@ -105,6 +105,15 @@ pmu_load(struct nv50_devinit *init, u8 type, bool post,
return pmu_exec(init, pmu.init_addr_pmu), 0; return pmu_exec(init, pmu.init_addr_pmu), 0;
} }
void
gm200_devinit_preos(struct nv50_devinit *init, bool post)
{
/* Optional: Execute PRE_OS application on PMU, which should at
* least take care of fans until a full PMU has been loaded.
*/
pmu_load(init, 0x01, post, NULL, NULL);
}
int int
gm200_devinit_post(struct nvkm_devinit *base, bool post) gm200_devinit_post(struct nvkm_devinit *base, bool post)
{ {
...@@ -156,10 +165,7 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post) ...@@ -156,10 +165,7 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
/* Optional: Execute PRE_OS application on PMU, which should at gm200_devinit_preos(init, post);
* least take care of fans until a full PMU has been loaded.
*/
pmu_load(init, 0x01, post, NULL, NULL);
return 0; return 0;
} }
......
...@@ -26,4 +26,5 @@ void gf100_devinit_preinit(struct nvkm_devinit *); ...@@ -26,4 +26,5 @@ void gf100_devinit_preinit(struct nvkm_devinit *);
u64 gm107_devinit_disable(struct nvkm_devinit *); u64 gm107_devinit_disable(struct nvkm_devinit *);
int gm200_devinit_post(struct nvkm_devinit *, bool); int gm200_devinit_post(struct nvkm_devinit *, bool);
void gm200_devinit_preos(struct nv50_devinit *, bool);
#endif #endif
/*
* Copyright 2018 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.
*/
#include "nv50.h"
#include <subdev/bios.h>
#include <subdev/bios/pll.h>
#include <subdev/clk/pll.h>
static int
tu104_devinit_pll_set(struct nvkm_devinit *init, u32 type, u32 freq)
{
struct nvkm_subdev *subdev = &init->subdev;
struct nvkm_device *device = subdev->device;
struct nvbios_pll info;
int head = type - PLL_VPLL0;
int N, fN, M, P;
int ret;
ret = nvbios_pll_parse(device->bios, type, &info);
if (ret)
return ret;
ret = gt215_pll_calc(subdev, &info, freq, &N, &fN, &M, &P);
if (ret < 0)
return ret;
switch (info.type) {
case PLL_VPLL0:
case PLL_VPLL1:
case PLL_VPLL2:
case PLL_VPLL3:
nvkm_wr32(device, 0x00ef10 + (head * 0x40), fN << 16);
nvkm_wr32(device, 0x00ef04 + (head * 0x40), (P << 16) |
(N << 8) |
(M << 0));
/*XXX*/
nvkm_wr32(device, 0x00ef0c + (head * 0x40), 0x00000900);
nvkm_wr32(device, 0x00ef00 + (head * 0x40), 0x02000014);
break;
default:
nvkm_warn(subdev, "%08x/%dKhz unimplemented\n", type, freq);
ret = -EINVAL;
break;
}
return ret;
}
static int
tu104_devinit_post(struct nvkm_devinit *base, bool post)
{
struct nv50_devinit *init = nv50_devinit(base);
gm200_devinit_preos(init, post);
return 0;
}
static const struct nvkm_devinit_func
tu104_devinit = {
.init = nv50_devinit_init,
.post = tu104_devinit_post,
.pll_set = tu104_devinit_pll_set,
.disable = gm107_devinit_disable,
};
int
tu104_devinit_new(struct nvkm_device *device, int index,
struct nvkm_devinit **pinit)
{
return nv50_devinit_new_(&tu104_devinit, device, index, pinit);
}
nvkm-y += nvkm/subdev/fault/base.o nvkm-y += nvkm/subdev/fault/base.o
nvkm-y += nvkm/subdev/fault/gp100.o nvkm-y += nvkm/subdev/fault/gp100.o
nvkm-y += nvkm/subdev/fault/gv100.o nvkm-y += nvkm/subdev/fault/gv100.o
nvkm-y += nvkm/subdev/fault/tu104.o
...@@ -23,21 +23,19 @@ ...@@ -23,21 +23,19 @@
#include <core/memory.h> #include <core/memory.h>
#include <core/notify.h> #include <core/notify.h>
#include <subdev/bar.h>
#include <subdev/mmu.h>
static void static void
nvkm_fault_ntfy_fini(struct nvkm_event *event, int type, int index) nvkm_fault_ntfy_fini(struct nvkm_event *event, int type, int index)
{ {
struct nvkm_fault *fault = container_of(event, typeof(*fault), event); struct nvkm_fault *fault = container_of(event, typeof(*fault), event);
fault->func->buffer.fini(fault->buffer[index]); fault->func->buffer.intr(fault->buffer[index], false);
} }
static void static void
nvkm_fault_ntfy_init(struct nvkm_event *event, int type, int index) nvkm_fault_ntfy_init(struct nvkm_event *event, int type, int index)
{ {
struct nvkm_fault *fault = container_of(event, typeof(*fault), event); struct nvkm_fault *fault = container_of(event, typeof(*fault), event);
fault->func->buffer.init(fault->buffer[index]); fault->func->buffer.intr(fault->buffer[index], true);
} }
static int static int
...@@ -91,7 +89,6 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id) ...@@ -91,7 +89,6 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id)
{ {
struct nvkm_subdev *subdev = &fault->subdev; struct nvkm_subdev *subdev = &fault->subdev;
struct nvkm_device *device = subdev->device; struct nvkm_device *device = subdev->device;
struct nvkm_vmm *bar2 = nvkm_bar_bar2_vmm(device);
struct nvkm_fault_buffer *buffer; struct nvkm_fault_buffer *buffer;
int ret; int ret;
...@@ -99,7 +96,7 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id) ...@@ -99,7 +96,7 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id)
return -ENOMEM; return -ENOMEM;
buffer->fault = fault; buffer->fault = fault;
buffer->id = id; buffer->id = id;
buffer->entries = fault->func->buffer.entries(buffer); fault->func->buffer.info(buffer);
fault->buffer[id] = buffer; fault->buffer[id] = buffer;
nvkm_debug(subdev, "buffer %d: %d entries\n", id, buffer->entries); nvkm_debug(subdev, "buffer %d: %d entries\n", id, buffer->entries);
...@@ -110,12 +107,12 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id) ...@@ -110,12 +107,12 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id)
if (ret) if (ret)
return ret; return ret;
ret = nvkm_vmm_get(bar2, 12, nvkm_memory_size(buffer->mem), /* Pin fault buffer in BAR2. */
&buffer->vma); buffer->addr = nvkm_memory_bar2(buffer->mem);
if (ret) if (buffer->addr == ~0ULL)
return ret; return -EFAULT;
return nvkm_memory_map(buffer->mem, 0, bar2, buffer->vma, NULL, 0); return 0;
} }
static int static int
...@@ -146,7 +143,6 @@ nvkm_fault_oneinit(struct nvkm_subdev *subdev) ...@@ -146,7 +143,6 @@ nvkm_fault_oneinit(struct nvkm_subdev *subdev)
static void * static void *
nvkm_fault_dtor(struct nvkm_subdev *subdev) nvkm_fault_dtor(struct nvkm_subdev *subdev)
{ {
struct nvkm_vmm *bar2 = nvkm_bar_bar2_vmm(subdev->device);
struct nvkm_fault *fault = nvkm_fault(subdev); struct nvkm_fault *fault = nvkm_fault(subdev);
int i; int i;
...@@ -154,7 +150,6 @@ nvkm_fault_dtor(struct nvkm_subdev *subdev) ...@@ -154,7 +150,6 @@ nvkm_fault_dtor(struct nvkm_subdev *subdev)
for (i = 0; i < fault->buffer_nr; i++) { for (i = 0; i < fault->buffer_nr; i++) {
if (fault->buffer[i]) { if (fault->buffer[i]) {
nvkm_vmm_put(bar2, &fault->buffer[i]->vma);
nvkm_memory_unref(&fault->buffer[i]->mem); nvkm_memory_unref(&fault->buffer[i]->mem);
kfree(fault->buffer[i]); kfree(fault->buffer[i]);
} }
......
...@@ -21,7 +21,14 @@ ...@@ -21,7 +21,14 @@
*/ */
#include "priv.h" #include "priv.h"
#include <subdev/mmu.h> #include <subdev/mc.h>
static void
gp100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
{
struct nvkm_device *device = buffer->fault->subdev.device;
nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, enable);
}
static void static void
gp100_fault_buffer_fini(struct nvkm_fault_buffer *buffer) gp100_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
...@@ -34,15 +41,17 @@ static void ...@@ -34,15 +41,17 @@ static void
gp100_fault_buffer_init(struct nvkm_fault_buffer *buffer) gp100_fault_buffer_init(struct nvkm_fault_buffer *buffer)
{ {
struct nvkm_device *device = buffer->fault->subdev.device; struct nvkm_device *device = buffer->fault->subdev.device;
nvkm_wr32(device, 0x002a74, upper_32_bits(buffer->vma->addr)); nvkm_wr32(device, 0x002a74, upper_32_bits(buffer->addr));
nvkm_wr32(device, 0x002a70, lower_32_bits(buffer->vma->addr)); nvkm_wr32(device, 0x002a70, lower_32_bits(buffer->addr));
nvkm_mask(device, 0x002a70, 0x00000001, 0x00000001); nvkm_mask(device, 0x002a70, 0x00000001, 0x00000001);
} }
static u32 static void
gp100_fault_buffer_entries(struct nvkm_fault_buffer *buffer) gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
{ {
return nvkm_rd32(buffer->fault->subdev.device, 0x002a78); buffer->entries = nvkm_rd32(buffer->fault->subdev.device, 0x002a78);
buffer->get = 0x002a7c;
buffer->put = 0x002a80;
} }
static void static void
...@@ -56,9 +65,10 @@ gp100_fault = { ...@@ -56,9 +65,10 @@ gp100_fault = {
.intr = gp100_fault_intr, .intr = gp100_fault_intr,
.buffer.nr = 1, .buffer.nr = 1,
.buffer.entry_size = 32, .buffer.entry_size = 32,
.buffer.entries = gp100_fault_buffer_entries, .buffer.info = gp100_fault_buffer_info,
.buffer.init = gp100_fault_buffer_init, .buffer.init = gp100_fault_buffer_init,
.buffer.fini = gp100_fault_buffer_fini, .buffer.fini = gp100_fault_buffer_fini,
.buffer.intr = gp100_fault_buffer_intr,
}; };
int int
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment