display: Use dcpext0 for HDMI out on t8112/t6020/t6021

dcpext0 behaves like dcp on M1* devices and can sleep after display
init. This has the advantage of not breaking macOS when starting with an
initialized display.
dcpext* are according to Apple's tech specs slightly more powerful than
dcp. They are advertised as 6K at 60Hz while dcp seems to be limited to
5K at 60Hz.

Signed-off-by: Janne Grunau <j@jannau.net>
This commit is contained in:
Janne Grunau 2023-11-26 10:37:04 +01:00 committed by Hector Martin
parent 5245fc6a58
commit 5006e083c7
5 changed files with 41 additions and 29 deletions

View file

@ -204,12 +204,7 @@ out_free:
int dcp_shutdown(dcp_dev_t *dcp, bool sleep)
{
if (dcp->dptx_ep) {
if (sleep) {
printf("DCP: dcp_shutdown(sleep=true) is broken with dptx-port, quiesce instead\n");
sleep = false;
}
}
/* dcp/dcp0 on desktop M2 and M2 Pro/Max devices do not wake from sleep */
dcp_system_shutdown(dcp->system_ep);
dcp_dptx_shutdown(dcp->dptx_ep);
dcp_dpav_shutdown(dcp->dpav_ep);

View file

@ -19,6 +19,7 @@ typedef struct {
const char dptx_phy[24];
const char dp2hdmi_gpio[24];
const char pmgr_dev[24];
const char dcp_alias[8];
u32 dcp_index;
u8 num_dptxports;
u8 die;

View file

@ -37,41 +37,49 @@ static const display_config_t display_config_m1 = {
.dcp_dart = "/arm-io/dart-dcp",
.disp_dart = "/arm-io/dart-disp0",
.pmgr_dev = "DISP0_CPU0",
.dcp_alias = "dcp",
};
#define USE_DCPEXT 1
static const display_config_t display_config_m2 = {
#if USE_DCPEXT
.dcp = "/arm-io/dcpext",
.dcp_dart = "/arm-io/dart-dcpext",
.disp_dart = "/arm-io/dart-dispext0",
.pmgr_dev = "DISPEXT_CPU0",
.dcp_alias = "dcpext",
.dcp_index = 1,
#else
.dcp = "/arm-io/dcp",
.dcp_dart = "/arm-io/dart-dcp",
.disp_dart = "/arm-io/dart-disp0",
.dp2hdmi_gpio = "/arm-io/dp2hdmi-gpio",
.dptx_phy = "/arm-io/dptx-phy",
.pmgr_dev = "DISP0_CPU0",
.dcp_alias = "dcp",
.dcp_index = 0,
#endif
.dp2hdmi_gpio = "/arm-io/dp2hdmi-gpio",
.dptx_phy = "/arm-io/dptx-phy",
.num_dptxports = 2,
};
#define T6020_T6021_USE_DCPEXT 255
static const display_config_t display_config_m2_pro_max = {
#if T6020_T6021_USE_DCPEXT == 0
#if USE_DCPEXT
.dcp = "/arm-io/dcpext0",
.dcp_dart = "/arm-io/dart-dcpext0",
.disp_dart = "/arm-io/dart-dispext0",
.pmgr_dev = "DISPEXT0_CPU0",
.dcp_alias = "dcpext0",
.dcp_index = 1,
.num_dptxports = 2,
#elif T6020_T6021_USE_DCPEXT == 1
.dcp = "/arm-io/dcpext1",
.dcp_dart = "/arm-io/dart-dcpext1",
.disp_dart = "/arm-io/dart-dispext1",
.pmgr_dev = "DISPEXT1_CPU0",
.dcp_index = 2,
.num_dptxports = 2,
#else
.dcp = "/arm-io/dcp0",
.dcp_dart = "/arm-io/dart-dcp0",
.disp_dart = "/arm-io/dart-disp0",
.pmgr_dev = "DISP0_CPU0",
.dcp_alias = "dcp",
.dcp_index = 0,
.num_dptxports = 1,
#endif
@ -86,6 +94,7 @@ static const display_config_t display_config_m2_ultra = {
.dp2hdmi_gpio = "/arm-io/dp2hdmi-gpio1",
.dptx_phy = "/arm-io/lpdptx-phy1",
.pmgr_dev = "DISPEXT4_CPU0",
.dcp_alias = "dcpext4",
.dcp_index = 1,
.num_dptxports = 2,
.die = 1,
@ -222,6 +231,18 @@ static uintptr_t display_map_fb(uintptr_t iova, u64 paddr, u64 size)
return iova;
}
const display_config_t *display_get_config(void)
{
if (adt_is_compatible(adt, 0, "J473AP"))
return &display_config_m2;
else if (adt_is_compatible(adt, 0, "J474sAP") || adt_is_compatible(adt, 0, "J475cAP"))
return &display_config_m2_pro_max;
else if (adt_is_compatible(adt, 0, "J180dAP") || adt_is_compatible(adt, 0, "J475dAP"))
return &display_config_m2_ultra;
else
return &display_config_m1;
}
int display_start_dcp(void)
{
if (iboot)
@ -232,14 +253,7 @@ int display_start_dcp(void)
return 0;
#endif
const display_config_t *disp_cfg = &display_config_m1;
if (adt_is_compatible(adt, 0, "J473AP"))
disp_cfg = &display_config_m2;
else if (adt_is_compatible(adt, 0, "J474sAP") || adt_is_compatible(adt, 0, "J475cAP"))
disp_cfg = &display_config_m2_pro_max;
else if (adt_is_compatible(adt, 0, "J180dAP") || adt_is_compatible(adt, 0, "J475dAP"))
disp_cfg = &display_config_m2_ultra;
const display_config_t *disp_cfg = display_get_config();
display_is_dptx = !!disp_cfg->dptx_phy[0];

View file

@ -3,6 +3,7 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include "dcp.h"
#include "types.h"
typedef enum _dcp_shutdown_mode {
@ -17,5 +18,6 @@ int display_init(void);
int display_start_dcp(void);
int display_configure(const char *config);
void display_shutdown(dcp_shutdown_mode mode);
const display_config_t *display_get_config(void);
#endif

View file

@ -8,6 +8,7 @@
#include "clk.h"
#include "dapf.h"
#include "devicetree.h"
#include "display.h"
#include "exception.h"
#include "firmware.h"
#include "isp.h"
@ -1774,7 +1775,6 @@ static int dt_set_display(void)
* they are missing. */
int ret = 0;
char dcp_alias[8] = "dcp";
if (!fdt_node_check_compatible(dt, 0, "apple,t8103")) {
ret = dt_carveout_reserved_regions("dcp", "disp0", "disp0_piodma",
@ -1818,9 +1818,7 @@ static int dt_set_display(void)
if (ret)
return ret;
} else if (!fdt_node_check_compatible(dt, 0, "apple,t6022")) {
// Set dcp_alias to "dcpext4" on M2 Ultra, cmp. display.c
strncpy(dcp_alias, "dcpext4", sizeof(dcp_alias));
dcp_alias[sizeof(dcp_alias) - 1] = '\0';
/* noop */
} else {
printf("FDT: unknown compatible, skip display reserved-memory setup\n");
return 0;
@ -1838,7 +1836,9 @@ static int dt_set_display(void)
!fdt_node_check_compatible(dt, 0, "apple,t6022"))
dt_reserve_dcpext_firmware();
return dt_vram_reserved_region(dcp_alias, "disp0");
const display_config_t *disp_cfg = display_get_config();
return dt_vram_reserved_region(disp_cfg->dcp_alias, "disp0");
}
static int dt_set_sio_fwdata(void)