The PGRAPH is the engine of the GPU that actually performs graphics operations like blitting and drawing triangles. It can be programmed by directly writing to its registers in MMIO space or by feeding commands through the PFIFO engine.
Basically, PGRAPH should be seen as a pipeline that is fed by the PFIFO CACHE.
The dispatch in PGRAPH is mainly done by dedicated PGRAPH_DISPATCH engine, which checks the commands and forwards them to the right subengine. As PGRAPH is a pipeline it doesn't end here, The subengines all dispatch stuff to one another:
Confusing enough already? The above list only mentions less than half of involved PGRAPH units :)
You'll find the register map here:
To pause the PGRAPH, you need to play with the PULL(bit 0) bit of the CONTROL(0x400500) register.
Clearing it will prevent PGRAPH from pulling commands from the PFIFO which will then starve of commands --> paused!
We also need to set the bit UNK16(bit 16) because otherwise, PGRAPH could be stuck in a ctxprog context switch or an m2mf memory transfer. Anyway, this bit should already been set.
We now need to wait for PGRAPH to actually pause.
The blob first checks on these registers (wait for them to come to 0):
Then, you'll need to wait for the STATUS(0x400700) register's bit ALL(bit 0) to go down to 0.
Un-pausing is done by setting the PULL(bit 0) bit of the CONTROL(0x400500) register. Remember to also set the bit UNK16(bit 16).