From 0944b8e83a47bbf5ae288d25f1843bd0c715077a Mon Sep 17 00:00:00 2001 From: Daniel Lemky Date: Fri, 6 Nov 2026 23:28:03 -0500 Subject: [PATCH 1/8] drm/apple: add opt-in J516M native panel admission Reuse the ADT-confirmed T6031 display layout on the J516M/T6034, with its exact board/SoC and pinned 14.7 DCP image. Retain the working T6031 handoff namespace separately from J514M and require an explicit display owner choice. Enable the existing swap timestamp behavior for the 120 Hz internal panel and carry the J516M panel admission cases into the existing host fixture. Other boards and their default policy are unchanged. Assisted-by: Codex:GPT-6 Signed-off-by: Daniel Lemky (cherry picked from commit 727efc7f628c9b1b406fce5338bb7b9498437cf3) [Carried without the dcpext/HDMI admission (apple_t6034_display.dcpext, the dcpext and HDMI device-tree includes, and the fabric, crossbar and ATC tunnel matches), which depend on the unmerged #292.] Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Scott Jones --- arch/arm64/boot/dts/apple/t6034-j516m.dts | 24 +++++++++++++++++ drivers/gpu/drm/apple/iomfb_v14_7.c | 19 ++++++++++++++ drivers/soc/apple/t6030-display-gate.c | 32 +++++++++++++++++++++++ tools/asahi/dcp14-panel-tests.py | 25 +++++++++++++++--- 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/apple/t6034-j516m.dts b/arch/arm64/boot/dts/apple/t6034-j516m.dts index 22ad5251eaecef..eac430b8d0a047 100644 --- a/arch/arm64/boot/dts/apple/t6034-j516m.dts +++ b/arch/arm64/boot/dts/apple/t6034-j516m.dts @@ -10,6 +10,7 @@ /dts-v1/; #include "t6034.dtsi" +#include "t6031-dcp.dtsi" #include "t603x-j514-j516.dtsi" / { @@ -38,3 +39,26 @@ compatible = "apple,j516-macaudio", "apple,j316-macaudio", "apple,macaudio"; model = "MacBook Pro J516"; }; + +/* + * J516M ADT confirms the J516C display register and interrupt layout. + * External displays (dcpext, HDMI) are not described here yet. + */ +&clk_disp0 { + /* + * Preserve the captured boot-clock metadata, as the J514M path does. + * Firmware warns that this is below its video clock; + * that warning is not proof of the programmed clock or a startup veto. + * The metadata does not qualify sustained power or thermal behavior. + */ + clock-frequency = <400000000>; +}; + +&dcp { + panel { + compatible = "apple,panel-j516", "apple,panel-mini-led", "apple,panel"; + width-mm = <346>; + height-mm = <223>; + adj-height-mm = <216>; + }; +}; diff --git a/drivers/gpu/drm/apple/iomfb_v14_7.c b/drivers/gpu/drm/apple/iomfb_v14_7.c index 4c7f76b9ed6f07..f2205622338858 100644 --- a/drivers/gpu/drm/apple/iomfb_v14_7.c +++ b/drivers/gpu/drm/apple/iomfb_v14_7.c @@ -197,6 +197,24 @@ static const struct dcp_v14_board dcp_v14_board_j516c = { .panel_nits = true, }; +/* J516M uses the J516C image; its first boot offered only a 120 Hz panel timing. */ +static const struct dcp_v14_board dcp_v14_board_j516m = { + .name = "J516M", + .debugfs = "dcp-j516m", + .dcp_compatible = "apple,t6031-dcp", + .machine = "apple,j516m", + .soc = "apple,t6034", + .firmware_uuid = DCP_V14_J516C_FIRMWARE_UUID, + .handoff = "apple,t6031-handoff", + .panel_width = 3456, + .panel_height = 2234, + .promotion = true, + .log_bringup = true, + .base_edid = true, + /* Same pinned DCP image as J516C: zero stamps cap this panel at 60 fps. */ + .swap_timestamps = true, +}; + /* * J514C (MacBook Pro 14", M3 Max): the T6031 DCP running the J516C image * (the DCP image is the SoC's; its UUID is checked at probe), in the J514S @@ -236,6 +254,7 @@ static const struct dcp_v14_board *const dcp_v14_boards[] = { &dcp_v14_board_j516c, &dcp_v14_board_j514c, &dcp_v14_board_j514m, + &dcp_v14_board_j516m, }; struct dcp_v14_property { diff --git a/drivers/soc/apple/t6030-display-gate.c b/drivers/soc/apple/t6030-display-gate.c index 016abbcf6cf96f..ff5fdec6589dd8 100644 --- a/drivers/soc/apple/t6030-display-gate.c +++ b/drivers/soc/apple/t6030-display-gate.c @@ -346,10 +346,39 @@ static const struct gate_soc gate_t6034 __initconst = { .fw_uuids = "asahi,t6034-fw-uuids", }; +static bool gate_j516m_requested __initdata; + +/* ADT-confirmed T6031 display layout, admitted only on the J516M. */ +static const struct gate_soc gate_j516m __initconst = { + .machine = "apple,j516m", + .prefix = "apple-t6034-display: ", + .name = "T6034", + .dcp_compat = "apple,t6031-dcp", + .display_compat = "apple,t6031-display-subsystem", + .marker = "apple,t6031-handoff", + .pwrstate_compat = "apple,t6031-pmgr-pwrstate", + .dcp_full_name = "dcp@386c00000", + .pmp_values = "/chosen/asahi,t6031-pmp", + .pmp_uuid = gate_t6031_pmp_uuid, + .report_compat = "apple,t6031-pmp-v2-report", + .disp_entry = "report@10", + .reuse_pmp = true, + .pmp_compat = "apple,t6031-pmp-v2", + .ans_entry = "report@21", + .requested = &gate_j516m_requested, + .opt_in = "apple_t6034_display.enable=1", + .ps_chain = { PMP_PS_DISP_FE, PMP_PS_DISP_CPU, PMP_PS_DISP_SYS }, + .pmp_ps_any_pmgr = true, + .describe = true, + .fw_uuids = "asahi,t6031-fw-uuids", + /* External displays (dcpext) are not qualified on the J516M: left off. */ +}; + static const struct gate_soc *const gate_socs[] __initconst = { &gate_t6030, &gate_t8122, &gate_t6031, + &gate_j516m, &gate_t6034, }; @@ -2053,6 +2082,9 @@ static void __init gate_run(void) board); } + if (gate_soc == &gate_j516m) + gate_j516m_requested = gate_t6034_switch > 0; + if (gate_soc == &gate_t6034) { if (!gate_t6034_default_board()) { gate_info("unsupported board; native display stays disabled\n"); diff --git a/tools/asahi/dcp14-panel-tests.py b/tools/asahi/dcp14-panel-tests.py index 19c02cafd82010..8efbbcea6419ab 100755 --- a/tools/asahi/dcp14-panel-tests.py +++ b/tools/asahi/dcp14-panel-tests.py @@ -36,7 +36,10 @@ struct device {struct device_node *of_node;}; static const char *machine; static bool of_device_is_compatible(const struct device_node *n,const char *c){return !strcmp(n->compatible,c);} - static bool of_machine_is_compatible(const char*c){return !strcmp(machine,c);} + static bool of_machine_is_compatible(const char*c){ + if (!strcmp(machine,c)) return true; + return (!strcmp(machine,"apple,j514m") || !strcmp(machine,"apple,j516m")) && !strcmp(c,"apple,t6034"); + } static struct device_node fb={"simple-framebuffer"},dcp={"apple,t8122-dcp"}; static u32 width,height,stride,notch,marker_value=1; static const char *image_uuid; @@ -65,6 +68,9 @@ defines='\n'.join(l for l in src.splitlines() if l.startswith('#define DCP_V14_') and 'FIRMWARE_UUID' in l)+'\n' sel_start='const struct dcp_v14_board *dcp_v14_board_select(' if 'const struct dcp_v14_board *dcp_v14_board_select(' in src else 'const struct dcp_v14_board *iomfb_v14_7_board(' sel=src[src.index(sel_start):src.index('const char *iomfb_v14_7_board_name(')] + if 'bool dcp_v14_board_stamps_swaps(' in src: + stamp_start=src.index('bool dcp_v14_board_stamps_swaps(') + sel+=src[stamp_start:src.index('\n}',stamp_start)+2]+'\n' geo=src[src.index('static int dcp_v14_geometry('):src.index('/* An external processor\'s firmware:')] driver='''struct apple_dcp_v14 {struct device *dev;const struct dcp_v14_board *board;u32 fb_width,fb_height,stride,notch_rows,panel_width,panel_height;};\n''' probe=src[src.index('int iomfb_v14_7_probe('):] @@ -155,9 +161,22 @@ dcp.compatible="apple,t8122-dcp";assert(IS_ERR(iomfb_v14_7_board(&dev))); dcp.compatible="apple,t6031-dcp";machine="apple,j514s";assert(IS_ERR(iomfb_v14_7_board(&dev))); machine="apple,j613";assert(IS_ERR(iomfb_v14_7_board(&dev))); - machine="apple,j516m";assert(IS_ERR(iomfb_v14_7_board(&dev))); + machine="apple,j516m"; + const struct dcp_v14_board*m16=iomfb_v14_7_board(&dev); + assert(!IS_ERR(m16)&&m16&&!strcmp(m16->name,"J516M")); + assert(m16->promotion&&m16->swap_timestamps&&!m16->ctm_set); + assert(dcp_v14_board_stamps_swaps(m16,false)); + assert(!dcp_v14_board_stamps_swaps(m16,true)); + assert(!dcp_v14_board_stamps_swaps(NULL,false)); + image_uuid="F493F03E-CC40-3D89-9A08-5F259BA2B246"; + assert(probe_gate(&dev,m16)==0); + image_uuid="DDF38191-93B3-324A-BC8F-643006F5AC82"; + assert(probe_gate(&dev,m16)==-ENODEV); + marker_value=0;image_uuid=m16->firmware_uuid; + assert(probe_gate(&dev,m16)==-ENODEV);marker_value=1; + dcp.compatible="apple,t6030-dcp";machine="apple,j516s";assert(iomfb_v14_7_board(&dev)==&dcp_v14_board_t6030); - puts("current J615/J613/J504/T6030/J516C/J514C admission + hidden/full notch, wrong geometry controls: PASS"); + puts("current J615/J613/J504/T6030/J516C/J514C/J516M admission + hidden/full notch, wrong geometry controls: PASS"); #endif } ''' From aaf73ec956fa6073b3e69e0a4dceb7b048f433f3 Mon Sep 17 00:00:00 2001 From: Daniel Lemky Date: Fri, 6 Nov 2026 23:28:24 -0500 Subject: [PATCH 2/8] drm/asahi: admit the measured J516M T6034 GPU profile Share the existing six-channel T6034 G15C hardware layout while keeping J516M machine and full firmware admission independent of J514M. Require the measured 30-core fused identity 0x7b5ed7f5fd and retain strict refusal of the generic firmware-prefix override. Link J516M GPU startup to its T6031 display supplier; keep J514M on its separate T6034 supplier. Extend the existing profile and display order fixtures with the prior J516M admission cases. Inherited J516C power/reference values remain thermally unqualified. Assisted-by: Codex:GPT-6 Signed-off-by: Daniel Lemky (cherry picked from commit 272cd802c034268f3f002151258ee8d1a054f3ef) Signed-off-by: Scott Jones --- drivers/gpu/drm/apple/apple_drv.c | 3 +++ drivers/gpu/drm/asahi/g15/boot.rs | 15 +++++++++++-- drivers/gpu/drm/asahi/g15/glue.c | 3 ++- drivers/gpu/drm/asahi/g15/hw.rs | 2 ++ drivers/gpu/drm/asahi/g15/hw/j516m.rs | 30 ++++++++++++++++++++++++++ drivers/gpu/drm/asahi/g15/mod.rs | 5 +++++ tools/asahi/g15-display-order-tests.py | 10 ++++++--- tools/asahi/g15-t6034-profile-tests.py | 14 +++++++++--- tools/aurora-ci/host-tests.json | 2 +- 9 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 drivers/gpu/drm/asahi/g15/hw/j516m.rs diff --git a/drivers/gpu/drm/apple/apple_drv.c b/drivers/gpu/drm/apple/apple_drv.c index b6a5be040ef9c8..9028388b33915b 100644 --- a/drivers/gpu/drm/apple/apple_drv.c +++ b/drivers/gpu/drm/apple/apple_drv.c @@ -139,6 +139,9 @@ EXPORT_SYMBOL_GPL(apple_drm_t6031_link_device); int apple_drm_t6034_link_device(struct device *consumer) { + if (of_machine_is_compatible("apple,j516m")) + return apple_g15_link_device(consumer, "apple,t6034", "apple,agx-t6034", + &apple_t6031_display); if (!of_machine_is_compatible("apple,j514m")) return -ENODEV; return apple_g15_link_device(consumer, "apple,t6034", "apple,agx-t6034", diff --git a/drivers/gpu/drm/asahi/g15/boot.rs b/drivers/gpu/drm/asahi/g15/boot.rs index b0ea7bfc44aedf..64d806561cdad3 100644 --- a/drivers/gpu/drm/asahi/g15/boot.rs +++ b/drivers/gpu/drm/asahi/g15/boot.rs @@ -480,6 +480,10 @@ pub(crate) fn admit( && cfg.platform == hw::Platform::DeviceTree && glue::machine(kernel::c_str!("apple,j514m")) && glue::machine(kernel::c_str!("apple,t6034")); + let j516m_board = cfg.chip_id == 0x6034 + && cfg.platform == hw::Platform::DeviceTree + && glue::machine(kernel::c_str!("apple,j516m")) + && glue::machine(kernel::c_str!("apple,t6034")); if pmp { if !glue::board() { return Err(ENODEV); @@ -494,7 +498,7 @@ pub(crate) fn admit( } return Err(err); } - } else if (cfg.chip_id == 0x6034 && !j514m_board) + } else if (cfg.chip_id == 0x6034 && !j514m_board && !j516m_board) || (!glue::machine(cfg.machine) && !j514c_board) { dev_err!(dev, "G15: not a {} machine\n", cfg.name); @@ -511,7 +515,7 @@ pub(crate) fn admit( return Err(err); } } - if j514c_board || j514m_board { + if j514c_board || j514m_board || j516m_board { if let hw::Board::DeviceTree(reference) = cfg.board { dev_warn!( dev, @@ -681,6 +685,13 @@ pub(crate) fn start( ); return Err(eproto()); } + if cfg.chip_id == 0x6034 + && glue::machine(kernel::c_str!("apple,j516m")) + && !hw::j516m::identity_matches(id.version, id.counts, id.cores) + { + dev_err!(d, "J516M powered identity differs from the measured bin\n"); + return Err(eproto()); + } // Binning: any non-empty enabled set in each cluster, nothing above the core slots. let clusters = cfg.num_clusters as usize; let slots = cfg.core_slots(); diff --git a/drivers/gpu/drm/asahi/g15/glue.c b/drivers/gpu/drm/asahi/g15/glue.c index 4a3dac630520df..90aca2c6f5cf15 100644 --- a/drivers/gpu/drm/asahi/g15/glue.c +++ b/drivers/gpu/drm/asahi/g15/glue.c @@ -165,7 +165,8 @@ int asahi_g15_display_prepare(struct device *dev) name = "T6031"; ret = apple_drm_t6031_link_device(dev); } else if (of_device_is_compatible(dev->of_node, "apple,agx-t6034")) { - compatible = "apple,t6034-display-subsystem"; + compatible = of_machine_is_compatible("apple,j516m") ? + "apple,t6031-display-subsystem" : "apple,t6034-display-subsystem"; name = "T6034"; ret = apple_drm_t6034_link_device(dev); } else { diff --git a/drivers/gpu/drm/asahi/g15/hw.rs b/drivers/gpu/drm/asahi/g15/hw.rs index 847ab6685444ad..a9987f83076674 100644 --- a/drivers/gpu/drm/asahi/g15/hw.rs +++ b/drivers/gpu/drm/asahi/g15/hw.rs @@ -11,6 +11,8 @@ use core::ops::Range; pub(crate) mod t6031; #[cfg(CONFIG_DRM_ASAHI_G15)] pub(crate) mod t6034; +#[cfg(CONFIG_DRM_ASAHI_G15)] +pub(crate) mod j516m; /// Identification register values of a qualified G15S. pub(crate) struct HwId { diff --git a/drivers/gpu/drm/asahi/g15/hw/j516m.rs b/drivers/gpu/drm/asahi/g15/hw/j516m.rs new file mode 100644 index 00000000000000..642abbd0999c3d --- /dev/null +++ b/drivers/gpu/drm/asahi/g15/hw/j516m.rs @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +//! Measured J516M/T6034 30-core profile. Share the six-channel G15C layout +//! with J514M, but retain independent machine, firmware and fused-core admission. +//! Native rendering is verified; inherited J516C power/reference values remain +//! unqualified for sustained power and thermal behavior on this board. + +use super::super::Config; +use super::FirmwareBuild; + +pub(crate) const CONFIG: Config = Config { + machine: kernel::c_str!("apple,j516m"), + firmware: &[FirmwareBuild { + name: "J516M RTKit 2419.140.12 (power qualification pending)", + machine: Some(kernel::c_str!("apple,j516m")), + text_size: 0x64000, + data_size: 0x140000, + marker: 0x5cf28, + text_sha256: [ + 0x4c, 0xa2, 0x4b, 0x65, 0x8f, 0x8e, 0xbe, 0x7c, 0x27, 0x37, 0x5f, 0xdf, 0x38, 0xe4, + 0x1e, 0x5d, 0xaf, 0x86, 0x32, 0x51, 0x50, 0x77, 0xb5, 0x37, 0xca, 0x19, 0xe6, 0xd0, + 0xdc, 0x77, 0x04, 0xb7, + ], + }], + ..super::t6034::CONFIG +}; + +pub(crate) fn identity_matches(version: u32, counts: u32, cores: u64) -> bool { + version == 0x07041100 && counts == 0x0021040a && cores == 0x7b5ed7f5fd +} diff --git a/drivers/gpu/drm/asahi/g15/mod.rs b/drivers/gpu/drm/asahi/g15/mod.rs index f8afd4fc7d2acd..010e5f0e5af4fc 100644 --- a/drivers/gpu/drm/asahi/g15/mod.rs +++ b/drivers/gpu/drm/asahi/g15/mod.rs @@ -203,6 +203,11 @@ impl platform::Driver for Driver<'_> { return Err(EPROBE_DEFER); } let cfg = *info.ok_or(ENODEV)?; + let cfg = if cfg.chip_id == 0x6034 && boot::glue::machine(c_str!("apple,j516m")) { + &hw::j516m::CONFIG + } else { + cfg + }; dev_info!(pdev.as_ref(), "G15: probing ({})\n", cfg.name); match crate::driver::AsahiPlatformDriver::probe_g15(pdev, cfg) { Ok(driver) => Some(driver), diff --git a/tools/asahi/g15-display-order-tests.py b/tools/asahi/g15-display-order-tests.py index 6ff26493965c60..8d18710802b587 100644 --- a/tools/asahi/g15-display-order-tests.py +++ b/tools/asahi/g15-display-order-tests.py @@ -221,9 +221,13 @@ def c_source(root): CHECK(publish(&d34) == 0 && d34.refs == 1); CHECK(prepare(&g34) == 0 && links_made == 1 && last_link.supplier == &d34); machine("apple,t6034", "apple,j516m"); - CHECK(prepare(&g34) == -ENODEV && links_made == 1); + CHECK(prepare(&g34) == 0 && links_made == 2 && last_link.supplier == &d31); + withdraw(&d31); + CHECK(prepare(&g34) == -EPROBE_DEFER && links_made == 2); + machine("apple,t6034", "apple,j999"); + CHECK(prepare(&g34) == -ENODEV && links_made == 2); machine("apple,t6031", "apple,j514m"); - CHECK(prepare(&g34) == -ENODEV && links_made == 1); + CHECK(prepare(&g34) == -ENODEV && links_made == 2); machine("apple,t6034", "apple,j514m"); withdraw(&d34); CHECK(!d34.refs && prepare(&g34) == -EPROBE_DEFER); @@ -328,7 +332,7 @@ def c_source(root): mod glue { use super::{call, STATE}; pub fn board() -> bool { call("board"); STATE.with(|s| s.borrow().board) } - pub fn machine(name: &str) -> bool { if !["apple,j514c", "apple,t6031", "apple,j514m", "apple,t6034"].contains(&name) { call("machine"); } STATE.with(|s| { let s=s.borrow(); match name { "apple,j514c" => s.j514c, "apple,t6031" => s.t6031, "apple,j514m" => s.j514m, "apple,t6034" => s.t6034, _ => s.machine } }) } + pub fn machine(name: &str) -> bool { if !["apple,j514c", "apple,t6031", "apple,j514m", "apple,j516m", "apple,t6034"].contains(&name) { call("machine"); } STATE.with(|s| { let s=s.borrow(); match name { "apple,j514c" => s.j514c, "apple,t6031" => s.t6031, "apple,j514m" => s.j514m, "apple,j516m" => false, "apple,t6034" => s.t6034, _ => s.machine } }) } pub unsafe fn asahi_g15_pmp_prepare(_: *mut core::ffi::c_void) -> core::ffi::c_int { call("pmp"); STATE.with(|s| s.borrow().pmp) } pub unsafe fn asahi_g15_display_prepare(_: *mut core::ffi::c_void) -> core::ffi::c_int { call("display"); STATE.with(|s| s.borrow().display) } pub fn dma_coherent(_: &super::device::Device) -> bool { call("coherent"); false } diff --git a/tools/asahi/g15-t6034-profile-tests.py b/tools/asahi/g15-t6034-profile-tests.py index 4f73b5172aee76..90605f84d1240b 100644 --- a/tools/asahi/g15-t6034-profile-tests.py +++ b/tools/asahi/g15-t6034-profile-tests.py @@ -3,7 +3,7 @@ """Compile actual G15C profiles and test T6034 shape and exact firmware admission. The diagnostic profile has no firmware row. Once a measured row is present, -exercise its complete public identity and J514M binding without reading an image. +exercise the complete public identities and J514M/J516M bindings without reading an image. """ from pathlib import Path import subprocess @@ -47,6 +47,7 @@ def item(text, marker): @TYPES@ #[path="@T6031@"] pub(crate) mod t6031; #[path="@T6034@"] pub(crate) mod t6034; + #[path="@J516M@"] pub(crate) mod j516m; } } fn main() { @@ -107,7 +108,7 @@ def item(text, marker): assert_eq!(t6031::IOMAPS.iter().find(|m|m.slot==11).unwrap().map_bytes,8*0xd8000); } ''' -for token,replacement in {'@CONFIG@':config,'@REFERENCE@':reference,'@VALUE@':value,'@TYPES@':types,'@T6031@':str(G15/'hw/t6031.rs'),'@T6034@':str(G15/'hw/t6034.rs'),'@MATCHING@':str(G15/'identity/matching.rs'),'@LOOKUP@':str(G15/'identity/lookup.rs')}.items():source=source.replace(token,replacement) +for token,replacement in {'@CONFIG@':config,'@REFERENCE@':reference,'@VALUE@':value,'@TYPES@':types,'@T6031@':str(G15/'hw/t6031.rs'),'@T6034@':str(G15/'hw/t6034.rs'),'@J516M@':str(G15/'hw/j516m.rs'),'@MATCHING@':str(G15/'identity/matching.rs'),'@LOOKUP@':str(G15/'identity/lookup.rs')}.items():source=source.replace(token,replacement) identity=(G15/'identity.rs').read_text() # Run the production firmware admission against synthetic public identity bytes. firmware=item(identity,'pub(crate) fn firmware(') @@ -156,8 +157,15 @@ def item(text, marker): } ''' for token,replacement in {'FIRMWARE':firmware,'MATCHING':str(G15/'identity/matching.rs'),'LOOKUP':str(G15/'identity/lookup.rs')}.items():identity_source=identity_source.replace(token,replacement) +j516m_source = source.replace('let c=&t6034::CONFIG;', 'let c=&j516m::CONFIG;') +j516m_source = j516m_source.replace('use g15::hw::{t6031,t6034};', 'use g15::hw::{t6031,j516m};') +j516m_source = j516m_source.replace('apple,j514m', 'apple,j516m') +j516m_source = j516m_source.replace('b"apple,j516m",b"apple,j514s"', 'b"apple,j514m",b"apple,j514s"') +j516m_source = j516m_source.replace('0x7b5fc7f5fd', '0x7b5ed7f5fd') +j516m_source = j516m_source.replace('[0x1fd,0x1fd,0x1fc,0x1ed]', '[0x1fd,0x1fd,0x1ed,0x1ed]') +j516m_source = j516m_source.replace(' assert_eq!((c.hw_ids', ' assert!(j516m::identity_matches(0x07041100,0x0021040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041200,0x0021040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041100,0x0001040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041100,0x0021040a,0x7b5fc7f5fd));\n' + ' assert_eq!((c.hw_ids', 1) with tempfile.TemporaryDirectory(prefix='t6034-profile-') as temp: - for name,code in [('profile',source),('measurement-refusal',identity_source)]: + for name,code in [('profile-j514m',source),('profile-j516m',j516m_source),('measurement-refusal',identity_source)]: p=Path(temp)/name;p.with_suffix('.rs').write_text(code) subprocess.run(['rustc','--edition=2021','--cfg','CONFIG_DRM_ASAHI_G15','-o',str(p),str(p.with_suffix('.rs'))],check=True) subprocess.run([str(p)],check=True) diff --git a/tools/aurora-ci/host-tests.json b/tools/aurora-ci/host-tests.json index fb9cdbdd66fc69..1a48d610093964 100644 --- a/tools/aurora-ci/host-tests.json +++ b/tools/aurora-ci/host-tests.json @@ -2226,7 +2226,7 @@ "tools/asahi/g15-t6034-profile-tests.py" ], "rust": "1.93.1", - "note": "Production G15C profiles, exact T6034 topology/six memory channels, full J514M firmware tuple and wrong-board/field refusal; strict nonempty and empty profiles never consult prefix overrides, while older policy remains unchanged. Public identity inputs only." + "note": "Production G15C profiles, exact T6034 topology/six memory channels, full J514M/J516M firmware tuples and wrong-board/field refusal; strict nonempty and empty profiles never consult prefix overrides, while older policy remains unchanged. Public identity inputs only." }, { "name": "tools/asahi/t6034-display-tests.py", From e47381284f55fc3cda63db7f8469a7fa52b27997 Mon Sep 17 00:00:00 2001 From: Daniel Lemky Date: Sat, 7 Nov 2026 20:42:40 -0500 Subject: [PATCH 3/8] pmdomain: apple: select J516M's display recovery switch J516M uses the T6031 PMP report layout, whose fallback tells users to boot with apple_t6031_display.enable=0 after startup fails. Its display gate only honors apple_t6034_display.enable, so that advice can leave a retained T6034 enable active and retry the failed startup. Select apple_t6034_display.enable=0 for the exact J516M/T6034 machine pair. Keep other report profiles' recovery switches and the nomodeset alternative unchanged. No PMP startup or report protocol changes. Fixes: 727efc7f628c9b1b406fce5338bb7b9498437cf3 ("drm/apple: add opt-in J516M native panel and HDMI admission") Assisted-by: Codex:GPT-6 Signed-off-by: Daniel Lemky (cherry picked from commit 721a41ccb47c1754de23529bb47d87c3f7be83ae) Signed-off-by: Scott Jones --- drivers/pmdomain/apple/pmp-report.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/pmdomain/apple/pmp-report.c b/drivers/pmdomain/apple/pmp-report.c index fac35afc4e6cb2..adda6374407e01 100644 --- a/drivers/pmdomain/apple/pmp-report.c +++ b/drivers/pmdomain/apple/pmp-report.c @@ -699,10 +699,18 @@ static void apple_pmp_start_finish(struct apple_pmp_start *st, int result) st->result = result; complete_all(&st->started); } - if (result && READ_ONCE(st->enabled)) + if (result && READ_ONCE(st->enabled)) { + const char *fallback = st->rep->offsets->fallback; + + /* J516M shares the T6031 report layout, but has its own display gate. */ + if (of_machine_is_compatible("apple,t6034") && + of_machine_is_compatible("apple,j516m")) + fallback = "apple_t6034_display.enable=0"; + dev_err(st->rep->dev, "%s PMP start failed (%d) after the PMP was enabled: it may keep running until the next reboot. Reboot to stop it; to boot without starting it: %s, or nomodeset\n", - st->rep->offsets->name, result, st->rep->offsets->fallback); + st->rep->offsets->name, result, fallback); + } } /* Teardown has begun: a start still in progress gives up early. */ From 60b5cbc991f660bf6f4285d7535afc6725f60fff Mon Sep 17 00:00:00 2001 From: Daniel Lemky Date: Fri, 6 Nov 2026 23:29:18 -0500 Subject: [PATCH 4/8] drm/apple: enable bounded J516M built-in panel brightness The J516M record already pins the J516C 14.7 image and J516 panel geometry. Admit this board to the existing nits backlight path, retaining the 500-nit bound, lifecycle and external-display exclusion. No protocol, raw register or boot-brightness changes are required. The original working kernel was physically qualified: apple-panel-bl registers and the brightness keys visibly dim and brighten the panel. The rebased branch has not been booted; suspend, DPMS cycles, the full range and photometric accuracy remain unqualified. Link: https://github.com/omacom/linux-aurora/pull/259 Assisted-by: Codex:GPT-6 Signed-off-by: Daniel Lemky (cherry picked from commit e9e02dc5e05725cfa1e5c9574e291a7937c8fe4e) Signed-off-by: Scott Jones --- drivers/gpu/drm/apple/iomfb_v14_7.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/apple/iomfb_v14_7.c b/drivers/gpu/drm/apple/iomfb_v14_7.c index f2205622338858..93ee1ee25ee3f0 100644 --- a/drivers/gpu/drm/apple/iomfb_v14_7.c +++ b/drivers/gpu/drm/apple/iomfb_v14_7.c @@ -213,6 +213,8 @@ static const struct dcp_v14_board dcp_v14_board_j516m = { .base_edid = true, /* Same pinned DCP image as J516C: zero stamps cap this panel at 60 fps. */ .swap_timestamps = true, + /* J516C's 14.7 image uses the bounded nits block for the J516 panel. */ + .panel_nits = true, }; /* @@ -384,7 +386,7 @@ static int dcp_v14_callback(void *cookie, u32 tag, const void *input, u32 in_siz static void dcp_v14_backlight_work(struct work_struct *work); -/* The internal panel of a board whose swap level block was validated (T6030). */ +/* The internal panel of a board admitted to the bounded swap level path. */ static bool dcp_v14_board_nits(const struct apple_dcp_v14 *v14) { return !v14->external && v14->panel_nits && v14->board && v14->board->panel_nits; @@ -1759,7 +1761,7 @@ 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,j504")); + machine_is(ctx, "apple,j504") || machine_is(ctx, "apple,j516m")); } const char *iomfb_v14_7_board_name(const struct dcp_v14_board *board) From b4cff0ea9ab8d3a8313b3375958d5aad64d4e4c0 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Sun, 8 Nov 2026 14:32:18 -0500 Subject: [PATCH 5/8] drm/asahi: g15: admit any 30-core J516M bin, not one Mac's core mask The J516M profile pinned the exact fused core mask of the first Mac it was measured on (0x7b5ed7f5fd). That is fine while the GPU is opt-in, but other 30-core J516Ms fuse off different cores and would be refused once it is on by default. Require the G15C version and counts and exactly 30 enabled cores instead, as Mesa does; start()'s per-cluster plausibility check still applies. Log the identity on a refusal. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Scott Jones --- drivers/gpu/drm/asahi/g15/boot.rs | 8 +++++++- drivers/gpu/drm/asahi/g15/hw/j516m.rs | 7 ++++++- tools/asahi/g15-t6034-profile-tests.py | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/asahi/g15/boot.rs b/drivers/gpu/drm/asahi/g15/boot.rs index 64d806561cdad3..819dbb85adbba7 100644 --- a/drivers/gpu/drm/asahi/g15/boot.rs +++ b/drivers/gpu/drm/asahi/g15/boot.rs @@ -689,7 +689,13 @@ pub(crate) fn start( && glue::machine(kernel::c_str!("apple,j516m")) && !hw::j516m::identity_matches(id.version, id.counts, id.cores) { - dev_err!(d, "J516M powered identity differs from the measured bin\n"); + dev_err!( + d, + "J516M powered identity is not the 30-core G15C: version {:#x} counts {:#x} core-mask {:#x}\n", + id.version, + id.counts, + id.cores + ); return Err(eproto()); } // Binning: any non-empty enabled set in each cluster, nothing above the core slots. diff --git a/drivers/gpu/drm/asahi/g15/hw/j516m.rs b/drivers/gpu/drm/asahi/g15/hw/j516m.rs index 642abbd0999c3d..1ae58fe1a365d7 100644 --- a/drivers/gpu/drm/asahi/g15/hw/j516m.rs +++ b/drivers/gpu/drm/asahi/g15/hw/j516m.rs @@ -25,6 +25,11 @@ pub(crate) const CONFIG: Config = Config { ..super::t6034::CONFIG }; +/// The 14-core-CPU, 30-core-GPU J516M: its G15C revision and counts, and exactly 30 enabled +/// cores. Which cores are fused off differs between Macs of the same bin, so the mask itself is +/// not pinned (the per-cluster plausibility check in `start()` still applies). +pub(crate) const ENABLED_CORES: u32 = 30; + pub(crate) fn identity_matches(version: u32, counts: u32, cores: u64) -> bool { - version == 0x07041100 && counts == 0x0021040a && cores == 0x7b5ed7f5fd + version == 0x07041100 && counts == 0x0021040a && cores.count_ones() == ENABLED_CORES } diff --git a/tools/asahi/g15-t6034-profile-tests.py b/tools/asahi/g15-t6034-profile-tests.py index 90605f84d1240b..ee8c2dccc5fb29 100644 --- a/tools/asahi/g15-t6034-profile-tests.py +++ b/tools/asahi/g15-t6034-profile-tests.py @@ -163,7 +163,7 @@ def item(text, marker): j516m_source = j516m_source.replace('b"apple,j516m",b"apple,j514s"', 'b"apple,j514m",b"apple,j514s"') j516m_source = j516m_source.replace('0x7b5fc7f5fd', '0x7b5ed7f5fd') j516m_source = j516m_source.replace('[0x1fd,0x1fd,0x1fc,0x1ed]', '[0x1fd,0x1fd,0x1ed,0x1ed]') -j516m_source = j516m_source.replace(' assert_eq!((c.hw_ids', ' assert!(j516m::identity_matches(0x07041100,0x0021040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041200,0x0021040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041100,0x0001040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041100,0x0021040a,0x7b5fc7f5fd));\n' + ' assert_eq!((c.hw_ids', 1) +j516m_source = j516m_source.replace(' assert_eq!((c.hw_ids', ' assert!(j516m::identity_matches(0x07041100,0x0021040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041200,0x0021040a,0x7b5ed7f5fd));\n assert!(!j516m::identity_matches(0x07041100,0x0001040a,0x7b5ed7f5fd));\n assert!(j516m::identity_matches(0x07041100,0x0021040a,0x7b5fc7f5fd));\n assert!(!j516m::identity_matches(0x07041100,0x0021040a,0x7b5ed7f5fc));\n assert!(!j516m::identity_matches(0x07041100,0x0021040a,0x7b5ed7f5ff));\n assert!(!j516m::identity_matches(0x07041100,0x0021040a,0));\n' + ' assert_eq!((c.hw_ids', 1) with tempfile.TemporaryDirectory(prefix='t6034-profile-') as temp: for name,code in [('profile-j514m',source),('profile-j516m',j516m_source),('measurement-refusal',identity_source)]: p=Path(temp)/name;p.with_suffix('.rs').write_text(code) From 4f58c0cdacc841bb95d34c89abe8eacc157448e3 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Sun, 8 Nov 2026 14:32:18 -0500 Subject: [PATCH 6/8] soc: apple: t6030-display-gate: default the J516M native display on normal boots Give the J516M the J514M policy: the native display is on unless apple_t6034_display.enable=0 is on the command line, and only on the exact apple,j516m + apple,t6034 pair. Its external displays stay off: the J516M profile hands over no dcpext. The "not requested" message read the T6031 switch for every opt-in SoC; read the T6034 one for the T6034 profiles. Extend t6034-display-tests.py to the J516M: the default, the owner's 0 and 1, the exact root pair, its T6031-layout DCP record and pinned image, with mutants for an unpinned SoC and an opt-in default. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Scott Jones --- drivers/soc/apple/t6030-display-gate.c | 33 ++++++++++++++++++++++---- tools/asahi/t6034-display-tests.py | 28 ++++++++++++++++++++-- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/drivers/soc/apple/t6030-display-gate.c b/drivers/soc/apple/t6030-display-gate.c index ff5fdec6589dd8..07ba8b9f60f571 100644 --- a/drivers/soc/apple/t6030-display-gate.c +++ b/drivers/soc/apple/t6030-display-gate.c @@ -198,6 +198,21 @@ static bool __init gate_t6034_wanted(int sw) return gate_t6034_default_board() && gate_t6031_wanted(sw, true); } +/* + * J516M: the T6031 display layout on a T6034, with J514M's owner switch + * (apple_t6034_display.enable) and the same default: on unless it is 0. + */ +static bool __init gate_j516m_default_board(void) +{ + return of_machine_is_compatible("apple,t6034") && + of_machine_is_compatible("apple,j516m"); +} + +static bool __init gate_j516m_wanted(int sw) +{ + return gate_j516m_default_board() && gate_t6031_wanted(sw, true); +} + /* One SoC's internal display handoff, as the gate checks and completes it */ struct gate_soc { const char *machine; /* root compatible */ @@ -366,7 +381,6 @@ static const struct gate_soc gate_j516m __initconst = { .pmp_compat = "apple,t6031-pmp-v2", .ans_entry = "report@21", .requested = &gate_j516m_requested, - .opt_in = "apple_t6034_display.enable=1", .ps_chain = { PMP_PS_DISP_FE, PMP_PS_DISP_CPU, PMP_PS_DISP_SYS }, .pmp_ps_any_pmgr = true, .describe = true, @@ -2082,8 +2096,15 @@ static void __init gate_run(void) board); } - if (gate_soc == &gate_j516m) - gate_j516m_requested = gate_t6034_switch > 0; + if (gate_soc == &gate_j516m) { + if (!gate_j516m_default_board()) { + gate_info("unsupported board; native display stays disabled\n"); + return; + } + gate_j516m_requested = gate_j516m_wanted(gate_t6034_switch); + if (gate_t6034_switch < 0) + gate_info("native display on by default on J516M; apple_t6034_display.enable=0 keeps the boot framebuffer\n"); + } if (gate_soc == &gate_t6034) { if (!gate_t6034_default_board()) { @@ -2096,7 +2117,11 @@ static void __init gate_run(void) } if (!*gate_soc->requested) { - if (gate_soc->opt_in && gate_t6031_switch < 0) + /* Each opt-in SoC's own switch: T6031's is not T6034's */ + int sw = gate_soc == &gate_t6034 || gate_soc == &gate_j516m ? + gate_t6034_switch : gate_t6031_switch; + + if (gate_soc->opt_in && sw < 0) gate_info("native display not requested (%s is not on the command line), display stays on the boot framebuffer\n", gate_soc->opt_in); else diff --git a/tools/asahi/t6034-display-tests.py b/tools/asahi/t6034-display-tests.py index ddd1cf54cc4c39..7647e4bcfebb0f 100644 --- a/tools/asahi/t6034-display-tests.py +++ b/tools/asahi/t6034-display-tests.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0-only OR MIT -"""Run production J514M display selection and opt-out policy on the host.""" +"""Run production J514M and J516M display selection and opt-out policy on the host.""" from pathlib import Path import re import subprocess @@ -33,6 +33,7 @@ def item(s, marker): records=driver[driver.index('static const struct dcp_v14_board dcp_v14_board_t6030'):driver.index('struct dcp_v14_property {')] functions='\n'.join([item(gate,'static bool __init gate_t6031_wanted('), item(gate,'static bool __init gate_t6034_default_board('),item(gate,'static bool __init gate_t6034_wanted('), + item(gate,'static bool __init gate_j516m_default_board('),item(gate,'static bool __init gate_j516m_wanted('), item(driver,'const struct dcp_v14_board *dcp_v14_board_select('),item(driver,'bool dcp_v14_board_admits(')]) main = r''' int main(void) @@ -58,6 +59,26 @@ def item(s, marker): } board="apple,j514m";soc="apple,t6034";dcp="apple,t6031-dcp";bool known; assert(!dcp_v14_board_select(dcp_is,machine_is,NULL,&known)); + /* J516M: the T6031 display layout on a T6034; default on, apple_t6034_display.enable=0 off */ + for(unsigned i=0;iname,"J516M") && !strcmp(b->handoff,"apple,t6031-handoff")); + assert(b->promotion && b->swap_timestamps && !b->ctm_set); + assert(dcp_v14_board_admits(b,"F493F03E-CC40-3D89-9A08-5F259BA2B246")); + assert(!dcp_v14_board_admits(b,"DDF38191-93B3-324A-BC8F-643006F5AC82")); + } + } + board="apple,j516m";soc="apple,t6034";dcp="apple,t6034-dcp"; + assert(!dcp_v14_board_select(dcp_is,machine_is,NULL,&known)); return 0; } ''' @@ -67,6 +88,8 @@ def item(s, marker): 'lost-board-soc':source.replace('.soc = "apple,t6034",','.soc = NULL,'), 'lost-owner-optout':source.replace('return sw < 0 ? default_board : sw;','return sw < 0 ? default_board : true;'), 'lost-firmware-identity':source.replace('return uuid && !strcmp(uuid, board->firmware_uuid);','return uuid != NULL;'), + 'j516m-any-soc':source.replace('return of_machine_is_compatible("apple,t6034") &&\n\t of_machine_is_compatible("apple,j516m");','return of_machine_is_compatible("apple,j516m");'), + 'j516m-opt-in':source.replace('return gate_j516m_default_board() && gate_t6031_wanted(sw, true);','return gate_j516m_default_board() && sw > 0;'), } with tempfile.TemporaryDirectory(prefix='t6034-display-') as directory: for name,c in mutants.items(): @@ -76,7 +99,8 @@ def item(s, marker): assert (result.returncode==0)==(name=='control'),(name,result.stderr) print(name+': '+('pass' if name=='control' else 'caught')) assert 'gate_t6034_requested = gate_t6034_wanted(gate_t6034_switch);' in gate -print('T6034 normal display defaults, owner disable, exact root pair and firmware identity: PASS') +assert 'gate_j516m_requested = gate_j516m_wanted(gate_t6034_switch);' in gate +print('T6034 (J514M, J516M) normal display defaults, owner disable, exact root pair and firmware identity: PASS') # Compile the production report layout records and OF match table. Matching # T6034 through its generic T6020 fallback binds a report that never creates From baf495599c74f3731cc807019f443b4cda5b085f Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Sun, 8 Nov 2026 14:41:05 -0500 Subject: [PATCH 7/8] tools/asahi: g15: follow the J516M profile in two host fixtures The J516M GPU profile adds a j516m module to hw.rs and a profile swap to the G15 probe. g15-zero-words-tests.py pins hw.rs for its golden T6030 profile and now skips that module line, as it does for t6034. g15-probe-init-tests.py compiles probe() with stubs, which now need Config.chip_id, hw::j516m::CONFIG, boot::glue::machine() and c_str!. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Scott Jones --- tools/asahi/g15-probe-init-tests.py | 8 ++++++-- tools/asahi/g15-zero-words-tests.py | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/asahi/g15-probe-init-tests.py b/tools/asahi/g15-probe-init-tests.py index 42b55f063359eb..3ee813480ae4fa 100644 --- a/tools/asahi/g15-probe-init-tests.py +++ b/tools/asahi/g15-probe-init-tests.py @@ -126,7 +126,10 @@ def item(text, marker): ) -> impl PinInit, Error> + 'bound; } } -struct Config { name: &'static str } +struct Config { name: &'static str, chip_id: u32 } +macro_rules! c_str { ($s:literal) => { $s } } +// The J516M probe swaps in its own profile; this fixture's device is never a J516M. +mod hw { pub mod j516m { pub static CONFIG: crate::Config = crate::Config { name: "j516m", chip_id: 0x6034 }; } } pub struct ThisModule; pub trait ModuleMetadata { const NAME: &'static std::ffi::CStr; } pub trait InPlaceModule: Sized { @@ -173,6 +176,7 @@ def item(text, marker): } mod boot { pub mod glue { pub fn retained() -> bool { crate::RETAINED.with(core::cell::Cell::get) } + pub fn machine(_compatible: &str) -> bool { false } pub unsafe fn asahi_g15_reprobe() { crate::activation_reprobe(); } // Reads the device tree and logs; no driver state. pub unsafe fn asahi_g15_report_loader_gpu() {} @@ -191,7 +195,7 @@ def item(text, marker): FAIL_ALLOC.set(fail_alloc); TOUCH.set(touch); PROBE_ERROR.set(error); RETAINED.set(false); ALLOCS.set(0); PROBES.set(0); } -static CFG: Config = Config { name: "test" }; +static CFG: Config = Config { name: "test", chip_id: 0x6034 }; static PDEV: platform::Device> = platform::Device { base: Device { data: Cell::new(core::ptr::null_mut()) }, ctx: PhantomData, }; diff --git a/tools/asahi/g15-zero-words-tests.py b/tools/asahi/g15-zero-words-tests.py index d443597fd1ca41..82141bcac76559 100644 --- a/tools/asahi/g15-zero-words-tests.py +++ b/tools/asahi/g15-zero-words-tests.py @@ -222,6 +222,7 @@ def main(): if name == 'hw.rs': # New SoC module wiring does not alter the golden T6030 profile. data = data.replace(b'#[cfg(CONFIG_DRM_ASAHI_G15)]\npub(crate) mod t6034;\n', b'') + data = data.replace(b'#[cfg(CONFIG_DRM_ASAHI_G15)]\npub(crate) mod j516m;\n', b'') actual = sha(data) if actual != expected: raise SystemExit("T6030 golden file changed: " + name) From 44ef4d95571630dfb175b2124eaf7de0d1a6fd07 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Sun, 8 Nov 2026 18:43:46 -0500 Subject: [PATCH 8/8] drm/apple: v14-board-test: J516M is admitted on its own record The J516M panel record admits the T6031-layout DCP on apple,j516m with apple,t6034, so v14_board_t6031_other_boards no longer holds: it expected that pair to be refused. Add a v14_board_j516m case, like the J516C and J514M ones: the record, its J516C image, panel, nits and stamps, and that it is neither the J516C nor the J514M record. Its name on a T6031 root is still refused. The refusal case now uses another T6034 board and the J514M. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Scott Jones --- drivers/gpu/drm/apple/v14-board-test.c | 42 ++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/apple/v14-board-test.c b/drivers/gpu/drm/apple/v14-board-test.c index bef910f8f5becc..858b5db4e2835d 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 j514m[] = { "apple,j514m", "apple,t6034", "apple,arm-platform", NULL }; static const char *const j514m_wrong_soc[] = { "apple,j514m", "apple,t6031", NULL }; static const char *const j516m[] = { "apple,j516m", "apple,t6034", "apple,arm-platform", NULL }; +static const char *const j516m_wrong_soc[] = { "apple,j516m", "apple,t6031", NULL }; +static const char *const t6034_other[] = { "apple,j999", "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 }; @@ -131,12 +133,47 @@ static void v14_board_j514m(struct kunit *test) KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", j514m, &known)); } -/* A T6031 DCP on a T6034 has no record: refused. */ +/* + * The J516M: a T6034 with the T6031 DCP layout, running the J516C image on the + * J516 panel. Admitted only on its own record, with its own SoC. + */ +static void v14_board_j516m(struct kunit *test) +{ + const struct dcp_v14_board *b; + bool known; + + b = board_for("apple,t6031-dcp", j516m, &known); + KUNIT_ASSERT_NOT_NULL(test, b); + KUNIT_EXPECT_TRUE(test, known); + KUNIT_EXPECT_STREQ(test, b->name, "J516M"); + KUNIT_EXPECT_STREQ(test, b->debugfs, "dcp-j516m"); + KUNIT_EXPECT_STREQ(test, b->machine, "apple,j516m"); + KUNIT_EXPECT_STREQ(test, b->soc, "apple,t6034"); + KUNIT_EXPECT_STREQ(test, b->handoff, "apple,t6031-handoff"); + KUNIT_EXPECT_STREQ(test, b->firmware_uuid, J516C_DCP_IMAGE); + KUNIT_EXPECT_EQ(test, b->panel_width, 3456); + KUNIT_EXPECT_EQ(test, b->panel_height, 2234); + KUNIT_EXPECT_TRUE(test, b->promotion); + KUNIT_EXPECT_TRUE(test, b->base_edid); + KUNIT_EXPECT_TRUE(test, b->panel_nits); + KUNIT_EXPECT_TRUE(test, dcp_v14_board_stamps_swaps(b, false)); + KUNIT_EXPECT_TRUE(test, dcp_v14_board_admits(b, J516C_DCP_IMAGE)); + KUNIT_EXPECT_FALSE(test, dcp_v14_board_admits(b, T6030_DCP_IMAGE)); + /* Neither the J516C record nor the J514M one. */ + KUNIT_EXPECT_PTR_NE(test, b, board_for("apple,t6031-dcp", j516c, &known)); + KUNIT_EXPECT_PTR_NE(test, b, board_for("apple,t6034-dcp", j514m, &known)); + /* Its name on a T6031 root is not a J516M. */ + KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", j516m_wrong_soc, &known)); +} + +/* A T6031 DCP on any other T6034, or on a J514M, has no record: refused. */ static void v14_board_t6031_other_boards(struct kunit *test) { bool known; - KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", j516m, &known)); + KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", t6034_other, &known)); + KUNIT_EXPECT_TRUE(test, known); + KUNIT_EXPECT_NULL(test, board_for("apple,t6031-dcp", j514m, &known)); KUNIT_EXPECT_TRUE(test, known); /* Not a 14.x internal DCP at all. */ KUNIT_EXPECT_NULL(test, board_for("apple,t8112-dcp", j516c, &known)); @@ -318,6 +355,7 @@ static struct kunit_case v14_board_cases[] = { KUNIT_CASE(v14_board_j516c), KUNIT_CASE(v14_board_j514c), KUNIT_CASE(v14_board_j514m), + KUNIT_CASE(v14_board_j516m), KUNIT_CASE(v14_board_t6031_other_boards), KUNIT_CASE(v14_board_j516c_image), KUNIT_CASE(v14_board_unchanged),