drm/nouveau/disp: move GSP head-timing ISR and vblank helpers to tu102.c

The GSP-RM display code in rm/r535/disp.c owns a handful of direct MMIO
routines: the head-timing (vblank) interrupt handler and the per-head
vblank enable/disable. They program display registers, not RM, so they
belong with the rest of the per-chip register code in engine/disp/.

Move them to tu102.c (Turing is the first GSP-capable generation) as
tu102_disp_intr() and tu102_head_vblank_get()/put(), exported for
rm/r535/disp.c, which keeps calling them by name for now. No functional
change.

Fixes: 6cc6e08d45 ("drm/nouveau/kms: add support for GB20x")
Cc: stable@vger.kernel.org
Signed-off-by: Mohamed Ahmed <mohamedahmedegypt2001@gmail.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patch.msgid.link/20260825001408.14219-2-mohamedahmedegypt2001@gmail.com
This commit is contained in:
Mohamed Ahmed 2026-08-25 04:13:59 +04:00 committed by Lyude Paul
parent 554ab79cfd
commit c6659e0ffc
4 changed files with 57 additions and 49 deletions

View File

@ -56,6 +56,9 @@ int gv100_head_new(struct nvkm_disp *, int id);
void gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state);
void gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline);
void tu102_head_vblank_get(struct nvkm_head *);
void tu102_head_vblank_put(struct nvkm_head *);
#define HEAD_MSG(h,l,f,a...) do { \
struct nvkm_head *_h = (h); \
nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \

View File

@ -72,6 +72,7 @@ int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *);
int gv100_disp_caps_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
int tu102_disp_init(struct nvkm_disp *);
irqreturn_t tu102_disp_intr(struct nvkm_inth *);
void nv50_disp_dptmds_war_2(struct nvkm_disp *, struct dcb_output *);
void nv50_disp_dptmds_war_3(struct nvkm_disp *, struct dcb_output *);

View File

@ -104,6 +104,56 @@ tu102_sor_new(struct nvkm_disp *disp, int id)
return nvkm_ior_new_(&tu102_sor, disp, SOR, id, hda & BIT(id));
}
/* The GSP-RM display path leaves head-timing (vblank) interrupts and their
* enables to us. These program the RM head-timing line (bit 1 of the
* per-head enable, not the bit nvkm's own gv100 path uses).
*/
void
tu102_head_vblank_put(struct nvkm_head *head)
{
struct nvkm_device *device = head->disp->engine.subdev.device;
nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000000);
}
void
tu102_head_vblank_get(struct nvkm_head *head)
{
struct nvkm_device *device = head->disp->engine.subdev.device;
nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002);
nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000002);
}
static void
tu102_disp_intr_head_timing(struct nvkm_disp *disp, int head)
{
struct nvkm_subdev *subdev = &disp->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 stat = nvkm_rd32(device, 0x611c00 + (head * 0x04));
if (stat & 0x00000002) {
nvkm_disp_vblank(disp, head);
nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000002);
}
}
irqreturn_t
tu102_disp_intr(struct nvkm_inth *inth)
{
struct nvkm_disp *disp = container_of(inth, typeof(*disp), engine.subdev.inth);
struct nvkm_subdev *subdev = &disp->engine.subdev;
struct nvkm_device *device = subdev->device;
unsigned long mask = nvkm_rd32(device, 0x611ec0) & 0x000000ff;
int head;
for_each_set_bit(head, &mask, 8)
tu102_disp_intr_head_timing(disp, head);
return IRQ_HANDLED;
}
int
tu102_disp_init(struct nvkm_disp *disp)
{

View File

@ -608,29 +608,12 @@ r535_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask)
return 4;
}
static void
r535_head_vblank_put(struct nvkm_head *head)
{
struct nvkm_device *device = head->disp->engine.subdev.device;
nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000000);
}
static void
r535_head_vblank_get(struct nvkm_head *head)
{
struct nvkm_device *device = head->disp->engine.subdev.device;
nvkm_wr32(device, 0x611800 + (head->id * 4), 0x00000002);
nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000002, 0x00000002);
}
static const struct nvkm_head_func
r535_head = {
.state = gv100_head_state,
.rgpos = gv100_head_rgpos,
.vblank_get = r535_head_vblank_get,
.vblank_put = r535_head_vblank_put,
.vblank_get = tu102_head_vblank_get,
.vblank_put = tu102_head_vblank_put,
};
static struct nvkm_conn *
@ -1404,35 +1387,6 @@ static const struct nvkm_event_func
r535_disp_event = {
};
static void
r535_disp_intr_head_timing(struct nvkm_disp *disp, int head)
{
struct nvkm_subdev *subdev = &disp->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 stat = nvkm_rd32(device, 0x611c00 + (head * 0x04));
if (stat & 0x00000002) {
nvkm_disp_vblank(disp, head);
nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000002);
}
}
static irqreturn_t
r535_disp_intr(struct nvkm_inth *inth)
{
struct nvkm_disp *disp = container_of(inth, typeof(*disp), engine.subdev.inth);
struct nvkm_subdev *subdev = &disp->engine.subdev;
struct nvkm_device *device = subdev->device;
unsigned long mask = nvkm_rd32(device, 0x611ec0) & 0x000000ff;
int head;
for_each_set_bit(head, &mask, 8)
r535_disp_intr_head_timing(disp, head);
return IRQ_HANDLED;
}
static void
r535_disp_fini(struct nvkm_disp *disp, bool suspend)
{
@ -1708,7 +1662,7 @@ r535_disp_oneinit(struct nvkm_disp *disp)
return ret;
ret = nvkm_inth_add(&device->vfn->intr, ret, NVKM_INTR_PRIO_NORMAL, &disp->engine.subdev,
r535_disp_intr, &disp->engine.subdev.inth);
tu102_disp_intr, &disp->engine.subdev.inth);
if (ret)
return ret;