Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions drivers/gpu/drm/apple/dcp-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ struct apple_dcp {
enum dcp_firmware_version fw_compat;
/* Bumped by every iomfb poweron; see afk_compact_slot(). */
u32 afk_power_gen;
/* Firmware 27.x: the method IDs of this build (iomfb_v27_methods()). */
const struct dcp_method_entry *v27_methods;
bool external;
/* A desktop 26.x external processor (apple,t6041-dcpext) */
bool desktop_external;
Expand Down
21 changes: 20 additions & 1 deletion drivers/gpu/drm/apple/dcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5044,6 +5044,8 @@ static enum dcp_firmware_version dcp_check_firmware_version(struct device *dev)
const struct dcp_v14_board *v14_board;
char compat_str[DCP_FW_VERSION_STR_LEN];
char fw_str[DCP_FW_VERSION_STR_LEN];
unsigned int num_missing;
const char *missing;
int ret;

/*
Expand All @@ -5060,8 +5062,18 @@ static enum dcp_firmware_version dcp_check_firmware_version(struct device *dev)

if (hw->firmware_compat == DCP_FIRMWARE_V_27_0) {
ret = dcp_read_fw_version(dev, "apple,firmware-compat", compat_str);
if (ret < 0 || strcmp(compat_str, "27.0.0"))
if (ret < 0 || !iomfb_v27_methods(compat_str)) {
dev_err(dev, "DCP firmware-compat %s has no 27.x method table\n",
ret < 0 ? "missing" : compat_str);
return DCP_FIRMWARE_UNKNOWN;
}
missing = iomfb_v27_missing_method(iomfb_v27_methods(compat_str),
&num_missing);
if (missing) {
dev_err(dev, "DCP firmware-compat %s not started: no ID known for %u methods (first: %s)\n",
compat_str, num_missing, missing);
return DCP_FIRMWARE_UNKNOWN;
}
return DCP_FIRMWARE_V_27_0;
}

Expand Down Expand Up @@ -6174,6 +6186,13 @@ static int dcp_platform_probe_pipe(struct platform_device *pdev)
return -ENOMEM;
}
}
if (fw_compat == DCP_FIRMWARE_V_27_0) {
char compat_str[DCP_FW_VERSION_STR_LEN];

/* Checked by dcp_check_firmware_version(). */
dcp_read_fw_version(dev, "apple,firmware-compat", compat_str);
dcp->v27_methods = iomfb_v27_methods(compat_str);
}
if (fw_compat == DCP_FIRMWARE_V_26_6_DESKTOP) {
dcp->desktop = devm_kzalloc(dev, sizeof(*dcp->desktop), GFP_KERNEL);
if (!dcp->desktop)
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/apple/iomfb-peer-runtime-v27.inc
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ static void dcp_peer_started_on_owner(struct apple_dcp *owner, void *data, void
dcp_peer_swap_armed_v27(owner, id);
trace_iomfb_swap_submit(owner, id);
trace_iomfb_swap_submit(peer, id);
dcp_push(owner, false, &dcp_methods[dcpep_swap_submit], sizeof(owner->present_v27),
dcp_push(owner, false, &owner->v27_methods[dcpep_swap_submit], sizeof(owner->present_v27),
sizeof(struct dcp_swap_submit_resp_v27), &owner->present_v27,
dcp_peer_submitted, owner);
if (READ_ONCE(owner->crashed))
return;
dcp_push(peer, false, &dcp_methods[dcpep_swap_submit], sizeof(owner->peer_present_v27),
dcp_push(peer, false, &peer->v27_methods[dcpep_swap_submit], sizeof(owner->peer_present_v27),
sizeof(struct dcp_swap_submit_resp_v27), &owner->peer_present_v27,
dcp_peer_submitted, owner);
if (READ_ONCE(peer->crashed))
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/apple/iomfb.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@ struct dcp_method_entry {
char tag_h17g[4];
};

/* The IOMFB method table of a firmware 27.x build, by its compat string; NULL if unknown. */
const struct dcp_method_entry *iomfb_v27_methods(const char *compat);
/* The first method of a firmware 27.x table that has no ID, NULL if none. */
const char *iomfb_v27_missing_method(const struct dcp_method_entry *methods,
unsigned int *count);

#define IOMFB_MAX_CB (1000)

bool iomfb_validate_callback_h17p(int tag, u32 in_len, u32 out_len);
Expand Down
5 changes: 5 additions & 0 deletions drivers/gpu/drm/apple/iomfb_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -1706,6 +1706,11 @@ static void boot_5(struct apple_dcp *dcp, void *out, void *cookie)
{
#if DCP_FW_H17(DCP_FW_VER)
/* H17P expects A380 right before set_display_refresh_properties */
if (!dcp_methods[dcpep_dfb_ready_query].tag[0]) {
/* No tag is known for this firmware build: do not send one. */
boot_5b(dcp, out, cookie);
return;
}
dcp_dfb_ready_query(dcp, false, boot_5b, NULL);
#else
boot_5b(dcp, out, cookie);
Expand Down
129 changes: 128 additions & 1 deletion drivers/gpu/drm/apple/iomfb_v27.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ static_assert(offsetof(struct dcp_swap_v27, brightness_update) == 0x354);
static_assert(offsetof(struct dcp_swap_v27, brightness_nits) == 0x35e);
static_assert(sizeof(struct dcp_swap_v27) == 0x6e0);

static const struct dcp_method_entry dcp_methods[dcpep_num_methods] = {
/* Firmware 27.0, the build Aurora's t6050-gpu table was written for. */
static const struct dcp_method_entry dcp_methods_27_0[dcpep_num_methods] = {
IOMFB_METHOD("A000", dcpep_late_init_signal),
IOMFB_METHOD("A027", dcpep_setup_video_limits),
IOMFB_METHOD("A136", iomfbep_a131_pmu_service_matched),
Expand Down Expand Up @@ -113,6 +114,132 @@ static const struct dcp_method_entry dcp_methods[dcpep_num_methods] = {
IOMFB_METHOD("A483", dcpep_register_dfb_surface),
};

/*
* Firmware 27.2 renumbered the AP methods: UnifiedPipeline2 grew into
* A400/A401, so IOMobileFramebufferAP moved up by 50 (start_signal A451,
* get_color_remap_mode A477), and set_create_DFB and vi_set_temperature_hint
* up by one. The UPPipe A0xx and A1xx IDs are unchanged. The firmware rejects
* an unknown tag with a panic ("link_rpc_lookup callback not found"), so
* dfb_ready_query, whose 27.2 tag has not been seen in a call, has no entry
* here and is not sent to this build (boot_5()).
*/
static const struct dcp_method_entry dcp_methods_27_2[dcpep_num_methods] = {
IOMFB_METHOD("A000", dcpep_late_init_signal),
IOMFB_METHOD("A027", dcpep_setup_video_limits),
IOMFB_METHOD("A136", iomfbep_a131_pmu_service_matched),
IOMFB_METHOD("A137", iomfbep_a132_backlight_service_matched),
IOMFB_METHOD("A390", dcpep_set_create_dfb),
IOMFB_METHOD("A391", iomfbep_a358_vi_set_temperature_hint),
IOMFB_METHOD("A451", dcpep_start_signal),
IOMFB_METHOD("A456", dcpep_swap_start),
IOMFB_METHOD("A458", dcpep_swap_submit),
IOMFB_METHOD("A461", dcpep_set_display_device),
IOMFB_METHOD("A462", dcpep_is_main_display),
IOMFB_METHOD("A463", dcpep_set_digital_out_mode),
IOMFB_METHOD("A473", iomfbep_set_matrix),
IOMFB_METHOD("A477", iomfbep_get_color_remap_mode),
IOMFB_METHOD("A500", dcpep_set_parameter_dcp),
IOMFB_METHOD("A504", dcpep_create_default_fb),
IOMFB_METHOD("A037", dcpep_get_dfb_compression_info),
IOMFB_METHOD("A036", dcpep_get_dfb_info),
IOMFB_METHOD("A103", dcpep_get_dfb_layout),
IOMFB_METHOD("A503", dcpep_get_dfb_state),
IOMFB_METHOD("A104", dcpep_set_dfb_dimensions),
IOMFB_METHOD("A105", dcpep_commit_dfb_info),
IOMFB_METHOD("A035", dcpep_dfb_query),
IOMFB_METHOD("A353", dcpep_pipe_query_353),
IOMFB_METHOD("A352", dcpep_pipe_set_352),
IOMFB_METHOD("A465", dcpep_pipe_cfg_415),
IOMFB_METHOD("A033", dcpep_pipe_cfg_031),
IOMFB_METHOD("A464", dcpep_pipe_cfg_414),
IOMFB_METHOD("A539", dcpep_pipe_query_478),
IOMFB_METHOD("A535", dcpep_pipe_query_474),
IOMFB_METHOD("A537", dcpep_pipe_set_476),
IOMFB_METHOD("A478", iomfbep_set_brightness_correction),
IOMFB_METHOD("A508", dcpep_enable_disable_video_power_savings),
IOMFB_METHOD("A516", dcpep_first_client_open),
IOMFB_METHOD("A517", iomfbep_last_client_close),
IOMFB_METHOD("A525", dcpep_set_display_refresh_properties),
IOMFB_METHOD("A528", dcpep_flush_supports_power),
IOMFB_METHOD("A529", iomfbep_abort_swaps_dcp),
IOMFB_METHOD("A534", dcpep_set_power_state),
IOMFB_METHOD("A533", dcpep_register_dfb_surface),
};

/*
* Firmware 27.3: only the methods seen, with the request and reply sizes this
* driver uses, in a trace of the calls the macOS 27.3 display driver makes to
* the DCP of a J716s while it starts. Three are one above their 27.2 IDs
* (set_display_refresh_properties A526, flush_supports_power A529,
* register_dfb_surface A534) and create_default_fb is still A504, so 27.3 has
* one more method somewhere between those. That trace has no display client,
* so it has no mode set, swap or power state call, and the methods it does not
* show have no entry here. Until a trace shows them the table is incomplete
* and the driver does not start this firmware (iomfb_v27_missing_method()).
*/
static const struct dcp_method_entry dcp_methods_27_3[dcpep_num_methods] = {
IOMFB_METHOD("A000", dcpep_late_init_signal),
IOMFB_METHOD("A027", dcpep_setup_video_limits),
IOMFB_METHOD("A136", iomfbep_a131_pmu_service_matched),
IOMFB_METHOD("A137", iomfbep_a132_backlight_service_matched),
IOMFB_METHOD("A390", dcpep_set_create_dfb),
IOMFB_METHOD("A391", iomfbep_a358_vi_set_temperature_hint),
IOMFB_METHOD("A451", dcpep_start_signal),
IOMFB_METHOD("A504", dcpep_create_default_fb),
IOMFB_METHOD("A037", dcpep_get_dfb_compression_info),
IOMFB_METHOD("A036", dcpep_get_dfb_info),
IOMFB_METHOD("A103", dcpep_get_dfb_layout),
IOMFB_METHOD("A503", dcpep_get_dfb_state),
IOMFB_METHOD("A104", dcpep_set_dfb_dimensions),
IOMFB_METHOD("A105", dcpep_commit_dfb_info),
IOMFB_METHOD("A035", dcpep_dfb_query),
IOMFB_METHOD("A385", dcpep_dfb_ready_query),
IOMFB_METHOD("A353", dcpep_pipe_query_353),
IOMFB_METHOD("A526", dcpep_set_display_refresh_properties),
IOMFB_METHOD("A529", dcpep_flush_supports_power),
IOMFB_METHOD("A534", dcpep_register_dfb_surface),
};

const struct dcp_method_entry *iomfb_v27_methods(const char *compat)
{
if (!strcmp(compat, "27.0.0"))
return dcp_methods_27_0;
if (!strcmp(compat, "27.2.0"))
return dcp_methods_27_2;
if (!strcmp(compat, "27.3.0"))
return dcp_methods_27_3;
return NULL;
}

/*
* The driver sends every method of the 27.0 table. dfb_ready_query is the one
* it leaves out for a build whose table has no ID for it (boot_5()). Return
* the name of the first other method @methods has no ID for, with their number
* in @count, or NULL if the table is complete. A method without an ID would go
* out with an empty tag, which the firmware answers with a panic, so a build
* with an incomplete table must not be started.
*/
const char *iomfb_v27_missing_method(const struct dcp_method_entry *methods,
unsigned int *count)
{
const char *first = NULL;
unsigned int i;

*count = 0;
for (i = 0; i < dcpep_num_methods; i++) {
if (!dcp_methods_27_0[i].tag[0] || methods[i].tag[0] ||
i == dcpep_dfb_ready_query)
continue;
if (!first)
first = dcp_methods_27_0[i].name;
(*count)++;
}
return first;
}

/* The template's calls resolve through the table probe chose for this build. */
#define dcp_methods (dcp->v27_methods)

#define iomfb_modeset_h17p iomfb_modeset_v27
#define iomfb_flush_h17p iomfb_flush_v27
#define iomfb_poweron_h17p iomfb_poweron_v27
Expand Down
Loading