Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
c89018e
drm/apple: accept automatic PMGR activity in J613 coldplug
satchlj Oct 31, 2026
d2c35b6
drm/asahi: accept the T8122 25G83 mailbox compatible list
satchlj Oct 31, 2026
d17068f
test: vary unrelated bits in J613 PMGR state words
satchlj Oct 31, 2026
012ad6a
Merge approved DCP auto-PM and GPU mailbox prerequisites
satchlj Oct 31, 2026
2bf9dbd
drm/asahi: describe the T8122 extended firmware profile and owned IO …
satchlj Oct 31, 2026
0667ef5
drm/asahi: construct and publish extended T8122 initialization data
satchlj Oct 31, 2026
ff9acb9
drm/asahi: prepare extended firmware queues and controller handoff
satchlj Oct 31, 2026
c0184b5
drm/asahi: dispatch G15 compute through extended T8122 firmware
satchlj Oct 31, 2026
99b74c9
drm/asahi: enable J613 extended firmware render and retirement
satchlj Oct 31, 2026
8387eee
Merge GPU26 prerequisites from PRs 301-307
satchlj Nov 3, 2026
98bca8b
soc: apple: rtkit: allow receivers to observe mailbox delivery time
satchlj Nov 3, 2026
4fa282a
drm/apple: acquire the J613 native26 external power suppliers
satchlj Nov 3, 2026
056547d
drm/apple: encode J613 native26 external primary surfaces
satchlj Nov 3, 2026
2d83989
drm/apple: support retained J613 native26 external displays
satchlj Nov 3, 2026
211c943
drm/apple: test native26 wire, attachment and PM boundaries
satchlj Nov 3, 2026
9eed248
selftests: apple: refresh display and PMP host boundaries
satchlj Nov 3, 2026
953df23
selftests: apple: keep child-seeding mutant compilable
satchlj Nov 3, 2026
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
34 changes: 34 additions & 0 deletions Documentation/devicetree/bindings/display/apple,dcp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ properties:
- apple,t8112-dcp
- apple,t6000-dcp
- apple,t6020-dcp
- apple,t8122-dcp
- apple,t8140-dcp
- apple,t8142-dcp
- const: apple,dcp
Expand All @@ -32,6 +33,7 @@ properties:
- apple,t8112-dcpext
- apple,t6000-dcpext
- apple,t6020-dcpext
- apple,t8122-dcpext
- const: apple,dcpext
- items:
- const: apple,t8140-dcpext
Expand Down Expand Up @@ -180,6 +182,38 @@ properties:
maxItems: 5
description: Loader-provided firmware ABI version used for IOMFB selection.

apple,j613-25g83-dcpext-handoff:
$ref: /schemas/types.yaml#/definitions/uint32
const: 1
description: |
Loader validation of the J613 native26 external processor. Requires
the separately validated internal mapping handoff, exact 26.6.2 image,
complete stream-5 mappings and retained locked page tables. Does not
enable hardware. Firmware reservations must also be complete.

apple,j613-25g83-dcpext-boot-state:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 4
maxItems: 4
description: |
Loader observations in order of powered ancestry, ASC CPU control,
ASC CPU status and firmware-DART protection. Read only while the
processor's full power ancestry is active. A powered processor must
have protected inherited roots; this is not an RTKit readiness claim.

apple,t8122-dcpext-firmware-ready:
$ref: /schemas/types.yaml#/definitions/uint32
const: 1
description: All external firmware reservations were committed by the loader.

apple,firmware-uuid:
$ref: /schemas/types.yaml#/definitions/string
description: UUID of the actual loaded display image, read from its iop nub.

apple,pmp:
$ref: /schemas/types.yaml#/definitions/phandle
description: Native PMP supplier, independent of the report request entry.

apple,connector-type:
enum: [HDMI-A, DP, USB-C]

Expand Down
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2723,7 +2723,9 @@ F: drivers/pwm/pwm-apple.c
F: drivers/reset/reset-apple-cio.c
F: drivers/rtc/rtc-macsmc.c
F: drivers/soc/apple/*
F: tools/asahi/m3-uapi-*
F: tools/asahi/pmp-bootargs-tests.rs
F: tools/asahi/test-m3-uapi.py
F: drivers/spi/spi-apple.c
F: drivers/spmi/spmi-apple-controller.c
F: drivers/thunderbolt/.kunitconfig.apple-dpin
Expand Down
19 changes: 18 additions & 1 deletion arch/arm64/boot/dts/apple/t8122-j613-dcp-25g83.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
};

&dcpext {
/delete-property/ apple,pmp-report;
apple,pmp-report = <&pmp_report_dispext>;
apple,pmp = <&pmp>;

Check warning on line 24 in arch/arm64/boot/dts/apple/t8122-j613-dcp-25g83.dtsi

View workflow job for this annotation

GitHub Actions / ci / device trees

dt-check style

[property-order] property 'apple,pmp' out of canonical order (should sort before 'apple,pmp-report')
};

&disp0_piodma {
Expand All @@ -37,11 +38,18 @@

/* This profile requests only DISP and ANS until external admission succeeds. */
&pmp_report_dispext {
apple,soc-device-record;
status = "disabled";
};

