Commit e7070389 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'topic/nvidia-gsp-2023-11-03' of git://anongit.freedesktop.org/drm/drm

Pull drm nouveau GSP support from Dave Airlie:
 "This adds the initial support for the NVIDIA GSP firmware to nouveau.

  This firmware is a new direction for Turing+ GPUs, and is only enabled
  by default on Ada generation. Other generations need to use
  nouveau.config=NvGspRm=1

  The GSP firmware takes nearly all the GPU init and power management
  tasks onto a risc-v CPU on the GPU.

  This series is mostly the work from Ben Skeggs, and Dave added some
  patches to rebase it to the latest firmware release which is where we
  will stay for as long as possible as the firmwares have no ABI
  stability"

* tag 'topic/nvidia-gsp-2023-11-03' of git://anongit.freedesktop.org/drm/drm: (49 commits)
  nouveau/gsp: add some basic registry entries.
  nouveau/gsp: fix message signature.
  nouveau/gsp: move to 535.113.01
  nouveau/disp: fix post-gsp build on 32-bit arm.
  nouveau: fix r535 build on 32-bit arm.
  drm/nouveau/ofa/r535: initial support
  drm/nouveau/nvjpg/r535: initial support
  drm/nouveau/nvenc/r535: initial support
  drm/nouveau/nvdec/r535: initial support
  drm/nouveau/gr/r535: initial support
  drm/nouveau/ce/r535: initial support
  drm/nouveau/fifo/r535: initial support
  drm/nouveau/disp/r535: initial support
  drm/nouveau/mmu/r535: initial support
  drm/nouveau/gsp/r535: add interrupt handling
  drm/nouveau/gsp/r535: add support for rm alloc
  drm/nouveau/gsp/r535: add support for rm control
  drm/nouveau/gsp/r535: add support for booting GSP-RM
  drm/nouveau/nvkm: support loading fws into sg_table
  drm/nouveau/kms/tu102-: disable vbios parsing when running on RM
  ...
parents aea6bf90 8d55b0a9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ nv50_core_new(struct nouveau_drm *drm, struct nv50_core **pcore)
		int version;
		int (*new)(struct nouveau_drm *, s32, struct nv50_core **);
	} cores[] = {
		{ AD102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
		{ GA102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
		{ TU102_DISP_CORE_CHANNEL_DMA, 0, corec57d_new },
		{ GV100_DISP_CORE_CHANNEL_DMA, 0, corec37d_new },
+143 −0
Original line number Diff line number Diff line
@@ -1592,6 +1592,148 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *st
	nv_encoder->crtc = NULL;
}

// common/inc/displayport/displayport.h
#define DP_CONFIG_WATERMARK_ADJUST                   2
#define DP_CONFIG_WATERMARK_LIMIT                   20
#define DP_CONFIG_INCREASED_WATERMARK_ADJUST         8
#define DP_CONFIG_INCREASED_WATERMARK_LIMIT         22

static bool
nv50_sor_dp_watermark_sst(struct nouveau_encoder *outp,
			  struct nv50_head *head, struct nv50_head_atom *asyh)
{
	bool enhancedFraming = outp->dp.dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP;
	u64 minRate = outp->dp.link_bw * 1000;
	unsigned tuSize = 64;
	unsigned waterMark;
	unsigned hBlankSym;
	unsigned vBlankSym;
	unsigned watermarkAdjust = DP_CONFIG_WATERMARK_ADJUST;
	unsigned watermarkMinimum = DP_CONFIG_WATERMARK_LIMIT;
	// depth is multiplied by 16 in case of DSC enable
	s32 hblank_symbols;
	// number of link clocks per line.
	int vblank_symbols	  = 0;
	bool bEnableDsc = false;
	unsigned surfaceWidth = asyh->mode.h.blanks - asyh->mode.h.blanke;
	unsigned rasterWidth = asyh->mode.h.active;
	unsigned depth = asyh->or.bpc * 3;
	unsigned DSC_FACTOR = bEnableDsc ? 16 : 1;
	u64 pixelClockHz = asyh->mode.clock * 1000;
	u64 PrecisionFactor = 100000, ratioF, watermarkF;
	u32 numLanesPerLink = outp->dp.link_nr;
	u32 numSymbolsPerLine;
	u32 BlankingBits;
	u32 surfaceWidthPerLink;
	u32 PixelSteeringBits;
	u64 NumBlankingLinkClocks;
	u32 MinHBlank;

	if (outp->outp.info.dp.increased_wm) {
		watermarkAdjust = DP_CONFIG_INCREASED_WATERMARK_ADJUST;
		watermarkMinimum = DP_CONFIG_INCREASED_WATERMARK_LIMIT;
	}

	if ((pixelClockHz * depth) >= (8 * minRate * outp->dp.link_nr * DSC_FACTOR))
	{
		return false;
	}

	//
	// For DSC, if (pclk * bpp) < (1/64 * orclk * 8 * lanes) then some TU may end up with
	// 0 active symbols. This may cause HW hang. Bug 200379426
	//
	if ((bEnableDsc) &&
	    ((pixelClockHz * depth) < div_u64(8 * minRate * outp->dp.link_nr * DSC_FACTOR, 64)))
	{
		return false;
	}

	//
	//  Perform the SST calculation.
	//	For auto mode the watermark calculation does not need to track accumulated error the
	//	formulas for manual mode will not work.  So below calculation was extracted from the DTB.
	//
	ratioF = div_u64((u64)pixelClockHz * depth * PrecisionFactor, DSC_FACTOR);

	ratioF = div_u64(ratioF, 8 * (u64) minRate * outp->dp.link_nr);

	if (PrecisionFactor < ratioF) // Assert if we will end up with a negative number in below
		return false;

	watermarkF = div_u64(ratioF * tuSize * (PrecisionFactor - ratioF), PrecisionFactor);
	waterMark = (unsigned)(watermarkAdjust + (div_u64(2 * div_u64(depth * PrecisionFactor, 8 * numLanesPerLink * DSC_FACTOR) + watermarkF, PrecisionFactor)));

	//
	//  Bounds check the watermark
	//
	numSymbolsPerLine = div_u64(surfaceWidth * depth, 8 * outp->dp.link_nr * DSC_FACTOR);

	if (WARN_ON(waterMark > 39 || waterMark > numSymbolsPerLine))
		return false;

	//
	//  Clamp the low side
	//
	if (waterMark < watermarkMinimum)
		waterMark = watermarkMinimum;

	//Bits to send BS/BE/Extra symbols due to pixel padding
	//Also accounts for enhanced framing.
	BlankingBits = 3*8*numLanesPerLink + (enhancedFraming ? 3*8*numLanesPerLink : 0);

	//VBID/MVID/MAUD sent 4 times all the time
	BlankingBits += 3*8*4;

	surfaceWidthPerLink = surfaceWidth;

	//Extra bits sent due to pixel steering
	u32 remain;
	div_u64_rem(surfaceWidthPerLink, numLanesPerLink, &remain);
	PixelSteeringBits = remain ? div_u64((numLanesPerLink - remain) * depth, DSC_FACTOR) : 0;

	BlankingBits += PixelSteeringBits;
	NumBlankingLinkClocks = div_u64((u64)BlankingBits * PrecisionFactor, (8 * numLanesPerLink));
	MinHBlank = (u32)(div_u64(div_u64(NumBlankingLinkClocks * pixelClockHz, minRate), PrecisionFactor));
	MinHBlank += 12;

	if (WARN_ON(MinHBlank > rasterWidth - surfaceWidth))
		return false;

	// Bug 702290 - Active Width should be greater than 60
	if (WARN_ON(surfaceWidth <= 60))
		return false;


	hblank_symbols = (s32)(div_u64((u64)(rasterWidth - surfaceWidth - MinHBlank) * minRate, pixelClockHz));

	//reduce HBlank Symbols to account for secondary data packet
	hblank_symbols -= 1; //Stuffer latency to send BS
	hblank_symbols -= 3; //SPKT latency to send data to stuffer

	hblank_symbols -= numLanesPerLink == 1 ? 9  : numLanesPerLink == 2 ? 6 : 3;

	hBlankSym = (hblank_symbols < 0) ? 0 : hblank_symbols;

	// Refer to dev_disp.ref for more information.
	// # symbols/vblank = ((SetRasterBlankEnd.X + SetRasterSize.Width - SetRasterBlankStart.X - 40) * link_clk / pclk) - Y - 1;
	// where Y = (# lanes == 4) 12 : (# lanes == 2) ? 21 : 39
	if (surfaceWidth < 40)
	{
		vblank_symbols = 0;
	}
	else
	{
		vblank_symbols = (s32)((div_u64((u64)(surfaceWidth - 40) * minRate, pixelClockHz))) - 1;

		vblank_symbols -= numLanesPerLink == 1 ? 39  : numLanesPerLink == 2 ? 21 : 12;
	}

	vBlankSym = (vblank_symbols < 0) ? 0 : vblank_symbols;

	return nvif_outp_dp_sst(&outp->outp, head->base.index, waterMark, hBlankSym, vBlankSym);
}

static void
nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *state)
{
@@ -1679,6 +1821,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
		break;
	case DCB_OUTPUT_DP:
		nouveau_dp_train(nv_encoder, false, mode->clock, asyh->or.bpc);
		nv50_sor_dp_watermark_sst(nv_encoder, head, asyh);
		depth = nv50_dp_bpc_to_depth(asyh->or.bpc);

		if (nv_encoder->outp.or.link & 1)
+3 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ struct nv_device_info_v0 {
#define NV_DEVICE_INFO_V0_VOLTA                                            0x0b
#define NV_DEVICE_INFO_V0_TURING                                           0x0c
#define NV_DEVICE_INFO_V0_AMPERE                                           0x0d
#define NV_DEVICE_INFO_V0_ADA                                              0x0e
	__u8  family;
	__u8  pad06[2];
	__u64 ram_size;
@@ -90,6 +91,8 @@ struct nv_device_time_v0 {
#define NV_DEVICE_HOST_RUNLIST_ENGINES_SEC2                          0x00004000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_NVDEC                         0x00008000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_NVENC                         0x00010000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_NVJPG                         0x00020000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_OFA                           0x00040000
/* Returns the number of available channels on runlist(data). */
#define NV_DEVICE_HOST_RUNLIST_CHANNELS               NV_DEVICE_HOST(0x00000101)
#endif
+21 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@
#define GV100_DISP                                    /* if0010.h */ 0x0000c370
#define TU102_DISP                                    /* if0010.h */ 0x0000c570
#define GA102_DISP                                    /* if0010.h */ 0x0000c670
#define AD102_DISP                                    /* if0010.h */ 0x0000c770

#define GV100_DISP_CAPS                                              0x0000c373

@@ -154,6 +155,7 @@
#define GV100_DISP_CORE_CHANNEL_DMA                   /* if0014.h */ 0x0000c37d
#define TU102_DISP_CORE_CHANNEL_DMA                   /* if0014.h */ 0x0000c57d
#define GA102_DISP_CORE_CHANNEL_DMA                   /* if0014.h */ 0x0000c67d
#define AD102_DISP_CORE_CHANNEL_DMA                   /* if0014.h */ 0x0000c77d

#define NV50_DISP_OVERLAY_CHANNEL_DMA                 /* if0014.h */ 0x0000507e
#define G82_DISP_OVERLAY_CHANNEL_DMA                  /* if0014.h */ 0x0000827e
@@ -192,8 +194,15 @@

#define AMPERE_B                                      /* cl9097.h */ 0x0000c797

#define ADA_A                                         /* cl9097.h */ 0x0000c997

#define NV74_BSP                                                     0x000074b0

#define NVC4B0_VIDEO_DECODER                                         0x0000c4b0
#define NVC6B0_VIDEO_DECODER                                         0x0000c6b0
#define NVC7B0_VIDEO_DECODER                                         0x0000c7b0
#define NVC9B0_VIDEO_DECODER                                         0x0000c9b0

#define GT212_MSVLD                                                  0x000085b1
#define IGT21A_MSVLD                                                 0x000086b1
#define G98_MSVLD                                                    0x000088b1
@@ -222,6 +231,10 @@
#define AMPERE_DMA_COPY_A                                            0x0000c6b5
#define AMPERE_DMA_COPY_B                                            0x0000c7b5

#define NVC4B7_VIDEO_ENCODER                                         0x0000c4b7
#define NVC7B7_VIDEO_ENCODER                                         0x0000c7b7
#define NVC9B7_VIDEO_ENCODER                                         0x0000c9b7

#define FERMI_DECOMPRESS                                             0x000090b8

#define NV50_COMPUTE                                                 0x000050c0
@@ -237,6 +250,14 @@
#define VOLTA_COMPUTE_A                                              0x0000c3c0
#define TURING_COMPUTE_A                                             0x0000c5c0
#define AMPERE_COMPUTE_B                                             0x0000c7c0
#define ADA_COMPUTE_A                                                0x0000c9c0

#define NV74_CIPHER                                                  0x000074c1

#define NVC4D1_VIDEO_NVJPG                                           0x0000c4d1
#define NVC9D1_VIDEO_NVJPG                                           0x0000c9d1

#define NVC6FA_VIDEO_OFA                                             0x0000c6fa
#define NVC7FA_VIDEO_OFA                                             0x0000c7fa
#define NVC9FA_VIDEO_OFA                                             0x0000c9fa
#endif
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ struct nvkm_device {
		GV100    = 0x140,
		TU100    = 0x160,
		GA100    = 0x170,
		AD100    = 0x190,
	} card_type;
	u32 chipset;
	u8  chiprev;
Loading