On Sat, 2026-08-15 at 03:57 +0400, Mohamed Ahmed wrote:
> 
> +
> +static const struct nvkm_head_func
> +gb202_head = {
> +     .state = r535_head_state,
> +     .vblank_get = gb202_head_vblank_get,
> +     .vblank_put = gb202_head_vblank_put,
> +};
> +

You should probably add these two as well:

        .state = gv100_head_state,
        .rgpos = gv100_head_rgpos,

I don't think they've actually changed in blackwell, but it's possible
maybe they do change in GB200x so you probably want to double check so
we don't lose precise vblank timestamps again.

>  static struct nvkm_conn *
>  r535_conn_new(struct nvkm_disp *disp, u32 id)
>  {
> @@ -1496,6 +1523,20 @@ r535_disp_intr(struct nvkm_inth *inth)
>       return IRQ_HANDLED;
>  }
>  
> +static irqreturn_t
> +gb202_disp_intr(struct nvkm_inth *inth)
> +{
> +     struct nvkm_disp *disp = container_of(inth, typeof(*disp),
> engine.subdev.inth);
> +     irqreturn_t ret = r535_disp_intr(inth);
> +
> +     /* The FE interrupt vectors are message-based on NVD5.0. Re-
> arm the
> +      * low-latency vector so it fires again for any event that
> latched
> +      * while we were servicing.
> +      */
> +     nvkm_wr32(disp->engine.subdev.device, 0x611f34, 0x00000001);
> +     return ret;
> +}
> +
>  static void
>  r535_disp_fini(struct nvkm_disp *disp, bool suspend)
>  {
> @@ -1568,7 +1609,9 @@ r535_disp_oneinit(struct nvkm_disp *disp)
>       struct nvkm_device *device = disp->engine.subdev.device;
>       struct nvkm_gsp *gsp = device->gsp;
>       const struct nvkm_rm_api *rmapi = gsp->rm->api;
> +     const struct nvkm_rm_gpu *gpu = gsp->rm->gpu;
>       NV2080_CTRL_INTERNAL_DISPLAY_WRITE_INST_MEM_PARAMS *ctrl;
> +     nvkm_inth_func intr_func;
>       unsigned long mask;
>       int ret, i;
>  
> @@ -1722,7 +1765,12 @@ r535_disp_oneinit(struct nvkm_disp *disp)
>               nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
>  
>               for_each_set_bit(i, &disp->head.mask, disp->head.nr)
> {
> -                     ret = nvkm_head_new_(&r535_head, disp, i);
> +                     const struct nvkm_head_func *func =
> &r535_head;
> +
> +                     if (gpu->disp.class.root >= GB202_DISP)
> +                             func = &gb202_head;
> +
> +                     ret = nvkm_head_new_(func, disp, i);
>                       if (ret)
>                               return ret;
>               }
> @@ -1766,12 +1814,21 @@ r535_disp_oneinit(struct nvkm_disp *disp)
>       if (ret)
>               return ret;
>  
> -     ret = nvkm_gsp_intr_stall(gsp, disp->engine.subdev.type,
> disp->engine.subdev.inst);
> +     if (gpu->disp.class.root >= GB202_DISP) {
> +             /* GB20x deliver head-timing interrupts on the
> display's
> +              * separate low-latency vector (interrupt table
> instance 1).
> +              */
> +             ret = nvkm_gsp_intr_stall(gsp, disp-
> >engine.subdev.type, 1);
> +             intr_func = gb202_disp_intr;
> +     } else {
> +             ret = nvkm_gsp_intr_stall(gsp, disp-
> >engine.subdev.type, disp->engine.subdev.inst);
> +             intr_func = r535_disp_intr;
> +     }
>       if (ret < 0)
>               return ret;
>  
>       ret = nvkm_inth_add(&device->vfn->intr, ret,
> NVKM_INTR_PRIO_NORMAL, &disp->engine.subdev,
> -                         r535_disp_intr, &disp-
> >engine.subdev.inth);
> +                         intr_func, &disp->engine.subdev.inth);
>       if (ret)
>               return ret;
>  
> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c
> b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c
> index 996941c668ba..2590b22663cb 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c
> @@ -44,6 +44,14 @@ r570_gsp_xlat_mc_engine_idx(u32 mc_engine_idx,
> enum nvkm_subdev_type *ptype, int
>               *ptype = NVKM_ENGINE_DISP;
>               *pinst = 0;
>               return true;
> +     case MC_ENGINE_IDX_DISP_LOW:
> +             /* GB20x+ report a separate low-latency display
> vector, used
> +              * for head-timing interrupts. Expose it as a second
> DISP
> +              * interrupt instance.
> +              */
> +             *ptype = NVKM_ENGINE_DISP;
> +             *pinst = 1;
> +             return true;
>       case MC_ENGINE_IDX_CE0 ... MC_ENGINE_IDX_CE19:
>               *ptype = NVKM_ENGINE_CE;
>               *pinst = mc_engine_idx - MC_ENGINE_IDX_CE0;

Reply via email to