&pmp_report_disp {
apple,soc-device-record;
};

&pmp_report_ans {
apple,soc-device-record;
apple,no-ack;

Check warning on line 51 in arch/arm64/boot/dts/apple/t8122-j613-dcp-25g83.dtsi

View workflow job for this annotation

GitHub Actions / ci / device trees

dt-check style

[property-order] property 'apple,no-ack' out of canonical order (should sort before 'apple,soc-device-record')
apple,always-on;

Check warning on line 52 in arch/arm64/boot/dts/apple/t8122-j613-dcp-25g83.dtsi

View workflow job for this annotation

GitHub Actions / ci / device trees

dt-check style

[property-order] property 'apple,always-on' out of canonical order (should sort before 'apple,no-ack')
};

&pmp_dart {
Expand Down Expand Up @@ -87,5 +95,14 @@
memory-region = <&uat_ttbs>, <&uat_pagetables>, <&uat_handoff>;
memory-region-names = "ttbs", "pagetables", "handoff";
apple,pmp = <&pmp>;
status = "disabled";

Check warning on line 98 in arch/arm64/boot/dts/apple/t8122-j613-dcp-25g83.dtsi

View workflow job for this annotation

GitHub Actions / ci / device trees

dt-check style

[required-blank-lines] "status" must be preceded by a blank line
};

/* Native26 firmware and PIODMA use the same 1-TiB alias as the panel. */
&dcpext_dart {
apple,dma-range = /bits/ 64 <0x10000000000 0x1000000000>;
};

