mirror of
https://github.com/AsahiLinux/m1n1
synced 2024-11-10 09:44:13 +00:00
display: Put DCP to sleep if display is external
This stops DCP from killing our modeset if the connection cycles. Also force a (potential) configure cycle if the display is external; this makes sure updated stage2s will have a chance at fixing issues of old stage1s. Modesetting is fast when it's the same mode as before. Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
parent
9748b5525e
commit
714420a694
8 changed files with 77 additions and 22 deletions
|
@ -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 @@ class M1N1Proxy(Reloadable):
|
|||
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__)
|
||||
|
|
10
src/dcp.c
10
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 @@ out_free:
|
|||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
4
src/hv.c
4
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();
|
||||
|
|
11
src/main.c
11
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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue