@Blackaddr - yes you might say I was a bit involved in the beta...
I guess the question is, it depends on what you are asking?
The SPI library already has support in it for DMA with the call: bool transfer(const void *txBuffer, void *rxBuffer, size_t count, EventResponderRef event_responder);
And T4 support for this was implemented as part of T4 beta.
The core files in this case hardware\teensy\avr\cores\teensy4: Does have the files DMAChannel.h/.cpp for helping with setting up DMA stuff.
Also during this time frame, we have also integrated DMA for the T4 into a few display drivers, including my own ili9341_t3n, more recently the ST7735_t3, ILI9488_t3, ...
There are some interesting complications with the T4 and DMA, depending on what type of memory you are using, more details up on the thread:
https://forum.pjrc.com/threads/57225-T4-DMA-and-Memory-DMAMEM-and-malloc-new
Put simply if you, do something like malloc a tx and rx buffer, initialize the tx buffer and setup your tx and rx DMAChannels to point to these two buffers and do a DMA operation, and then look at the returned data in rx buffer, you may find that stuff you put into the TX Buffer was not what was sent over the MOSI pin, and the data returned on the MISO pin may not be what you see when you look at it with your program.
Why? The upper 512KB of memory (OCRAM) is cached. The normal processor instructions work through the cache, while DMA works directly with the actual contents stored in memory, which if the Cache has not flushed its updated values to memory or retrieved updated values from memory when those have changed, they will be different...
There are ways to force these two cases: TX case: arm_dcache_flush(write_data, count); RX case: arm_dcache_delete(retbuf, count)
But I have had a few times I pulled out a bit of hair!