&dispext0_dart {
apple,dma-range = /bits/ 64 <0x10000000000 0x1000000000>;
};
106 changes: 91 additions & 15 deletions drivers/gpu/drm/apple/afk.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ void afk_service_retry(struct apple_dcp_afkep *ep)
{
unsigned long flags;

if (!ep || !ep->wire_v2 || ep != ep->dcp->dcpavservep)
if (!ep || !ep->wire_v2 ||
(!dcp_is_ext26(ep->dcp) && ep != ep->dcp->dcpavservep))
return;
spin_lock_irqsave(&ep->lock, flags);
if (!ep->stopping)
Expand Down Expand Up @@ -103,6 +104,7 @@ struct apple_dcp_afkep *afk_init(struct apple_dcp *dcp, u32 endpoint,
afkep->ops = ops;
afkep->dcp = dcp;
afkep->endpoint = endpoint;
afkep->wire_v2 = dcp_is_ext26(dcp);
afkep->wq = alloc_ordered_workqueue("apple-dcp-afkep%02x",
WQ_MEM_RECLAIM, endpoint);
if (!afkep->wq) {
Expand Down Expand Up @@ -424,8 +426,12 @@ static void afk_retry_service_init(struct apple_dcp_afkep *ep)

if (!service->pending_open)
continue;
ret = ops->revalidate(service, service->pending_name,
service->pending_class, service->pending_unit);
if (dcp_is_ext26(ep->dcp) &&
(!READ_ONCE(ep->dcp->ext26_services_open) ||
(ep == ep->dcp->dptxep && !dptx_native_controllers_ready(ep->dcp))))
continue;
ret = ops->revalidate ? ops->revalidate(service, service->pending_name,
service->pending_class, service->pending_unit) : 0;
if (ret) {
afk_discard_pending_open(service);
continue;
Expand All @@ -443,8 +449,9 @@ static void afk_retry_service_init(struct apple_dcp_afkep *ep)
}
service->pending_open = false;
afk_service_publish(service);
ops->init(service, service->pending_name, service->pending_class,
service->pending_unit);
if (ops->init)
ops->init(service, service->pending_name, service->pending_class,
service->pending_unit);
if (service->enabled)
afk_populate_service_debugfs(service);
kfree(service->pending_name);
Expand Down Expand Up @@ -477,8 +484,8 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
const char *epic_name = NULL, *epic_class = NULL;
const struct apple_epic_service_ops *ops;
struct dcp_parse_ctx ctx;
u8 *props = payload + sizeof(name);
size_t props_size = payload_size - sizeof(name);
u8 *props;
size_t props_size;

previous = afk_epic_find_service(ep, channel);
/*
Expand All @@ -503,7 +510,8 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,

if (!pending->pending_open || pending->channel != channel)
continue;
if (!pending->ops->revalidate(pending, pending->pending_name,
if (!pending->ops->revalidate ||
!pending->ops->revalidate(pending, pending->pending_name,
pending->pending_class, pending->pending_unit))
return;
afk_discard_pending_open(pending);
Expand All @@ -516,6 +524,8 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
}

strscpy(name, payload, sizeof(name));
props = payload + sizeof(name);
props_size = payload_size - sizeof(name);

/*
* in DCP firmware 13.2 DCP reports interface-name as name which starts
Expand All @@ -532,8 +542,18 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
return;
}
ret = parse_epic_service_init(&ctx, &epic_name, &epic_class, &epic_unit,
ep->dcp->fw_compat == DCP_FIRMWARE_H17P);
ep->dcp->fw_compat == DCP_FIRMWARE_H17P &&
!dcp_is_ext26(ep->dcp));
if (ret) {
/* These native infrastructure reports have no EPIC identity. */
if (dcp_is_ext26(ep->dcp) && ret == -ENOENT &&
(ep->endpoint == SYSTEM_ENDPOINT ||
ep->endpoint == DISP0_ENDPOINT)) {
dev_dbg(ep->dcp->dev,
"native26 AFK ep=%#x interface=%u report=%s has no EPIC identity; ignored\n",
ep->endpoint, channel, name);
return;
}
dev_err(ep->dcp->dev,
"AFK[ep:%02x]: failed to extract init props: %d\n",
ep->endpoint, ret);
Expand All @@ -548,6 +568,10 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
ops = afk_match_service(ep, epic_name);
else
ops = afk_match_service(ep, service_name);
if (dcp_is_ext26(ep->dcp))
dev_dbg(ep->dcp->dev,
"native26 AFK identity ep=%#x interface=%u name=%s class=%s unit=%lld\n",
ep->endpoint, channel, epic_name ?: name, epic_class ?: "", epic_unit);

/* T6030 14.7: the DPAV controller endpoint binds whatever it announces. */
if (!ops && ep->dcp->fw_compat == DCP_FIRMWARE_V_14_7 && ep->ops &&
Expand All @@ -558,6 +582,9 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
ops = ep->ops;
}

if (!ops && dcp_is_ext26(ep->dcp) && ep->ops &&
!strcmp(ep->ops->name, "native26-observer"))
ops = ep->ops;
if (!ops) {
dev_err(ep->dcp->dev,
"AFK[ep:%02x]: unable to match service %s on channel %d\n",
Expand Down Expand Up @@ -588,13 +615,19 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
"AFK optional %s (%s) is unsupported on channel %u\n",
ops->name, service_name, channel);
else
dev_err(ep->dcp->dev, "AFK service %s admission failed: %d\n",
service_name, ret);
dev_err(ep->dcp->dev,
"AFK service %s admission failed: %d (ep=%#x interface=%u name=%s unit=%lld)\n",
service_name, ret, ep->endpoint, channel, epic_name ?: name, epic_unit);
afk_service_discard(service);
goto free;
}
}
if (previous && retired && ops->revalidate) {
if ((previous && retired && ops->revalidate) ||
(dcp_is_ext26(ep->dcp) &&
(!READ_ONCE(ep->dcp->ext26_services_open) ||
(ep == ep->dcp->dptxep && !dptx_native_controllers_ready(ep->dcp))))) {
/* No reader may use a native interface before its deferred OPEN. */
WRITE_ONCE(service->enabled, false);
/* Preserve the admitted identity and its original provider ticket. */
service->pending_open = true;
service->pending_name = epic_name;
Expand Down Expand Up @@ -1828,6 +1861,22 @@ static int afk_send_command_common(struct apple_epic_service *service, u8 type,
goto err_put_service;
}

if (dcp_is_ext26(ep->dcp)) {
size_t charge = ALIGN(payload_len, SZ_16K) + ALIGN(output_len, SZ_16K);

spin_lock_irqsave(&ep->lock, flags);
ret = READ_ONCE(ep->dcp->crashed) ? -EIO :
(ep->ext26_command_count >= 255 ||
charge > SZ_16M - ep->ext26_command_bytes) ? -ENOSPC : 0;
if (!ret) {
ep->ext26_command_bytes += charge;
ep->ext26_command_count++;
}
spin_unlock_irqrestore(&ep->lock, flags);
if (ret)
goto err_put_service;
}

rxbuf = dma_alloc_coherent(ep->dcp->dev, output_len, &rxbuf_dma,
GFP_KERNEL);
if (!rxbuf) {
Expand Down Expand Up @@ -1921,7 +1970,9 @@ static int afk_send_command_common(struct apple_epic_service *service, u8 type,
*/
if (!service->cmds[idx].done) {
service->cmds[idx].completion = NULL;
service->cmds[idx].free_on_ack = true;
service->cmds[idx].free_on_ack = !dcp_is_ext26(ep->dcp);
if (dcp_is_ext26(ep->dcp))
WRITE_ONCE(ep->dcp->crashed, true);
spin_unlock_irqrestore(&service->lock, flags);
dev_warn(ep->dcp->dev,
"AFK[ep:%02x]: %s (chan:%u) command type 0x%x tag 0x%04x timed out after %u ms\n",
Expand Down Expand Up @@ -1985,9 +2036,11 @@ static int afk_send_command_common(struct apple_epic_service *service, u8 type,
spin_unlock_irqrestore(&service->lock, flags);
err_free_txbuf:
kfree(inline_command);
dma_free_coherent(ep->dcp->dev, payload_len, txbuf, txbuf_dma);
if (!dcp_is_ext26(ep->dcp))
dma_free_coherent(ep->dcp->dev, payload_len, txbuf, txbuf_dma);
err_free_rxbuf:
dma_free_coherent(ep->dcp->dev, output_len, rxbuf, rxbuf_dma);
if (!dcp_is_ext26(ep->dcp))
dma_free_coherent(ep->dcp->dev, output_len, rxbuf, rxbuf_dma);
err_put_service:
afk_service_put(service);
return ret;
Expand Down Expand Up @@ -2346,3 +2399,26 @@ static void afk_remove_service_debugfs(struct apple_epic_service *srv)
#if IS_ENABLED(CONFIG_DRM_APPLE_PARSER_KUNIT_TEST)
#include "afk-parser-test.c"
#endif

/* Called after RX and the ordered endpoint worker have been joined. */
bool afk_host_idle(struct apple_dcp_afkep *ep)
{
unsigned long flags;
unsigned int i;
bool idle = true;

spin_lock_irqsave(&ep->lock, flags);
if (ep->rxbfr.ready)
idle = READ_ONCE(*ep->rxbfr.rptr) == READ_ONCE(*ep->rxbfr.wptr);
if (ep->txbfr.ready)
idle &= READ_ONCE(*ep->txbfr.rptr) == READ_ONCE(*ep->txbfr.wptr);
spin_unlock_irqrestore(&ep->lock, flags);
for (i = 0; i < AFK_MAX_CHANNEL && idle; i++) {
struct apple_epic_service *service = &ep->services[i];

spin_lock_irqsave(&service->lock, flags);
idle = bitmap_empty(service->cmd_map, MAX_PENDING_CMDS);
spin_unlock_irqrestore(&service->lock, flags);
}
return idle;
}
4 changes: 4 additions & 0 deletions drivers/gpu/drm/apple/afk.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,8 @@ struct apple_dcp_afkep {
void *bfr;
u16 bfr_tag;
size_t bfr_size;
size_t ext26_command_bytes;
unsigned int ext26_command_count;
dma_addr_t bfr_dma;

struct afk_ringbuffer txbfr;
Expand All @@ -474,6 +476,8 @@ struct apple_dcp_afkep *afk_init(struct apple_dcp *dcp, u32 endpoint,
int afk_v2_copy_owned(struct apple_epic_service *service, u64 dva,
void *buffer, size_t size, bool to_peer);
int afk_start(struct apple_dcp_afkep *ep);
/* A sampled host boundary, never a remote-producer or DMA fence. */
bool afk_host_idle(struct apple_dcp_afkep *ep);
void afk_shutdown(struct apple_dcp_afkep *ep);
void afk_quiesce(struct apple_dcp_afkep *ep);
int afk_receive_message(struct apple_dcp_afkep *ep, u64 message);
Expand Down
11 changes: 8 additions & 3 deletions drivers/gpu/drm/apple/apple_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,13 @@ static void apple_crtc_atomic_enable(struct drm_crtc *crtc,
/* A cable generation can change while the CRTC stays active. */
dcp_external_recover(to_apple_crtc(crtc)->dcp);
}
if (crtc_state->active)
dcp_crtc_atomic_modeset(crtc, commit);
if (crtc_state->active) {
ret = dcp_crtc_atomic_modeset(crtc, commit);
if (ret && dcp_is_ext26(dcp)) {
dev_err(dcp->dev, "native26 modeset failed (%d); releasing pending flip\n", ret);
goto failed;
}
}
dcp_typec_follow_done(locked);
return;

Expand Down Expand Up @@ -683,7 +688,7 @@ static int apple_probe_per_dcp(struct device *dev,
planes[zpos] = apple_plane_init(drm, 1U << num, surf,
supports_l10r,
supports_xrgb2101010,
plane_type, interchange);
plane_type, interchange, dcp_is_ext26(dcp_data));

if (IS_ERR(planes[zpos]))
return PTR_ERR(planes[zpos]);
Expand Down
Loading
Loading