diff --git a/proxyclient/m1n1/proxy.py b/proxyclient/m1n1/proxy.py index 1cfff5f2b..77f62cae6 100644 --- a/proxyclient/m1n1/proxy.py +++ b/proxyclient/m1n1/proxy.py @@ -66,6 +66,11 @@ class EXC_RET(IntEnum): EXIT_GUEST = 3 STEP = 4 +class DCP_SHUTDOWN_MODE(IntEnum): + QUIESCED = 0 + SLEEP_IF_EXTERNAL = 1 + SLEEP = 2 + ExcInfo = Struct( "regs" / Array(32, Int64ul), "spsr" / RegAdapter(SPSR), @@ -1043,8 +1048,8 @@ def display_init(self): return self.request(self.P_DISPLAY_INIT) def display_configure(self, cfg): return self.request(self.P_DISPLAY_CONFIGURE, cfg) - def display_shutdown(self): - return self.request(self.P_DISPLAY_SHUTDOWN) + def display_shutdown(self, mode): + return self.request(self.P_DISPLAY_SHUTDOWN, mode) __all__.extend(k for k, v in globals().items() if (callable(v) or isinstance(v, type)) and v.__module__ == __name__) diff --git a/src/dcp.c b/src/dcp.c index dc85dc264..efa862d95 100644 --- a/src/dcp.c +++ b/src/dcp.c @@ -3,6 +3,7 @@ #include "dcp.h" #include "adt.h" #include "malloc.h" +#include "pmgr.h" #include "rtkit.h" #include "utils.h" @@ -59,9 +60,14 @@ dcp_dev_t *dcp_init(const char *dcp_path, const char *dcp_dart_path, const char return NULL; } -int dcp_shutdown(dcp_dev_t *dcp) +int dcp_shutdown(dcp_dev_t *dcp, bool sleep) { - rtkit_quiesce(dcp->rtkit); + if (sleep) { + rtkit_sleep(dcp->rtkit); + pmgr_reset(0, "DISP0_CPU0"); + } else { + rtkit_quiesce(dcp->rtkit); + } rtkit_free(dcp->rtkit); dart_shutdown(dcp->dart_disp); iovad_shutdown(dcp->iovad_dcp, dcp->dart_dcp); diff --git a/src/dcp.h b/src/dcp.h index 49532189d..c9de8f2ef 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -17,6 +17,6 @@ typedef struct { dcp_dev_t *dcp_init(const char *dcp_path, const char *dcp_dart_path, const char *disp_dart_path); -int dcp_shutdown(dcp_dev_t *dcp); +int dcp_shutdown(dcp_dev_t *dcp, bool sleep); #endif diff --git a/src/display.c b/src/display.c index 2d60c845e..d662426f9 100644 --- a/src/display.c +++ b/src/display.c @@ -22,10 +22,11 @@ continue; \ } -dcp_dev_t *dcp; -dcp_iboot_if_t *iboot; -u64 fb_dva; -u64 fb_size; +static dcp_dev_t *dcp; +static dcp_iboot_if_t *iboot; +static u64 fb_dva; +static u64 fb_size; +static bool display_is_external; #define abs(x) ((x) >= 0 ? (x) : -(x)) @@ -157,7 +158,7 @@ static uintptr_t display_map_fb(uintptr_t iova, u64 paddr, u64 size) return iova; } -static int display_start_dcp(void) +int display_start_dcp(void) { if (iboot) return 0; @@ -185,14 +186,14 @@ static int display_start_dcp(void) fb_dva = display_map_fb(0, pa, size); if (!fb_dva) { printf("display: failed to find display DVA\n"); - dcp_shutdown(dcp); + dcp_shutdown(dcp, false); return -1; } iboot = dcp_ib_init(dcp); if (!iboot) { printf("display: failed to initialize DCP iBoot interface\n"); - dcp_shutdown(dcp); + dcp_shutdown(dcp, false); return -1; } @@ -453,9 +454,24 @@ int display_configure(const char *config) int display_init(void) { + int node = adt_path_offset(adt, "/arm-io/disp0"); + + if (node < 0) { + printf("DISP0 node not found!\n"); + return -1; + } + + display_is_external = adt_getprop(adt, node, "external", NULL); + if (display_is_external) + printf("display: Display is external\n"); + else + printf("display: Display is internal\n"); + if (cur_boot_args.video.width == 640 && cur_boot_args.video.height == 1136) { printf("display: Dummy framebuffer found, initializing display\n"); - + return display_configure(NULL); + } else if (display_is_external) { + printf("display: External display found, reconfiguring\n"); return display_configure(NULL); } else { printf("display: Display is already initialized (%ldx%ld)\n", cur_boot_args.video.width, @@ -464,11 +480,27 @@ int display_init(void) } } -void display_shutdown(void) +void display_shutdown(dcp_shutdown_mode mode) { if (iboot) { dcp_ib_shutdown(iboot); - dcp_shutdown(dcp); + switch (mode) { + case DCP_QUIESCED: + printf("display: Quiescing DCP (unconditional)\n"); + dcp_shutdown(dcp, false); + break; + case DCP_SLEEP_IF_EXTERNAL: + if (!display_is_external) + printf("display: Quiescing DCP (internal)\n"); + else + printf("display: Sleeping DCP (external)\n"); + dcp_shutdown(dcp, display_is_external); + break; + case DCP_SLEEP: + printf("display: Sleeping DCP (unconditional)\n"); + dcp_shutdown(dcp, true); + break; + } iboot = NULL; } } diff --git a/src/display.h b/src/display.h index 7b2f5afd0..250d51fab 100644 --- a/src/display.h +++ b/src/display.h @@ -3,8 +3,15 @@ #ifndef DISPLAY_H #define DISPLAY_H +typedef enum _dcp_shutdown_mode { + DCP_QUIESCED = 0, + DCP_SLEEP_IF_EXTERNAL = 1, + DCP_SLEEP = 2, +} dcp_shutdown_mode; + int display_init(void); +int display_start_dcp(void); int display_configure(const char *config); -void display_shutdown(void); +void display_shutdown(dcp_shutdown_mode mode); #endif diff --git a/src/hv.c b/src/hv.c index 8b407c738..9210e5550 100644 --- a/src/hv.c +++ b/src/hv.c @@ -50,7 +50,9 @@ static struct hv_secondary_info_t hv_secondary_info; void hv_init(void) { pcie_shutdown(); - display_shutdown(); + // Make sure we wake up DCP if we put it to sleep, just quiesce it to match ADT + if (display_start_dcp() >= 0) + display_shutdown(DCP_QUIESCED); // reenable hpm interrupts for the guest for unused iodevs usb_hpm_restore_irqs(0); smp_start_secondaries(); diff --git a/src/main.c b/src/main.c index d1a2e4d98..0e419f0a7 100644 --- a/src/main.c +++ b/src/main.c @@ -132,9 +132,15 @@ void m1n1_main(void) gxf_init(); mcc_init(); mmu_init(); + aic_init(); + wdt_disable(); + pmgr_init(); #ifdef USE_FB display_init(); + // Kick DCP to sleep, so dodgy monitors which cause reconnect cycles don't cause us to lose the + // framebuffer. + display_shutdown(DCP_SLEEP_IF_EXTERNAL); fb_init(false); fb_display_logo(); #ifdef FB_SILENT_MODE @@ -144,9 +150,6 @@ void m1n1_main(void) #endif #endif - aic_init(); - wdt_disable(); - pmgr_init(); clk_init(); cpufreq_init(); sep_init(); @@ -164,7 +167,7 @@ void m1n1_main(void) nvme_shutdown(); exception_shutdown(); usb_iodev_shutdown(); - display_shutdown(); + display_shutdown(DCP_SLEEP_IF_EXTERNAL); #ifdef USE_FB fb_shutdown(next_stage.restore_logo); #endif diff --git a/src/proxy.c b/src/proxy.c index 8e68ff3d6..4208be434 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -531,7 +531,7 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply) reply->retval = display_configure((char *)request->args[0]); break; case P_DISPLAY_SHUTDOWN: - display_shutdown(); + display_shutdown(request->args[0]); break; default: