Skip to content

Commit 6cc6e08

Browse files
Ben Skeggsairlied
authored andcommitted
drm/nouveau/kms: add support for GB20x
Adds basic support for the new display classes available on GB20x GPUs. Most of the changes here deal with HW method moves, with the only other change of note being tweaks to skip allocation of CTXDMA objects, which aren't required on Blackwell display. Signed-off-by: Ben Skeggs <[email protected]> Reviewed-by: Dave Airlie <[email protected]> Reviewed-by: Timur Tabi <[email protected]> Tested-by: Timur Tabi <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent f0ddbb1 commit 6cc6e08

File tree

27 files changed

+1836
-9
lines changed

27 files changed

+1836
-9
lines changed

drivers/gpu/drm/nouveau/dispnv50/Kbuild

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ nouveau-y += dispnv50/core907d.o
99
nouveau-y += dispnv50/core917d.o
1010
nouveau-y += dispnv50/corec37d.o
1111
nouveau-y += dispnv50/corec57d.o
12+
nouveau-y += dispnv50/coreca7d.o
1213

1314
nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crc.o
1415
nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crc907d.o
1516
nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crcc37d.o
1617
nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crcc57d.o
18+
nouveau-$(CONFIG_DEBUG_FS) += dispnv50/crcca7d.o
1719

1820
nouveau-y += dispnv50/dac507d.o
1921
nouveau-y += dispnv50/dac907d.o
@@ -31,6 +33,7 @@ nouveau-y += dispnv50/head907d.o
3133
nouveau-y += dispnv50/head917d.o
3234
nouveau-y += dispnv50/headc37d.o
3335
nouveau-y += dispnv50/headc57d.o
36+
nouveau-y += dispnv50/headca7d.o
3437

3538
nouveau-y += dispnv50/wimm.o
3639
nouveau-y += dispnv50/wimmc37b.o
@@ -39,6 +42,7 @@ nouveau-y += dispnv50/wndw.o
3942
nouveau-y += dispnv50/wndwc37e.o
4043
nouveau-y += dispnv50/wndwc57e.o
4144
nouveau-y += dispnv50/wndwc67e.o
45+
nouveau-y += dispnv50/wndwca7e.o
4246

4347
nouveau-y += dispnv50/base.o
4448
nouveau-y += dispnv50/base507c.o

