From d1ad27fe1fbc6ffe98c492550a1e8440e7165f77 Mon Sep 17 00:00:00 2001 From: Erik Bourget Date: Sun, 8 Nov 2026 14:49:08 -0500 Subject: [PATCH 1/2] dt-bindings: media: apple: Describe the T6050 capture interface Describe named register resources, host stream pairs, camera power gates and loader-provided memory for the T6050 ISP. Retain the disabled hardware inventory format used by the other T6050 boards. Developed with Claude Code. Signed-off-by: Erik Bourget --- .../bindings/media/apple,t6050-isp.yaml | 228 ++++++++++++++++-- 1 file changed, 206 insertions(+), 22 deletions(-) diff --git a/Documentation/devicetree/bindings/media/apple,t6050-isp.yaml b/Documentation/devicetree/bindings/media/apple,t6050-isp.yaml index ea791487d642e..61892d3c8c17c 100644 --- a/Documentation/devicetree/bindings/media/apple,t6050-isp.yaml +++ b/Documentation/devicetree/bindings/media/apple,t6050-isp.yaml @@ -4,19 +4,23 @@ $id: http://devicetree.org/schemas/media/apple,t6050-isp.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Apple T6050 image signal processor +title: Apple T6050 Image Signal Processor maintainers: - Ryan Murray <81541646+RyanTheTide@users.noreply.github.com> + - Erik Bourget description: - The camera image signal processor of the T6050 MacBook Pros (ADT isp0). - Unlike earlier generations its ADT node lists the coprocessor window and - two PMGR windows rather than mailbox and handshake windows inside the ISP - block. Its buffers go through the three instances of the ISP DART. It is - described from the ADT so the device tree lists all of the SoC's - hardware; no driver supports this generation yet and the node stays - disabled. + The T6050 ISP controls the attached camera sensor and processes its frames + through firmware the bootloader loads. The firmware segments are described + as reserved memory mapped at the addresses the firmware runs them at. The + host exchanges commands and image buffers through streams 0 and 12 of three + DART instances. A capture watchdog must be serviced while streaming. + + Disabled hardware inventory nodes use three register windows, five interrupts, + three stream references and two power domains. Driver-ready nodes name their + five register windows and describe the host streams and individual power gates. + The bootloader supplies the reserved memory and platform ID before enabling them. select: properties: @@ -33,31 +37,124 @@ properties: - const: apple,isp reg: + minItems: 3 + maxItems: 5 + description: + Inventory nodes list the coprocessor and two PMGR windows. Named driver + resources list the coprocessor, mailbox, handshake, doorbell and watchdog. + + reg-names: items: - - description: Coprocessor registers - - description: The ISP's PMGR control window - - description: The ISP's PMGR power-state window + - const: coproc + - const: mbox + - const: gpio + - const: mbox2 + - const: wdt interrupts: - minItems: 5 + minItems: 1 maxItems: 5 iommus: - items: - - description: Stream 0 of the first ISP DART - - description: Stream 0 of the second ISP DART - - description: Stream 0 of the third ISP DART + minItems: 3 + maxItems: 6 + description: + Inventory nodes list stream 0 of each DART. Driver-ready nodes list + streams 0 and 12 of each of the three DARTs, in controller order. power-domains: - items: - - description: ISP system domain - - description: Camera sensor domain + minItems: 2 + maxItems: 8 + description: + Inventory nodes list system and sensor domains. Driver-ready nodes list + system, CPU, FE, sensor, DPRX, secure, BE and CLR domains, in that order. clocks: maxItems: 2 - status: - const: disabled + memory-region: + items: + - description: Firmware text loaded by the bootloader + - description: Firmware data loaded by the bootloader + - description: Firmware main memory window; host allocations follow it + + memory-region-names: + items: + - const: text + - const: data + - const: heap + + apple,dart-vm-size: + $ref: /schemas/types.yaml#/definitions/uint64 + description: + Size in bytes of the host allocation aperture used by the ISP driver. + + apple,platform-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Platform identifier passed in the firmware boot descriptor. + + apple,cam-connections-scheme: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Camera connection layout of the board passed in the firmware boot + descriptor. + + apple,firmware-version: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 3 + maxItems: 5 + description: Version of the firmware loaded by the bootloader. + + apple,firmware-compat: + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 3 + maxItems: 5 + description: Compatibility version supplied by the bootloader. + + apple,temporal-filter: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Firmware temporal-filter strength selected for the attached sensor. + + sensor-presets: + type: object + description: + Sensor firmware presets and the host output geometry associated with them. + patternProperties: + "^preset[0-9]+$": + type: object + properties: + apple,config-index: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Sensor configuration index understood by the firmware + apple,input-size: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: Input width in pixels + - description: Input height in pixels + description: Sensor input dimensions + apple,output-size: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: Output width in pixels + - description: Output height in pixels + description: Delivered frame dimensions + apple,crop: + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: Horizontal crop origin in pixels + - description: Vertical crop origin in pixels + - description: Crop width in pixels + - description: Crop height in pixels + description: Cropped sensor rectangle + required: + - apple,config-index + - apple,input-size + - apple,output-size + - apple,crop + additionalProperties: false + additionalProperties: false required: - compatible @@ -65,6 +162,93 @@ required: - interrupts - iommus - power-domains - - status + +allOf: + - if: + required: + - reg-names + then: + properties: + reg: + minItems: 5 + interrupts: + maxItems: 1 + iommus: + minItems: 6 + power-domains: + minItems: 8 + clocks: false + required: + - apple,dart-vm-size + - sensor-presets + allOf: + - if: + properties: + status: + const: disabled + required: + - status + then: {} + else: + required: + - memory-region + - memory-region-names + - apple,platform-id + else: + properties: + reg: + maxItems: 3 + interrupts: + minItems: 5 + iommus: + maxItems: 3 + power-domains: + maxItems: 2 + status: + const: disabled + required: + - status additionalProperties: false + +examples: + - | + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@580000000 { + compatible = "apple,t6050-isp", "apple,isp"; + reg = <0x5 0x80000000 0x0 0x1604000>, + <0x5 0x82924000 0x0 0x40>, + <0x5 0x829241d0 0x0 0x20>, + <0x5 0x82924464 0x0 0x10>, + <0x5 0xc3b50000 0x0 0x8000>; + reg-names = "coproc", "mbox", "gpio", "mbox2", "wdt"; + interrupt-parent = <&aic>; + interrupts = ; + iommus = <&isp_dart0 0>, <&isp_dart0 12>, + <&isp_dart1 0>, <&isp_dart1 12>, + <&isp_dart2 0>, <&isp_dart2 12>; + power-domains = <&ps_isp_sys>, <&ps_isp_cpu>, <&ps_isp_fe>, + <&ps_ispsens0>, <&ps_isp_dprx>, <&ps_isp_secure>, + <&ps_isp_be>, <&ps_isp_clr>; + memory-region = <&isp_fw_text>, <&isp_fw_data>, <&isp_heap>; + memory-region-names = "text", "data", "heap"; + apple,dart-vm-size = /bits/ 64 <0xde000000>; + apple,platform-id = <0x75>; + apple,cam-connections-scheme = <0x10>; + + sensor-presets { + preset0 { + apple,config-index = <5>; + apple,input-size = <1920 2160>; + apple,output-size = <1920 1080>; + apple,crop = <0 0 1920 1080>; + }; + }; + }; + }; From 562e67859dc0f356548bff552e0ad97115984cc5 Mon Sep 17 00:00:00 2001 From: Erik Bourget Date: Sun, 8 Nov 2026 14:49:09 -0500 Subject: [PATCH 2/2] media: apple: isp: Add T6050 camera capture support The T6050 ISP uses the H17 capture path with its own MMIO and DSID clear windows, host stream filter mask and mailbox interrupt enables. Describe these resources and keep the existing per-SoC behavior as the default. Exercise both the default and T6050 address-filter masks in KUnit. The source implementation captured 1080p NV12 frames at 30 fps on J716c. Developed with Claude Code. Signed-off-by: Erik Bourget --- .../media/platform/apple/isp/isp-drv-test.c | 18 ++++- drivers/media/platform/apple/isp/isp-drv.c | 80 ++++++++++++++++++- drivers/media/platform/apple/isp/isp-drv.h | 3 + drivers/media/platform/apple/isp/isp-fw.c | 14 ++-- 4 files changed, 104 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/apple/isp/isp-drv-test.c b/drivers/media/platform/apple/isp/isp-drv-test.c index dbddb079a0f57..53f731234e64c 100644 --- a/drivers/media/platform/apple/isp/isp-drv-test.c +++ b/drivers/media/platform/apple/isp/isp-drv-test.c @@ -43,15 +43,16 @@ static void isp_test_dapf_in_fw_mmio(struct kunit *test) * leaves every other byte alone. The bank is plain memory here: the driver * is arm64 only, where the MMIO accessors work on it unchanged. */ -static void isp_test_dapf_program(struct kunit *test) +static void isp_test_dapf_program_mask(struct kunit *test, u32 sidmask) { static const struct isp_dapf_window windows[] = { { 0x380704000, 0x380704063 }, { 0x382824000, 0x382824004 }, }; - static const struct apple_isp_hw hw = { + const struct apple_isp_hw hw = { .dapf = windows, .num_dapf = ARRAY_SIZE(windows), + .dapf_sidmask = sidmask, }; size_t size = (ARRAY_SIZE(windows) + 1) * DAPF_WINDOW_STRIDE; u8 expect[DAPF_WINDOW_STRIDE]; @@ -76,7 +77,7 @@ static void isp_test_dapf_program(struct kunit *test) put_unaligned_le32(0, &expect[0x04]); put_unaligned_le64(windows[i].start, &expect[0x08]); put_unaligned_le64(windows[i].end, &expect[0x10]); - put_unaligned_le32(1, &expect[0x20]); + put_unaligned_le32(sidmask ?: 1, &expect[0x20]); KUNIT_EXPECT_MEMEQ_MSG(test, bank + i * DAPF_WINDOW_STRIDE, expect, sizeof(expect), "window %u", i); } @@ -86,9 +87,20 @@ static void isp_test_dapf_program(struct kunit *test) ISP_TEST_DAPF_FILL, DAPF_WINDOW_STRIDE)); } +static void isp_test_dapf_program(struct kunit *test) +{ + isp_test_dapf_program_mask(test, 0); +} + +static void isp_test_dapf_program_t6050(struct kunit *test) +{ + isp_test_dapf_program_mask(test, 0xcc3); +} + static struct kunit_case isp_dapf_test_cases[] = { KUNIT_CASE(isp_test_dapf_in_fw_mmio), KUNIT_CASE(isp_test_dapf_program), + KUNIT_CASE(isp_test_dapf_program_t6050), {} }; diff --git a/drivers/media/platform/apple/isp/isp-drv.c b/drivers/media/platform/apple/isp/isp-drv.c index 627a9bdb9e94d..21dd9cdc1be2a 100644 --- a/drivers/media/platform/apple/isp/isp-drv.c +++ b/drivers/media/platform/apple/isp/isp-drv.c @@ -255,6 +255,7 @@ static int apple_isp_map_dapf(struct apple_isp *isp) int apple_isp_program_dapf(struct apple_isp *isp) { const struct apple_isp_hw *hw = isp->hw; + u32 sidmask = hw->dapf_sidmask ?: DAPF_CTRL2_ISP; void __iomem *w; unsigned int i; @@ -264,7 +265,7 @@ int apple_isp_program_dapf(struct apple_isp *isp) writeq(hw->dapf[i].start, w + DAPF_START); writeq(hw->dapf[i].end, w + DAPF_END); writel(DAPF_CTRL0_ISP, w + DAPF_CTRL0); - writel(DAPF_CTRL2_ISP, w + DAPF_CTRL2); + writel(sidmask, w + DAPF_CTRL2); } /* Only bits 7:0 of CTRL0 and bits 63:2 of END read back. */ @@ -274,7 +275,7 @@ int apple_isp_program_dapf(struct apple_isp *isp) readq(w + DAPF_START) != hw->dapf[i].start || (readq(w + DAPF_END) | 3) != (hw->dapf[i].end | 3) || (readl(w + DAPF_CTRL0) & 0xff) != DAPF_CTRL0_ISP || - readl(w + DAPF_CTRL2) != DAPF_CTRL2_ISP) { + readl(w + DAPF_CTRL2) != sidmask) { dev_err(isp->dev, "DAPF window %u (0x%llx-0x%llx) failed readback\n", i, hw->dapf[i].start, hw->dapf[i].end); return -EIO; @@ -1141,7 +1142,82 @@ static const struct apple_isp_hw apple_isp_hw_t8142 = { .setfile_stride_fixup = true, }; +/* T6050 ISP17c: CPU-visible firmware MMIO windows and DART filters. */ +static const struct isp_mmio_window apple_isp_fw_mmio_t6050[] = { + { 0x280680000, 0x8000 }, + { 0x280900000, 0x4000 }, + { 0x284240000, 0x28000 }, + { 0x284e3c000, 0x4000 }, + { 0x286724000, 0x4000 }, + { 0x29062c000, 0x20000 }, + { 0x509660000, 0x4000 }, + { 0x2220004000, 0x14000 }, + { 0x2222004000, 0x14000 }, + { 0x2224004000, 0x14000 }, + { 0x2226004000, 0x14000 }, + { 0x2228004000, 0x14000 }, + { 0x222a004000, 0x14000 }, + { 0x222c004000, 0x14000 }, + { 0x222e004000, 0x14000 }, +}; + +static const struct isp_dapf_window apple_isp_dapf_t6050[] = { + { 0x2809003b0, 0x2809003f3 }, + { 0x280680000, 0x280687fff }, + { 0x284e3c000, 0x284e3c003 }, + { 0x29062c000, 0x290648003 }, + { 0x509660000, 0x509660003 }, + { 0x286724000, 0x286724004 }, + { 0x284240000, 0x284264000 }, + { 0x2220004000, 0x22200162fc }, + { 0x2222004000, 0x22220162fc }, + { 0x2224004000, 0x22240162fc }, + { 0x2226004000, 0x22260162fc }, + { 0x2228004000, 0x22280162fc }, + { 0x222a004000, 0x222a0162fc }, + { 0x222c004000, 0x222c0162fc }, + { 0x222e004000, 0x222e0162fc }, +}; + +static const u64 apple_isp_dsid_t6050[] = { + 0x2220016000, + 0x2222016000, + 0x2224016000, + 0x2226016000, + 0x2228016000, + 0x222a016000, + 0x222c016000, + 0x222e016000, +}; + +static const struct apple_isp_hw apple_isp_hw_t6050 = { + .gen = ISP_GEN_T6040, + .fw_abi = ISP_FW_ABI_H17, + .dsid_count = ARRAY_SIZE(apple_isp_dsid_t6050), + .dsid_clr_bases = apple_isp_dsid_t6050, + .dsid_clr_range0 = 0x2fc, + .mbox_irq_enable = ISP_MBOX_IRQ_ENABLE_T6031, + .mbox_extra_enables = true, + .scl1 = true, + .meta_size = ISP_META_SIZE_T8140, + .capture_meta_size = ISP_CAPTURE_META_SIZE_T8140, + .fw_mmio = apple_isp_fw_mmio_t6050, + .num_fw_mmio = ARRAY_SIZE(apple_isp_fw_mmio_t6050), + .dapf = apple_isp_dapf_t6050, + .num_dapf = ARRAY_SIZE(apple_isp_dapf_t6050), + .dapf_sidmask = 0xcc3, + .coproc_control = ISP_COPROC_CONTROL_T8140, + .coproc_status = ISP_COPROC_STATUS_T8140, + .coproc_quiesce = ISP_COPROC_QUIESCE_T8140, + .boot_mode = 1, + .shared_size = 0xde000000, + .fw_restore = true, + .deferred_start = true, + .setfile_stride_fixup = true, +}; + static const struct of_device_id apple_isp_of_match[] = { + { .compatible = "apple,t6050-isp", .data = &apple_isp_hw_t6050 }, { .compatible = "apple,t8103-isp", .data = &apple_isp_hw_t8103 }, { .compatible = "apple,t8112-isp", .data = &apple_isp_hw_t8112 }, { .compatible = "apple,t8122-isp", .data = &apple_isp_hw_t8122 }, diff --git a/drivers/media/platform/apple/isp/isp-drv.h b/drivers/media/platform/apple/isp/isp-drv.h index 9056c3d7af143..66fa3e1264576 100644 --- a/drivers/media/platform/apple/isp/isp-drv.h +++ b/drivers/media/platform/apple/isp/isp-drv.h @@ -162,6 +162,7 @@ struct apple_isp_hw { u64 pmu_base; int dsid_count; + const u64 *dsid_clr_bases; /* windows of the H17 multi broadcast-clear command, the unused all ones */ u8 dsid_slots; u64 dsid_clr_base0; @@ -194,6 +195,7 @@ struct apple_isp_hw { u32 mbox2_offset; /* further interrupt enable and routing words (ISP17a) */ bool mbox_irq_route; + bool mbox_extra_enables; /* coprocessor control register, 0 for ISP_COPROC_CONTROL */ u32 coproc_control; /* coprocessor status register, 0 for ISP_COPROC_STATUS */ @@ -216,6 +218,7 @@ struct apple_isp_hw { */ const struct isp_dapf_window *dapf; unsigned int num_dapf; + u32 dapf_sidmask; /* ISP_GPIO_6 boot mode */ u32 boot_mode; diff --git a/drivers/media/platform/apple/isp/isp-fw.c b/drivers/media/platform/apple/isp/isp-fw.c index 28727ef24fbb6..302b18cd189c6 100644 --- a/drivers/media/platform/apple/isp/isp-fw.c +++ b/drivers/media/platform/apple/isp/isp-fw.c @@ -251,7 +251,7 @@ static irqreturn_t apple_isp_isr_thread(int irq, void *dev) static void isp_disable_irq(struct apple_isp *isp) { isp_mbox_write32(isp, isp->hw->mbox_irq_enable, 0x0); - if (isp->hw->mbox_irq_route) { + if (isp->hw->mbox_irq_route || isp->hw->mbox_extra_enables) { isp_mbox_write32(isp, ISP_MBOX_IRQ_ENABLE1_T8140, 0x0); isp_mbox_write32(isp, ISP_MBOX_IRQ_ENABLE2_T8140, 0x0); } @@ -273,13 +273,14 @@ static int isp_enable_irq(struct apple_isp *isp) isp_dbg(isp, "about to enable interrupts...\n"); isp_mbox_write32(isp, isp->hw->mbox_irq_enable, 0xf); - if (isp->hw->mbox_irq_route) { + if (isp->hw->mbox_irq_route || isp->hw->mbox_extra_enables) { isp_mbox_write32(isp, ISP_MBOX_IRQ_ENABLE1_T8140, ISP_MBOX_IRQ_ENABLE1_T8140_VAL); isp_mbox_write32(isp, ISP_MBOX_IRQ_ENABLE2_T8140, ISP_MBOX_IRQ_ENABLE2_T8140_VAL); - isp_mbox_write32(isp, ISP_MBOX_IRQ_ROUTE_T8140, - ISP_MBOX_IRQ_ROUTE_T8140_VAL); + if (isp->hw->mbox_irq_route) + isp_mbox_write32(isp, ISP_MBOX_IRQ_ROUTE_T8140, + ISP_MBOX_IRQ_ROUTE_T8140_VAL); } return 0; @@ -934,12 +935,13 @@ static int isp_set_dsid_clr(struct apple_isp *isp) unsigned int slots = max_t(unsigned int, hw->dsid_count, hw->dsid_slots); - if (WARN_ON(hw->dsid_count > ARRAY_SIZE(used) || + if (WARN_ON((!hw->dsid_clr_bases && hw->dsid_count > ARRAY_SIZE(used)) || slots > ARRAY_SIZE(bases))) return -EINVAL; for (unsigned int i = 0; i < slots; i++) - bases[i] = i < hw->dsid_count ? used[i] : U64_MAX; + bases[i] = i < hw->dsid_count ? + (hw->dsid_clr_bases ? hw->dsid_clr_bases[i] : used[i]) : U64_MAX; return isp_cmd_set_dsid_clr_multi_bc(isp, bases, slots, hw->dsid_clr_range0);