From 90e66db0bb4a5356d551cc35ef63dc6ed95bfc57 Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Sun, 14 Apr 2024 12:20:31 +0900 Subject: [PATCH 1/6] Add PDN_sleep and PDN_wakeup --- include/arm11/drivers/pdn.h | 2 + kernel/include/internal/config.h | 2 +- source/arm11/drivers/gfx.c | 69 ++++++++++++++++++++++++++------ source/arm11/drivers/pdn.c | 22 ++++++++++ 4 files changed, 82 insertions(+), 13 deletions(-) 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/kernel/include/internal/config.h b/kernel/include/internal/config.h index 4606aa6..de664e2 100644 --- a/kernel/include/internal/config.h +++ b/kernel/include/internal/config.h @@ -25,7 +25,7 @@ * Maximum number of objects we can create (Slabheap). */ #define MAX_TASKS (3) // Including main and idle task. -#define MAX_EVENTS (10) +#define MAX_EVENTS (11) #define MAX_MUTEXES (3) #define MAX_SEMAPHORES (0) #define MAX_TIMERS (0) diff --git a/source/arm11/drivers/gfx.c b/source/arm11/drivers/gfx.c index e1ecc3a..aef14f1 100644 --- a/source/arm11/drivers/gfx.c +++ b/source/arm11/drivers/gfx.c @@ -550,8 +550,47 @@ void GX_processCommandList(const u32 size, const u32 *const cmdList) gx->p3d[GPUREG_CMDBUF_JUMP0] = 1; } +void GFX_enterLowPowerState(void) +{ + GFX_setForceBlack(true, true); + const GfxState *const state = &g_gfxState; + LCD_deinit(state->mcuLcdState); + stopDisplayControllersSafe(); + + for(u8 i = 0; i < 6; i++) + { + unbindInterruptEvent(IRQ_PSC0 + i); + } + + PDN_controlGpu(false, false, false); + PDN_sleep(); +} + +void GFX_returnFromLowPowerState(void) +{ + PDN_wakeup(); + PDN_controlGpu(true, false, false); + + for(u8 i = 0; i < 6; i++) + { + bindInterruptToEvent(g_gfxState.events[i], IRQ_PSC0 + i, 14); + } + + displayControllerInit(GFX_TOP_2D); + const GfxState *const state = &g_gfxState; + + LCD_init(state->mcuLcdState<<1, state->lcdLum); + GFX_setForceBlack(false, false); + + GFX_waitForVBlank0(); + GFX_waitForVBlank0(); +} + + void GFX_sleep(void) { + GFX_setForceBlack(true, true); + const GfxState *const state = &g_gfxState; LCD_deinit(state->mcuLcdState); @@ -567,6 +606,11 @@ 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? @@ -581,13 +625,20 @@ void GFX_sleep(void) // Stop clock. PDN_controlGpu(false, false, false); + PDN_sleep(); } void GFX_sleepAwake(void) { + PDN_wakeup(); // 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; @@ -605,23 +656,14 @@ void GFX_sleepAwake(void) // TODO: Do we need the PPF hardware bug workaround here too? // Since PPF is not being reset i don't think so? - // Initialize display controllers. - // gsp does completely reinitialize both display controllers here. - // 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->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; + displayControllerInit(GFX_TOP_2D); // TODO: Enable 3D LED if needed. // Power on LCDs and backlights. + const GfxState *const state = &g_gfxState; 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 +671,9 @@ void GFX_sleepAwake(void) // Enable frame buffer output. GFX_setForceBlack(false, false); + + GFX_waitForVBlank0(); + GFX_waitForVBlank0(); } bool GFX_setupExceptionFrameBuffer(void) @@ -662,4 +707,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..eaeb47a 100644 --- a/source/arm11/drivers/pdn.c +++ b/source/arm11/drivers/pdn.c @@ -25,6 +25,7 @@ #include "arm11/start.h" #include "util.h" #include "arm11/drivers/scu.h" +#include "kevent.h" //#define CORE123_INIT (1) @@ -212,4 +213,25 @@ 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; } +} + +void PDN_sleep(void) +{ + getPdnRegs()->wake_enable = PDN_WAKE_SHELL_OPENED; + getPdnRegs()->cnt |= PDN_CNT_SLEEP; +} + +void PDN_wakeup(void) +{ + static KHandle pdnWakeEvent; + if (!pdnWakeEvent) + { + pdnWakeEvent = createEvent(true); + } + + bindInterruptToEvent(pdnWakeEvent, IRQ_PDN, 14); + waitForEvent(pdnWakeEvent); + getPdnRegs()->wake_enable = 0; + getPdnRegs()->wake_reason = PDN_WAKE_SHELL_OPENED; + unbindInterruptEvent(IRQ_PDN); } \ No newline at end of file From d7a30661c975cb398c4f7da021f431d9fb729fc7 Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Mon, 22 Apr 2024 13:08:01 +0900 Subject: [PATCH 2/6] remove extra methods GFX_enterLowPowerState and GFX_returnFromLowPowerState was introduced because the branch was based on old commmit --- source/arm11/drivers/gfx.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/source/arm11/drivers/gfx.c b/source/arm11/drivers/gfx.c index aef14f1..9c67f5e 100644 --- a/source/arm11/drivers/gfx.c +++ b/source/arm11/drivers/gfx.c @@ -550,43 +550,6 @@ void GX_processCommandList(const u32 size, const u32 *const cmdList) gx->p3d[GPUREG_CMDBUF_JUMP0] = 1; } -void GFX_enterLowPowerState(void) -{ - GFX_setForceBlack(true, true); - const GfxState *const state = &g_gfxState; - LCD_deinit(state->mcuLcdState); - stopDisplayControllersSafe(); - - for(u8 i = 0; i < 6; i++) - { - unbindInterruptEvent(IRQ_PSC0 + i); - } - - PDN_controlGpu(false, false, false); - PDN_sleep(); -} - -void GFX_returnFromLowPowerState(void) -{ - PDN_wakeup(); - PDN_controlGpu(true, false, false); - - for(u8 i = 0; i < 6; i++) - { - bindInterruptToEvent(g_gfxState.events[i], IRQ_PSC0 + i, 14); - } - - displayControllerInit(GFX_TOP_2D); - const GfxState *const state = &g_gfxState; - - LCD_init(state->mcuLcdState<<1, state->lcdLum); - GFX_setForceBlack(false, false); - - GFX_waitForVBlank0(); - GFX_waitForVBlank0(); -} - - void GFX_sleep(void) { GFX_setForceBlack(true, true); From 418fb4b59741f61d7439ae3a854631b2c88b201d Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Sat, 27 Apr 2024 14:06:44 +0900 Subject: [PATCH 3/6] Don't reinit PDC --- source/arm11/drivers/gfx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/arm11/drivers/gfx.c b/source/arm11/drivers/gfx.c index 9c67f5e..d1c9f58 100644 --- a/source/arm11/drivers/gfx.c +++ b/source/arm11/drivers/gfx.c @@ -619,12 +619,19 @@ void GFX_sleepAwake(void) // TODO: Do we need the PPF hardware bug workaround here too? // Since PPF is not being reset i don't think so? - displayControllerInit(GFX_TOP_2D); + // Initialize display controllers. + // gsp does completely reinitialize both display controllers here. + // 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->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; // TODO: Enable 3D LED if needed. // Power on LCDs and backlights. - const GfxState *const state = &g_gfxState; LCD_init(state->mcuLcdState<<1, state->lcdLum); From 871d9ca5f3a6fa8152c73f98d70e788b8d17e05e Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Sat, 27 Apr 2024 15:19:09 +0900 Subject: [PATCH 4/6] Modify gfx and pdn sleep mode PDN_sleep now blocks. Also, controlling pdn is now done in pdn.c instead of gfx.c --- source/arm11/drivers/gfx.c | 7 ------- source/arm11/drivers/pdn.c | 27 ++++++++++++++++----------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/source/arm11/drivers/gfx.c b/source/arm11/drivers/gfx.c index d1c9f58..8c921df 100644 --- a/source/arm11/drivers/gfx.c +++ b/source/arm11/drivers/gfx.c @@ -586,17 +586,10 @@ void GFX_sleep(void) GxRegs *const gx = getGxRegs(); gx->psc_vram |= PSC_VRAM_BANK_DIS_ALL; - // Stop clock. - PDN_controlGpu(false, false, false); - PDN_sleep(); } void GFX_sleepAwake(void) { - PDN_wakeup(); - // 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); diff --git a/source/arm11/drivers/pdn.c b/source/arm11/drivers/pdn.c index eaeb47a..6662733 100644 --- a/source/arm11/drivers/pdn.c +++ b/source/arm11/drivers/pdn.c @@ -215,23 +215,28 @@ void PDN_controlGpu(const bool enableClk, const bool resetPsc, const bool resetO } } +static void my_isr(u32 intSource) { + getPdnRegs()->wake_enable = 0; + getPdnRegs()->wake_reason = PDN_WAKE_SHELL_OPENED; +} + void PDN_sleep(void) { + IRQ_registerIsr(IRQ_PDN, 14, 0, my_isr); getPdnRegs()->wake_enable = PDN_WAKE_SHELL_OPENED; + getPdnRegs()->cnt |= PDN_CNT_SLEEP; -} -void PDN_wakeup(void) -{ - static KHandle pdnWakeEvent; - if (!pdnWakeEvent) - { - pdnWakeEvent = createEvent(true); - } + // turning off Gpu needs to be done after sleeping + PDN_controlGpu(false, false, false); + + __wfi(); - bindInterruptToEvent(pdnWakeEvent, IRQ_PDN, 14); - waitForEvent(pdnWakeEvent); getPdnRegs()->wake_enable = 0; getPdnRegs()->wake_reason = PDN_WAKE_SHELL_OPENED; - unbindInterruptEvent(IRQ_PDN); +} + +void PDN_wakeup(void) +{ + PDN_controlGpu(true, true, false); } \ No newline at end of file From b8bd80073dd69978c30541c47d851d0e8f4da02e Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Sat, 27 Apr 2024 15:50:59 +0900 Subject: [PATCH 5/6] cleanup --- source/arm11/drivers/gfx.c | 7 +------ source/arm11/drivers/pdn.c | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/source/arm11/drivers/gfx.c b/source/arm11/drivers/gfx.c index 8c921df..69ef27a 100644 --- a/source/arm11/drivers/gfx.c +++ b/source/arm11/drivers/gfx.c @@ -580,11 +580,7 @@ void GFX_sleep(void) TIMER_sleepUs(40); // Flush caches to VRAM. - 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; + flushDCacheRange((void*)VRAM_BASE, VRAM_SIZE); } @@ -597,7 +593,6 @@ void GFX_sleepAwake(void) // 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; diff --git a/source/arm11/drivers/pdn.c b/source/arm11/drivers/pdn.c index 6662733..a4d8a0e 100644 --- a/source/arm11/drivers/pdn.c +++ b/source/arm11/drivers/pdn.c @@ -26,6 +26,7 @@ #include "util.h" #include "arm11/drivers/scu.h" #include "kevent.h" +#include "arm11/drivers/gx.h" //#define CORE123_INIT (1) @@ -215,28 +216,35 @@ void PDN_controlGpu(const bool enableClk, const bool resetPsc, const bool resetO } } -static void my_isr(u32 intSource) { +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, my_isr); + 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(); - - getPdnRegs()->wake_enable = 0; - getPdnRegs()->wake_reason = PDN_WAKE_SHELL_OPENED; } 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 From 8f93afdf821a32ea848eedee48a771099d131ae1 Mon Sep 17 00:00:00 2001 From: Evans Jahja Date: Sat, 27 Apr 2024 15:55:29 +0900 Subject: [PATCH 6/6] revert unused stuffs back to base branch --- kernel/include/internal/config.h | 2 +- source/arm11/drivers/gfx.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/kernel/include/internal/config.h b/kernel/include/internal/config.h index de664e2..4606aa6 100644 --- a/kernel/include/internal/config.h +++ b/kernel/include/internal/config.h @@ -25,7 +25,7 @@ * Maximum number of objects we can create (Slabheap). */ #define MAX_TASKS (3) // Including main and idle task. -#define MAX_EVENTS (11) +#define MAX_EVENTS (10) #define MAX_MUTEXES (3) #define MAX_SEMAPHORES (0) #define MAX_TIMERS (0) diff --git a/source/arm11/drivers/gfx.c b/source/arm11/drivers/gfx.c index 69ef27a..f9ae2db 100644 --- a/source/arm11/drivers/gfx.c +++ b/source/arm11/drivers/gfx.c @@ -607,15 +607,15 @@ void GFX_sleepAwake(void) // TODO: Do we need the PPF hardware bug workaround here too? // Since PPF is not being reset i don't think so? - // Initialize display controllers. - // gsp does completely reinitialize both display controllers here. - // 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->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; + // Initialize display controllers. + // gsp does completely reinitialize both display controllers here. + // 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->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; // TODO: Enable 3D LED if needed.