diff --git a/arch/arm64/boot/dts/apple/t8122-j504.dts b/arch/arm64/boot/dts/apple/t8122-j504.dts index 4c36e01bae6412..818ab8d786b7b7 100644 --- a/arch/arm64/boot/dts/apple/t8122-j504.dts +++ b/arch/arm64/boot/dts/apple/t8122-j504.dts @@ -31,6 +31,26 @@ }; }; +&dcp { + panel: panel { + compatible = "apple,panel-j504", "apple,panel-mini-led", "apple,panel"; + /* + * The J514S panel: 3024x1964 at 254 ppi; 189 mm high without the + * 74 notch rows. The J504 boot framebuffer is 3024x1890 below them. + */ + width-mm = <302>; + height-mm = <196>; + adj-height-mm = <189>; + apple,max-brightness = <500>; + }; +}; + +/* The boot framebuffer is the same panel, as on the J613 (HiDPI scale for simpledrm). */ +&framebuffer0 { + panel = <&panel>; + post-init-providers = <&panel>; +}; + &wifi0 { brcm,board-type = "apple,tresco"; }; diff --git a/drivers/gpu/drm/apple/iomfb_v14_7.c b/drivers/gpu/drm/apple/iomfb_v14_7.c index e540ba355f8298..6a20b9add7b3bb 100644 --- a/drivers/gpu/drm/apple/iomfb_v14_7.c +++ b/drivers/gpu/drm/apple/iomfb_v14_7.c @@ -140,6 +140,31 @@ static const struct dcp_v14_board dcp_v14_board_j615 = { .ctm_get = A(420), }; +/* + * J504 (MacBook Pro 14", M3): the J613 DCP image on the same T8122 DCP (the + * J504 ADT names it), driving the 14" mini-LED panel of the J514S: 3024x1964 + * with 74 notch rows above the 3024x1890 boot framebuffer, at 60 or 120 Hz. + * The colour matrix methods are this image's, and so is the panel level + * block the J613 qualified (brightness in nits, 500 at most here). Its swaps + * keep zero timestamps as on the Airs. Every panel timing and the + * display clock are logged for the first boots. + */ +static const struct dcp_v14_board dcp_v14_board_j504 = { + .name = "J504", + .debugfs = "dcp-j504", + .dcp_compatible = "apple,t8122-dcp", + .machine = "apple,j504", + .firmware_uuid = DCP_V14_J613_FIRMWARE_UUID, + .handoff = "apple,t8122-handoff", + .panel_width = 3024, + .panel_height = 1964, + .promotion = true, + .log_bringup = true, + .panel_nits = true, + .ctm_set = A(421), + .ctm_get = A(420), +}; + /* * J516C (MacBook Pro 16", M3 Max): the J516S panel, 3456x2234 with 74 notch * rows above the 3456x2160 boot framebuffer, at 60 or 120 Hz, on the T6031 @@ -194,6 +219,7 @@ static const struct dcp_v14_board *const dcp_v14_boards[] = { &dcp_v14_board_t6030, &dcp_v14_board_j613, &dcp_v14_board_j615, + &dcp_v14_board_j504, &dcp_v14_board_j516c, &dcp_v14_board_j514c, }; @@ -1698,7 +1724,8 @@ static bool dcp_v14_panel_nits_admit(const struct dcp_v14_board *board, { return board && board->panel_nits && (machine_is(ctx, "apple,j514s") || machine_is(ctx, "apple,j516s") || - machine_is(ctx, "apple,j516c") || machine_is(ctx, "apple,j613")); + machine_is(ctx, "apple,j516c") || machine_is(ctx, "apple,j613") || + machine_is(ctx, "apple,j504")); } const char *iomfb_v14_7_board_name(const struct dcp_v14_board *board) diff --git a/drivers/gpu/drm/apple/iomfb_v14_7_backlight_test.c b/drivers/gpu/drm/apple/iomfb_v14_7_backlight_test.c index 3c1fc2f45d534e..6f1b6ad2bfe967 100644 --- a/drivers/gpu/drm/apple/iomfb_v14_7_backlight_test.c +++ b/drivers/gpu/drm/apple/iomfb_v14_7_backlight_test.c @@ -122,13 +122,14 @@ static bool v14_bl_ctx_machine_is(const void *ctx, const char *compat) return !strcmp(((const char *const *)ctx)[1], compat); } -/* Only admitted T6030, J516C and J613 internal panels carry levels. */ +/* Only admitted T6030, J516C, J613 and J504 internal panels carry levels. */ static void v14_bl_boards(struct kunit *test) { static const char *const t6030_j516s[] = { "apple,t6030-dcp", "apple,j516s" }; static const char *const t6030_j514s[] = { "apple,t6030-dcp", "apple,j514s" }; static const char *const j613[] = { "apple,t8122-dcp", "apple,j613" }; static const char *const j615[] = { "apple,t8122-dcp", "apple,j615" }; + static const char *const j504[] = { "apple,t8122-dcp", "apple,j504" }; static const char *const j516c[] = { "apple,t6031-dcp", "apple,j516c" }; static const char *const other_t6030[] = { "apple,t6030-dcp", "apple,other" }; const struct dcp_v14_board *board; @@ -156,6 +157,11 @@ static void v14_bl_boards(struct kunit *test) board = dcp_v14_board_select(v14_bl_ctx_dcp_is, v14_bl_ctx_machine_is, j615, &known); KUNIT_ASSERT_NOT_NULL(test, board); KUNIT_EXPECT_FALSE(test, board->panel_nits); + board = dcp_v14_board_select(v14_bl_ctx_dcp_is, v14_bl_ctx_machine_is, j504, &known); + KUNIT_ASSERT_NOT_NULL(test, board); + KUNIT_EXPECT_TRUE(test, board->panel_nits); + KUNIT_EXPECT_TRUE(test, dcp_v14_panel_nits_admit(board, v14_bl_ctx_machine_is, j504)); + KUNIT_EXPECT_FALSE(test, dcp_v14_panel_nits_admit(board, v14_bl_ctx_machine_is, j615)); board = dcp_v14_board_select(v14_bl_ctx_dcp_is, v14_bl_ctx_machine_is, j516c, &known); KUNIT_ASSERT_NOT_NULL(test, board); KUNIT_EXPECT_TRUE(test, board->panel_nits); diff --git a/drivers/gpu/drm/apple/v14-board-test.c b/drivers/gpu/drm/apple/v14-board-test.c index 98df7dfab36ea8..f6202c07e39b03 100644 --- a/drivers/gpu/drm/apple/v14-board-test.c +++ b/drivers/gpu/drm/apple/v14-board-test.c @@ -54,6 +54,8 @@ static const char *const j514c[] = { "apple,j514c", "apple,t6031", "apple,arm-pl static const char *const j516m[] = { "apple,j516m", "apple,t6034", "apple,arm-platform", NULL }; static const char *const j516s[] = { "apple,j516s", "apple,t6030", "apple,arm-platform", NULL }; static const char *const j613[] = { "apple,j613", "apple,t8122", "apple,arm-platform", NULL }; +static const char *const j504[] = { "apple,j504", "apple,t8122", "apple,arm-platform", NULL }; +static const char *const j433[] = { "apple,j433", "apple,t8122", "apple,arm-platform", NULL }; static void v14_board_j516c(struct kunit *test) { @@ -252,7 +254,46 @@ static void v14_swap_timestamps_encoding(struct kunit *test) } } +/* + * J504 (14" M3 MacBook Pro): the J613 image on the T8122 DCP, its own 3024x1964 + * ProMotion panel, the qualified level block (brightness) and unstamped swaps. The other T8122 + * Macs (J433, J434) have no record. + */ +static void v14_board_j504(struct kunit *test) +{ + const struct dcp_v14_board *b, *air; + bool known; + + b = board_for("apple,t8122-dcp", j504, &known); + KUNIT_ASSERT_NOT_NULL(test, b); + air = board_for("apple,t8122-dcp", j613, &known); + KUNIT_ASSERT_NOT_NULL(test, air); + KUNIT_EXPECT_PTR_NE(test, b, air); + KUNIT_EXPECT_STREQ(test, b->name, "J504"); + KUNIT_EXPECT_STREQ(test, b->machine, "apple,j504"); + KUNIT_EXPECT_STREQ(test, b->handoff, "apple,t8122-handoff"); + KUNIT_EXPECT_STREQ(test, b->firmware_uuid, J613_DCP_IMAGE); + KUNIT_EXPECT_EQ(test, b->panel_width, 3024); + KUNIT_EXPECT_EQ(test, b->panel_height, 1964); + KUNIT_EXPECT_TRUE(test, b->promotion); + KUNIT_EXPECT_TRUE(test, b->log_bringup); + KUNIT_EXPECT_TRUE(test, b->panel_nits); + KUNIT_EXPECT_FALSE(test, b->base_edid); + KUNIT_EXPECT_EQ(test, b->ctm_set, air->ctm_set); + KUNIT_EXPECT_EQ(test, b->ctm_get, air->ctm_get); + KUNIT_EXPECT_TRUE(test, dcp_v14_board_admits(b, J613_DCP_IMAGE)); + KUNIT_EXPECT_FALSE(test, dcp_v14_board_admits(b, T6030_DCP_IMAGE)); + KUNIT_EXPECT_FALSE(test, dcp_v14_board_admits(b, J516C_DCP_IMAGE)); + KUNIT_EXPECT_FALSE(test, dcp_v14_board_stamps_swaps(b, false)); + + KUNIT_EXPECT_NULL(test, board_for("apple,t8122-dcp", j433, &known)); + KUNIT_EXPECT_TRUE(test, known); + /* A J504 root with another SoC's DCP gets no J504 record. */ + KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", j504, &known)); +} + static struct kunit_case v14_board_cases[] = { + KUNIT_CASE(v14_board_j504), KUNIT_CASE(v14_board_j516c), KUNIT_CASE(v14_board_j514c), KUNIT_CASE(v14_board_t6031_other_boards), diff --git a/drivers/gpu/drm/asahi/m3/m3_params.rs b/drivers/gpu/drm/asahi/m3/m3_params.rs index 8167c6c3ec05c4..b6dbb6726a004f 100644 --- a/drivers/gpu/drm/asahi/m3/m3_params.rs +++ b/drivers/gpu/drm/asahi/m3/m3_params.rs @@ -589,9 +589,9 @@ pub(crate) fn thermal_hot_param() -> (u64, bool) { /// Whether to start the runtime backend on a T8122 (`asahi.m3_backend`), and say why not. /// -/// The runtime starts only on the boards the T8122 table allows (the M3 MacBook Airs), with -/// `auto` and `runtime` alike: it has not run on any T8122, so nothing forces it onto another -/// board. The G15 manager backend is T6030-only. +/// The runtime starts only on the boards the T8122 table allows (the M3 MacBook Airs and the +/// 14" M3 MacBook Pro, `t8122_admission::T8122_BOARDS`), with `auto` and `runtime` alike: +/// nothing forces it onto another board. The G15 manager backend is T6030-only. pub(crate) fn t8122_backend(pdev: &platform::Device>) -> bool { let dev = pdev.as_ref(); match M3_BACKEND.load(Ordering::Relaxed) { @@ -610,7 +610,7 @@ pub(crate) fn t8122_backend(pdev: &platform::Device>) -> bool { _ => { dev_info!( dev, - "M3: no GPU backend on this T8122 board: the runtime backend may start only on the M3 MacBook Airs (J613, J615)\n" + "M3: no GPU backend on this T8122 board: the runtime backend may start only on the M3 MacBook Airs (J613, J615) and the 14\" M3 MacBook Pro (J504)\n" ); false } diff --git a/drivers/gpu/drm/asahi/m3/m3_soc.rs b/drivers/gpu/drm/asahi/m3/m3_soc.rs index 4b81475612b6fa..6a1f08fd852530 100644 --- a/drivers/gpu/drm/asahi/m3/m3_soc.rs +++ b/drivers/gpu/drm/asahi/m3/m3_soc.rs @@ -284,9 +284,10 @@ pub(crate) static T8122: Soc = Soc { gpu_revision_id: hw::GpuRevisionID::C0, board: "apple,t8122", gpu: "apple,agx-t8122", - // The M3 MacBook Airs (13" J613, 15" J615). Allowed, not validated: the runtime has not run - // on either, and starts only behind a boot loader that hands the GPU over. - validated_boards: &[b"apple,j613", b"apple,j615"], + // The M3 MacBook Airs (13" J613, 15" J615) and the 14" M3 MacBook Pro (J504), which loads + // the same G15G image (`t8122_admission::T8122_BOARDS`). The runtime starts only behind a + // boot loader that hands the GPU over. + validated_boards: &crate::m3::t8122_admission::T8122_BOARDS, clusters: 1, cores_per_cluster: 10, mailbox_compatibles: &[ diff --git a/drivers/gpu/drm/asahi/m3/m3_thermal_policy.rs b/drivers/gpu/drm/asahi/m3/m3_thermal_policy.rs index 11901c94056256..f7aa8120b25aaf 100644 --- a/drivers/gpu/drm/asahi/m3/m3_thermal_policy.rs +++ b/drivers/gpu/drm/asahi/m3/m3_thermal_policy.rs @@ -269,6 +269,7 @@ mod zone_tests { } assert_eq!(required_zones(b"apple,j613\0"), 1); assert_eq!(required_zones(b"apple,j615\0"), 1); + assert_eq!(required_zones(b"apple,j504\0apple,t8122\0"), 1); } #[test] diff --git a/drivers/gpu/drm/asahi/m3/t8122_admission.rs b/drivers/gpu/drm/asahi/m3/t8122_admission.rs index 7505065810acc3..f4c4658bc5d0b9 100644 --- a/drivers/gpu/drm/asahi/m3/t8122_admission.rs +++ b/drivers/gpu/drm/asahi/m3/t8122_admission.rs @@ -2,6 +2,12 @@ //! Read-only T8122 identity admission. Firmware startup remains disabled. +/// The T8122 boards the M3 runtime starts on by default: the M3 MacBook Airs (13" J613, 15" J615) +/// and the 14" M3 MacBook Pro (J504). All three load the same 14.8.3 G15G image (UUID +/// `DF697F05-…`, checked separately by firmware admission). The other T8122 Macs (the J433 and +/// J434 iMacs) are not listed. +pub(crate) const T8122_BOARDS: [&[u8]; 3] = [b"apple,j613", b"apple,j615", b"apple,j504"]; + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub(crate) struct Identity { pub(crate) active_cores: u32, @@ -151,6 +157,17 @@ pub(crate) fn read_identity( #[cfg(test)] mod tests { + use super::T8122_BOARDS; + + #[test] + fn the_t8122_runtime_boards_are_exactly_the_airs_and_the_14_inch_pro() { + // Exact: dropping the J504 or adding another T8122 Mac (J433, J434) must fail here. + assert_eq!(T8122_BOARDS, [&b"apple,j613"[..], b"apple,j615", b"apple,j504"]); + for other in [&b"apple,j433"[..], b"apple,j434", b"apple,t8122"] { + assert!(!T8122_BOARDS.contains(&other)); + } + } + use super::*; const G15G_C0: u32 = 0x0702_2000; diff --git a/drivers/gpu/drm/asahi/m3/t8122_start.rs b/drivers/gpu/drm/asahi/m3/t8122_start.rs index 737034dd6f8c13..f4fe2bae341aa5 100644 --- a/drivers/gpu/drm/asahi/m3/t8122_start.rs +++ b/drivers/gpu/drm/asahi/m3/t8122_start.rs @@ -301,8 +301,8 @@ pub(crate) fn arm(dev: &device::Device, soc: &Soc) -> Result> e.mapping_count(), storage::IOMAP_BASE ); - // J613/J615 have no SoC die temperature zone yet, so a cap above the no-feedback limit runs - // the fanless GPU without any temperature feedback (`m3_thermal` holds the cap but gets no + // J615 and J504 have no SoC die temperature zone yet, so a cap above the no-feedback limit + // runs the GPU without any temperature feedback (`m3_thermal` holds the cap but gets no // reading). The runtime cap and the firmware ceiling stay equal, because the cap is at most // the no-feedback limit. if v.pstate_cap > knobs::PSTATE_CAP { diff --git a/tools/asahi/dcp14-panel-tests.py b/tools/asahi/dcp14-panel-tests.py index 0abcd1e89d3f93..19c02cafd82010 100755 --- a/tools/asahi/dcp14-panel-tests.py +++ b/tools/asahi/dcp14-panel-tests.py @@ -87,7 +87,25 @@ machine="apple,j613";const struct dcp_v14_board*j=iomfb_v14_7_board(&dev); assert(!IS_ERR(j)&&j->panel_width==2560 && j->panel_height==1664); machine="apple,j700";assert(IS_ERR(iomfb_v14_7_board(&dev))); - machine="apple,j504";assert(IS_ERR(iomfb_v14_7_board(&dev))); + /* J504 (14" M3 MacBook Pro): the J613 image, the J514 panel, 60 or 120 Hz. */ + machine="apple,j504";const struct dcp_v14_board*p14=iomfb_v14_7_board(&dev); + assert(!IS_ERR(p14)&&p14&&!strcmp(p14->name,"J504")&&!strcmp(p14->debugfs,"dcp-j504")); + assert(p14->panel_width==3024&&p14->panel_height==1964&&p14->promotion&&p14->log_bringup); + assert(!strcmp(p14->firmware_uuid,"90F849E1-B422-367E-B389-50246F8DEC47")); + assert(!strcmp(p14->handoff,"apple,t8122-handoff")&&p14->panel_nits&&!p14->swap_timestamps); + assert(p14->ctm_set==A(421)&&p14->ctm_get==A(420)); + image_uuid=p14->firmware_uuid;assert(probe_gate(&dev,p14)==0); + image_uuid="C042E95C-B9D8-3F0E-94B3-582A08AA6FDD";assert(probe_gate(&dev,p14)==-ENODEV); + image_uuid="F493F03E-CC40-3D89-9A08-5F259BA2B246";assert(probe_gate(&dev,p14)==-ENODEV); + image_uuid=NULL;assert(probe_gate(&dev,p14)==-ENODEV); + image_uuid=p14->firmware_uuid;marker_value=0;assert(probe_gate(&dev,p14)==-ENODEV);marker_value=1; + {struct apple_dcp_v14 q={.dev=&dev,.board=p14};width=3024;height=1890;stride=width*4;notch=74; + assert(dcp_v14_geometry(&q)==0&&q.panel_height==1964&&q.notch_rows==74); + height=1964;notch=0;assert(dcp_v14_geometry(&q)==0&&q.panel_height==1964); + width=2560;height=1600;stride=width*4;notch=64;assert(dcp_v14_geometry(&q)==-EINVAL);} + /* Other T8122 Macs (J433/J434 iMacs) have no record. */ + machine="apple,j433";assert(IS_ERR(iomfb_v14_7_board(&dev))); + machine="apple,j434";assert(IS_ERR(iomfb_v14_7_board(&dev))); dcp.compatible="apple,t6030-dcp";machine="apple,j516s";assert(iomfb_v14_7_board(&dev)==&dcp_v14_board_t6030); dcp.compatible="apple,t8122-dcp"; struct apple_dcp_v14 v={.dev=&dev,.board=b};width=2880;height=1800;stride=width*4;notch=64; @@ -139,7 +157,7 @@ machine="apple,j613";assert(IS_ERR(iomfb_v14_7_board(&dev))); machine="apple,j516m";assert(IS_ERR(iomfb_v14_7_board(&dev))); dcp.compatible="apple,t6030-dcp";machine="apple,j516s";assert(iomfb_v14_7_board(&dev)==&dcp_v14_board_t6030); - puts("current J615/J613/T6030/J516C/J514C admission + hidden/full notch, wrong geometry controls: PASS"); + puts("current J615/J613/J504/T6030/J516C/J514C admission + hidden/full notch, wrong geometry controls: PASS"); #endif } '''