drivers/gpu/drm/nouveau/dispnv50/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
4242
int version;
4343
int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
4444
} cores[] = {
45+
{ GB202_DISP_CORE_CHANNEL_DMA, 0, coreca7d_new },
4546
{ AD102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
4647
{ GA102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
4748
{ TU102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },

drivers/gpu/drm/nouveau/dispnv50/core.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
struct nv50_core {
99
const struct nv50_core_func *func;
10+
struct nv50_disp *disp;
11+
1012
struct nv50_dmac chan;
13+
1114
bool assign_windows;
1215
};
1316

@@ -18,6 +21,7 @@ struct nv50_core_func {
1821
int (*init)(struct nv50_core *);
1922
void (*ntfy_init)(struct nouveau_bo *, u32 offset);
2023
int (*caps_init)(struct nouveau_drm *, struct nv50_disp *);
24+
u32 caps_class;
2125
int (*ntfy_wait_done)(struct nouveau_bo *, u32 offset,
2226
struct nvif_device *);
2327
int (*update)(struct nv50_core *, u32 *interlock, bool ntfy);
@@ -70,4 +74,6 @@ int corec37d_wndw_owner(struct nv50_core *);
7074
extern const struct nv50_outp_func sorc37d;
7175

7276
int corec57d_new(struct nouveau_drm *, s32, struct nv50_core **);
77+
78+
int coreca7d_new(struct nouveau_drm *, s32, struct nv50_core **);
7379
#endif

drivers/gpu/drm/nouveau/dispnv50/core507d.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm,
165165
if (!(core = *pcore = kzalloc(sizeof(*core), GFP_KERNEL)))
166166
return -ENOMEM;
167167
core->func = func;
168+
core->disp = disp;
168169

169170
ret = nv50_dmac_create(drm,
170171
&oclass, 0, &args, sizeof(args),

drivers/gpu/drm/nouveau/dispnv50/corec37d.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ int corec37d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
105105
int ret;
106106

107107
ret = nvif_object_ctor(&disp->disp->object, "dispCaps", 0,
108-
GV100_DISP_CAPS, NULL, 0, &disp->caps);
108+
disp->core->func->caps_class, NULL, 0, &disp->caps);
109109
if (ret) {
110110
NV_ERROR(drm,
111111
"Failed to init notifier caps region: %d\n",
@@ -162,6 +162,7 @@ corec37d = {
162162
.init = corec37d_init,
163163
.ntfy_init = corec37d_ntfy_init,
164164
.caps_init = corec37d_caps_init,
165+
.caps_class = GV100_DISP_CAPS,
165166
.ntfy_wait_done = corec37d_ntfy_wait_done,
166167
.update = corec37d_update,
167168
.wndw.owner = corec37d_wndw_owner,

drivers/gpu/drm/nouveau/dispnv50/corec57d.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "core.h"
2323
#include "head.h"
2424

25+
#include <nvif/class.h>
2526
#include <nvif/pushc37b.h>
2627

2728
#include <nvhw/class/clc57d.h>
@@ -63,6 +64,7 @@ corec57d = {
6364
.init = corec57d_init,
6465
.ntfy_init = corec37d_ntfy_init,
6566
.caps_init = corec37d_caps_init,
67+
.caps_class = GV100_DISP_CAPS,
6668
.ntfy_wait_done = corec37d_ntfy_wait_done,
6769
.update = corec37d_update,
6870
.wndw.owner = corec37d_wndw_owner,
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* SPDX-License-Identifier: MIT
2+
*
3+
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
4+
*/
5+
#include "core.h"
6+
#include "head.h"
7+
8+
#include <nvif/class.h>
9+
#include <nvif/pushc97b.h>
10+
11+
#include <nvhw/class/clca7d.h>
12+
13+
#include <nouveau_bo.h>
14+
15+
static int
16+
coreca7d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
17+
{
18+
const u64 ntfy_addr = core->disp->sync->offset + NV50_DISP_CORE_NTFY;
19+
const u32 ntfy_hi = upper_32_bits(ntfy_addr);
20+
const u32 ntfy_lo = lower_32_bits(ntfy_addr);
21+
struct nvif_push *push = &core->chan.push;
22+
int ret;
23+
24+
ret = PUSH_WAIT(push, 5 + (ntfy ? 5 + 2 : 0));
25+
if (ret)
26+
return ret;
27+
28+
if (ntfy) {
29+
PUSH_MTHD(push, NVCA7D, SET_SURFACE_ADDRESS_HI_NOTIFIER, ntfy_hi,
30+
31+
SET_SURFACE_ADDRESS_LO_NOTIFIER,
32+
NVVAL(NVCA7D, SET_SURFACE_ADDRESS_LO_NOTIFIER, ADDRESS_LO, ntfy_lo >> 4) |
33+
NVDEF(NVCA7D, SET_SURFACE_ADDRESS_LO_NOTIFIER, TARGET, PHYSICAL_NVM) |
34+
NVDEF(NVCA7D, SET_SURFACE_ADDRESS_LO_NOTIFIER, ENABLE, ENABLE));
35+
36+
PUSH_MTHD(push, NVCA7D, SET_NOTIFIER_CONTROL,
37+
NVDEF(NVCA7D, SET_NOTIFIER_CONTROL, MODE, WRITE) |
38+
NVDEF(NVCA7D, SET_NOTIFIER_CONTROL, NOTIFY, ENABLE));
39+
}
40+
41+
PUSH_MTHD(push, NVCA7D, SET_INTERLOCK_FLAGS, interlock[NV50_DISP_INTERLOCK_CURS],
42+
SET_WINDOW_INTERLOCK_FLAGS, interlock[NV50_DISP_INTERLOCK_WNDW]);
43+
44+
PUSH_MTHD(push, NVCA7D, UPDATE,
45+
NVDEF(NVCA7D, UPDATE, RELEASE_ELV, TRUE) |
46+
NVDEF(NVCA7D, UPDATE, SPECIAL_HANDLING, NONE) |
47+
NVDEF(NVCA7D, UPDATE, INHIBIT_INTERRUPTS, FALSE));
48+
49+
if (ntfy) {
50+
PUSH_MTHD(push, NVCA7D, SET_NOTIFIER_CONTROL,
51+
NVDEF(NVCA7D, SET_NOTIFIER_CONTROL, NOTIFY, DISABLE));
52+
}
53+
54+
return PUSH_KICK(push);
55+
}
56+
57+
static int
58+
coreca7d_init(struct nv50_core *core)
59+
{
60+
struct nvif_push *push = &core->chan.push;
61+
const u32 windows = 8, heads = 4;
62+
int ret, i;
63+
64+
ret = PUSH_WAIT(push, windows * 6 + heads * 6);
65+
if (ret)
66+
return ret;
67+
68+
for (i = 0; i < windows; i++) {
69+
PUSH_MTHD(push, NVCA7D, WINDOW_SET_WINDOW_FORMAT_USAGE_BOUNDS(i),
70+
NVDEF(NVCA7D, WINDOW_SET_WINDOW_FORMAT_USAGE_BOUNDS, RGB_PACKED1BPP, TRUE) |
71+
NVDEF(NVCA7D, WINDOW_SET_WINDOW_FORMAT_USAGE_BOUNDS, RGB_PACKED2BPP, TRUE) |
72+
NVDEF(NVCA7D, WINDOW_SET_WINDOW_FORMAT_USAGE_BOUNDS, RGB_PACKED4BPP, TRUE) |
73+
NVDEF(NVCA7D, WINDOW_SET_WINDOW_FORMAT_USAGE_BOUNDS, RGB_PACKED8BPP, TRUE),
74+
75+
WINDOW_SET_WINDOW_ROTATED_FORMAT_USAGE_BOUNDS(i), 0x00000000);
76+
77+
PUSH_MTHD(push, NVCA7D, WINDOW_SET_WINDOW_USAGE_BOUNDS(i),
78+
NVVAL(NVCA7D, WINDOW_SET_WINDOW_USAGE_BOUNDS, MAX_PIXELS_FETCHED_PER_LINE, 0x7fff) |
79+
NVDEF(NVCA7D, WINDOW_SET_WINDOW_USAGE_BOUNDS, ILUT_ALLOWED, TRUE) |
80+
NVDEF(NVCA7D, WINDOW_SET_WINDOW_USAGE_BOUNDS, INPUT_SCALER_TAPS, TAPS_2) |
81+
NVDEF(NVCA7D, WINDOW_SET_WINDOW_USAGE_BOUNDS, UPSCALING_ALLOWED, FALSE),
82+
83+
WINDOW_SET_PHYSICAL(i), BIT(i));
84+
}
85+
86+
for (i = 0; i < heads; i++) {
87+
PUSH_MTHD(push, NVCA7D, HEAD_SET_HEAD_USAGE_BOUNDS(i),
88+
NVDEF(NVCA7D, HEAD_SET_HEAD_USAGE_BOUNDS, CURSOR, USAGE_W256_H256) |
89+
NVDEF(NVCA7D, HEAD_SET_HEAD_USAGE_BOUNDS, OLUT_ALLOWED, TRUE) |
90+
NVDEF(NVCA7D, HEAD_SET_HEAD_USAGE_BOUNDS, OUTPUT_SCALER_TAPS, TAPS_2) |
91+
NVDEF(NVCA7D, HEAD_SET_HEAD_USAGE_BOUNDS, UPSCALING_ALLOWED, TRUE));
92+
93+
PUSH_MTHD(push, NVCA7D, HEAD_SET_TILE_MASK(i), BIT(i));
94+
95+
PUSH_MTHD(push, NVCA7D, TILE_SET_TILE_SIZE(i), 0);
96+
}
97+
98+
core->assign_windows = true;
99+
return PUSH_KICK(push);
100+
}
101+
102+
static const struct nv50_core_func
103+
coreca7d = {
104+
.init = coreca7d_init,
105+
.ntfy_init = corec37d_ntfy_init,
106+
.caps_init = corec37d_caps_init,
107+
.caps_class = GB202_DISP_CAPS,
108+
.ntfy_wait_done = corec37d_ntfy_wait_done,
109+
.update = coreca7d_update,
110+
.wndw.owner = corec37d_wndw_owner,
111+
.head = &headca7d,
112+
.sor = &sorc37d,
113+
#if IS_ENABLED(CONFIG_DEBUG_FS)
114+
.crc = &crcca7d,
115+
#endif
116+
};
117+
118+
int
119+
coreca7d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
120+
{
121+
return core507d_new_(&coreca7d, drm, oclass, pcore);
122+
}

drivers/gpu/drm/nouveau/dispnv50/crc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,10 @@ nv50_crc_ctx_init(struct nv50_head *head, struct nvif_mmu *mmu,
509509
if (ret)
510510
return ret;
511511

512+
/* No CTXDMAs on Blackwell. */
513+
if (core->chan.base.user.oclass >= GB202_DISP_CORE_CHANNEL_DMA)
514+
return 0;
515+
512516
ret = nvif_object_ctor(&core->chan.base.user, "kmsCrcNtfyCtxDma",
513517
NV50_DISP_HANDLE_CRC_CTX(head, idx),
514518
NV_DMA_IN_MEMORY,

drivers/gpu/drm/nouveau/dispnv50/crc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ void nv50_crc_atomic_clr(struct nv50_head *);
9494
extern const struct nv50_crc_func crc907d;
9595
extern const struct nv50_crc_func crcc37d;
9696
extern const struct nv50_crc_func crcc57d;
97+
extern const struct nv50_crc_func crcca7d;
9798

9899
#else /* IS_ENABLED(CONFIG_DEBUG_FS) */
99100
struct nv50_crc {};
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/* SPDX-License-Identifier: MIT
2+
*
3+
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
4+
*/
5+
#include "crcc37d.h"
6+
#include "core.h"
7+
#include "head.h"
8+
9+
#include <nvif/pushc97b.h>
10+
11+
#include <nvhw/class/clca7d.h>
12+
13+
static int
14+
crcca7d_set_ctx(struct nv50_head *head, struct nv50_crc_notifier_ctx *ctx)
15+
{
16+
struct nvif_push *push = &head->disp->core->chan.push;
17+
const int i = head->base.index;
18+
int ret;
19+
20+
ret = PUSH_WAIT(push, ctx ? 3 : 2);
21+
if (ret)
22+
return ret;
23+
24+
if (ctx) {
25+
const u32 crc_hi = upper_32_bits(ctx->mem.addr);
26+
const u32 crc_lo = lower_32_bits(ctx->mem.addr);
27+
28+
PUSH_MTHD(push, NVCA7D, HEAD_SET_SURFACE_ADDRESS_HI_CRC(i), crc_hi,
29+
30+
HEAD_SET_SURFACE_ADDRESS_LO_CRC(i),
31+
NVVAL(NVCA7D, HEAD_SET_SURFACE_ADDRESS_LO_CRC, ADDRESS_LO, crc_lo >> 4) |
32+
NVDEF(NVCA7D, HEAD_SET_SURFACE_ADDRESS_LO_CRC, TARGET, PHYSICAL_NVM) |
33+
NVDEF(NVCA7D, HEAD_SET_SURFACE_ADDRESS_LO_CRC, ENABLE, ENABLE));
34+
} else {
35+
PUSH_MTHD(push, NVCA7D, HEAD_SET_SURFACE_ADDRESS_LO_CRC(i),
36+
NVDEF(NVCA7D, HEAD_SET_SURFACE_ADDRESS_LO_CRC, ENABLE, DISABLE));
37+
}
38+
39+
return 0;
40+
}
41+
42+
static int
43+
crcca7d_set_src(struct nv50_head *head, int or, enum nv50_crc_source_type source,
44+
struct nv50_crc_notifier_ctx *ctx)
45+
{
46+
struct nvif_push *push = &head->disp->core->chan.push;
47+
const int i = head->base.index;
48+
int primary_crc, ret;
49+
50+
if (!source) {
51+
ret = PUSH_WAIT(push, 1);
52+
if (ret)
53+
return ret;
54+
55+
PUSH_MTHD(push, NVCA7D, HEAD_SET_CRC_CONTROL(i), 0);
56+
57+
return crcca7d_set_ctx(head, NULL);
58+
}
59+
60+
switch (source) {
61+
case NV50_CRC_SOURCE_TYPE_SOR:
62+
primary_crc = NVCA7D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SOR(or);
63+
break;
64+
case NV50_CRC_SOURCE_TYPE_SF:
65+
primary_crc = NVCA7D_HEAD_SET_CRC_CONTROL_PRIMARY_CRC_SF;
66+
break;
67+
default:
68+
break;
69+
}
70+
71+
ret = crcca7d_set_ctx(head, ctx);
72+
if (ret)
73+
return ret;
74+
75+
ret = PUSH_WAIT(push, 2);
76+
if (ret)
77+
return ret;
78+
79+
PUSH_MTHD(push, NVCA7D, HEAD_SET_CRC_CONTROL(i),
80+
NVDEF(NVCA7D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, CORE) |
81+
NVDEF(NVCA7D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) |
82+
NVVAL(NVCA7D, HEAD_SET_CRC_CONTROL, PRIMARY_CRC, primary_crc) |
83+
NVDEF(NVCA7D, HEAD_SET_CRC_CONTROL, SECONDARY_CRC, NONE) |
84+
NVDEF(NVCA7D, HEAD_SET_CRC_CONTROL, CRC_DURING_SNOOZE, DISABLE));
85+
86+
return 0;
87+
}
88+
89+
const struct nv50_crc_func
90+
crcca7d = {
91+
.set_src = crcca7d_set_src,
92+
.set_ctx = crcca7d_set_ctx,
93+
.get_entry = crcc37d_get_entry,
94+
.ctx_finished = crcc37d_ctx_finished,
95+
.flip_threshold = CRCC37D_FLIP_THRESHOLD,
96+
.num_entries = CRCC37D_MAX_ENTRIES,
97+
.notifier_len = sizeof(struct crcc37d_notifier),
98+
};

0 commit comments

Comments
 (0)