diff --git a/include/arm11/drivers/pdn.h b/include/arm11/drivers/pdn.h index 4f3f31e..9a3db1f 100644 --- a/include/arm11/drivers/pdn.h +++ b/include/arm11/drivers/pdn.h @@ -161,6 +161,8 @@ void PDN_core123Init(void); void PDN_setSocmode(PdnSocmode socmode); void PDN_poweroffCore23(void); void PDN_controlGpu(const bool enableClk, const bool resetPsc, const bool resetOther); +void PDN_sleep(void); +void PDN_wakeup(void); #ifdef __cplusplus } // extern "C" diff --git a/source/arm11/drivers/gfx.c b/source/arm11/drivers/gfx.c index e1ecc3a..f9ae2db 100644 --- a/source/arm11/drivers/gfx.c +++ b/source/arm11/drivers/gfx.c @@ -552,6 +552,8 @@ void GX_processCommandList(const u32 size, const u32 *const cmdList) void GFX_sleep(void) { + GFX_setForceBlack(true, true); + const GfxState *const state = &g_gfxState; LCD_deinit(state->mcuLcdState); @@ -567,30 +569,30 @@ void GFX_sleep(void) // Stop display controllers. stopDisplayControllersSafe(); + for(u8 i = 0; i < 6; i++) + { + unbindInterruptEvent(IRQ_PSC0 + i); + } + // Wait for at least 1 horizontal line. 40 µs in this case. // 16713.680875044929009032708 / 413 = 40.468960956525251837852 µs. // TODO: 40 µs may not be enough in legacy mode? TIMER_sleepUs(40); // Flush caches to VRAM. - flushDCacheRange((void*)VRAM_BASE, VRAM_SIZE); + flushDCacheRange((void*)VRAM_BASE, VRAM_SIZE); - // Disable VRAM banks. This is needed for PDN sleep mode. - GxRegs *const gx = getGxRegs(); - gx->psc_vram |= PSC_VRAM_BANK_DIS_ALL; - - // Stop clock. - PDN_controlGpu(false, false, false); } void GFX_sleepAwake(void) { - // Resume clock and reset PSC. - PDN_controlGpu(true, true, false); + for(u8 i = 0; i < 6; i++) + { + bindInterruptToEvent(g_gfxState.events[i], IRQ_PSC0 + i, 14); + } // Restore PSC settings. GxRegs *const gx = getGxRegs(); - gx->psc_vram &= ~PSC_VRAM_BANK_DIS_ALL; gx->gpu_clk = 0x70100; gx->psc_fill0.cnt = 0; gx->psc_fill1.cnt = 0; @@ -610,7 +612,7 @@ void GFX_sleepAwake(void) // Since both PDCs are not reset in sleep mode this is not strictly necessary. // Warning: If we decide to change this to a full reinit restore the mode! const GfxState *const state = &g_gfxState; - gx->pdc0.swap = state->swap; // Bit 1 is not writable. + gx->pdc0.swap = state->swap; // Bit 1 is not writable. gx->pdc1.swap = state->swap>>1; gx->pdc0.cnt = PDC_CNT_OUT_EN | GFX_PDC0_IRQS | PDC_CNT_EN; gx->pdc1.cnt = PDC_CNT_OUT_EN | GFX_PDC1_IRQS | PDC_CNT_EN; @@ -620,8 +622,6 @@ void GFX_sleepAwake(void) // Power on LCDs and backlights. LCD_init(state->mcuLcdState<<1, state->lcdLum); - // Active backlight and luminance stuff. - // TODO // Not from gsp. Wait for VRAM clear finish. GFX_waitForPSC0(); @@ -629,6 +629,9 @@ void GFX_sleepAwake(void) // Enable frame buffer output. GFX_setForceBlack(false, false); + + GFX_waitForVBlank0(); + GFX_waitForVBlank0(); } bool GFX_setupExceptionFrameBuffer(void) @@ -662,4 +665,4 @@ bool GFX_setupExceptionFrameBuffer(void) gx->pdc1.swap = PDC_SWAP_IRQ_ACK_ALL; // Set to single buffer mode. return true; -} \ No newline at end of file +} diff --git a/source/arm11/drivers/pdn.c b/source/arm11/drivers/pdn.c index f59b200..a4d8a0e 100644 --- a/source/arm11/drivers/pdn.c +++ b/source/arm11/drivers/pdn.c @@ -25,6 +25,8 @@ #include "arm11/start.h" #include "util.h" #include "arm11/drivers/scu.h" +#include "kevent.h" +#include "arm11/drivers/gx.h" //#define CORE123_INIT (1) @@ -212,4 +214,37 @@ void PDN_controlGpu(const bool enableClk, const bool resetPsc, const bool resetO wait_cycles(12); // 4x the needed cycles in case we are in LGR2 mode. pdn->gpu_cnt = reg | PDN_GPU_CNT_NORST_ALL; } +} + +static void pdn_isr(UNUSED u32 intSource) +{ + getPdnRegs()->wake_enable = 0; + getPdnRegs()->wake_reason = PDN_WAKE_SHELL_OPENED; +} + +void PDN_sleep(void) +{ + IRQ_registerIsr(IRQ_PDN, 14, 0, pdn_isr); + getPdnRegs()->wake_enable = PDN_WAKE_SHELL_OPENED; + + if (getPdnRegs()->cnt & PDN_CNT_VRAM_OFF) + { + // Disable VRAM banks. This is needed for PDN sleep mode. + GxRegs *const gx = getGxRegs(); + gx->psc_vram |= PSC_VRAM_BANK_DIS_ALL; + } + + getPdnRegs()->cnt |= PDN_CNT_SLEEP; + + // turning off Gpu needs to be done after sleeping + PDN_controlGpu(false, false, false); + __wfi(); +} + +void PDN_wakeup(void) +{ + PDN_controlGpu(true, true, false); + GxRegs *const gx = getGxRegs(); + gx->psc_vram &= ~PSC_VRAM_BANK_DIS_ALL; + } \ No newline at end of file