Skip to content

SP11/Denali front camera (IMX681, C-PHY): reception on CSIPHY2 trio 0, SOT sync last blocker #74

Description

@karsies-wq

Surface Pro 11 (x1e80100 "Denali") front camera: IMX681 C-PHY reception FOUND on CSIPHY2 — SOT sync is the last blocker

UPDATE (evening): The PHY sweep found it. The front camera is wired to
CSIPHY2 (0xace8000), trio 0 — not CSIPHY4 as the CRD analogy suggested.
With the downstream-ordered C-PHY init (2.1.2 tables) on csiphy2/trio0 the CSID
now reports, per the downstream cam_ife_csid880.h bit map:

  • DL0/DL1/DL2_EOT captured (bits 0-2) — real C-PHY traffic reaching the CSID;
  • ERROR_CPHY_SOT_RECEPTION (bit 12) persistently;
  • at some AFE settings additionally ERROR_CPHY_PH_CRC (bit 13) — i.e. a
    packet header made it to the CRC check once symbol alignment got close;
  • never LONG_PKT/SHORT_PKT; zero VFE interrupts.

Tuning observed so far: CDR (trio_base+0x78) has a sharp response curve —
dead below 0x46, best (EOTs + SOT error) around 0x52–0x58; settle count sweeps
(0x10..0x50) change nothing; CSIPHY core clk at 300 vs 480 MHz no difference;
presenting the trio as 2/3 CSID lanes → lane FIFO overflow (1 is correct).
Sensor PLL read back during streaming: Windows "mode 1" exactly — VT PLL
2160 MHz, OP PLL 2400 MHz, op_sys_div 1, RAW10, one trio; internal frame
counter ~61 fps at 3840x2160, so the symbol rate should be ~1.2 or ~2.2 Gsps
(all 8 downstream AFE rows 1.0–2.5 Gsps tried; only the 1.0–2.0 region responds).

Remaining question for anyone who knows this PHY: what turns
ERROR_CPHY_SOT_RECEPTION into captured SOTs on the Gen2 2.1.2 combo PHY?

Candidates I can't resolve from public code: per-sensor analog EQ/offset values
(downstream pulls these from CAMX tuning data, e.g. the 0x?90–0x?98 lane
registers), an exact symbol-rate-matched AFE row, or something about trio wire
order that Windows configures elsewhere. Everything below this line is the
original dossier describing how we got here.


Original dossier: IMX681 streams internally, but zero C-PHY/D-PHY reception on CSIPHY4 — full findings

TL;DR: On the Snapdragon Surface Pro 11 I have the Sony IMX681 front camera fully
under control via the generic CCS driver (identifies, binds, PLL locks, MODE_SELECT=1,
internal frame counter ticks at ~61 fps), but the CAMSS receiver never sees a single
symbol — CSI2_RX_IRQ_STATUS stays 0x00000000 with no CRC/ECC errors, across an
exhaustive sweep of D-PHY and (self-ported) C-PHY reception on CSIPHY4. I'm looking
for anyone who knows the Denali camera wiring (which CSIPHY, which trio), or has
insight into x1e80100 C-PHY reception.

Kernel: jglathe jg/ubuntu-qcom-x1e-7.2-rc5-jg-0 (7.2-rc5). All work below is
reproducible; patches and tooling available on request.

What works (sensor side)

  • Board DT written from scratch (mainline x1e80100-microsoft-denali.dts has no
    camera nodes): CCI buses, pm8010 rails (l1m..l7m) + pm8550 l7b/l16b, MCLK pinmux
    (cam_aon on gpio100 — absent from the shipped DT, sensors don't respond without
    it), reset GPIOs, camss + csiphy4 + camera@10 on cci1/i2c-bus@1.
  • Sensor identified over CCI: CCS sensor_model_id 0x0681, manufacturer 0x4260,
    rev 0x10, at i2c 0x10 (EEPROM 0x50 alongside; rear OV13858 VCM+sensor on cci0/1;
    IR ST VD55G0 at 0x60 on cci0/0). Matches the Windows driver blobs (MSHW0490/91/92).
  • ccs.ko binds using static data (ccs-sensor-4260-0681-0010.fw) fixing four
    broken limit registers (read 0x00000000 → UBSAN shift + reject-all-link-freqs) and
    min_pll_op_clk_freq (0x1118 reads 0x044f3000 = fixed-point 1103.19 MHz, but the
    sensor claims IEEE 754 → decodes as 0 → single-PLL path bails with -EINVAL and no
    debug output). After that the CCS PLL calculator accepts computed link freqs.
  • The full Windows init goes into the sensor: 361-register vendor init table +
    204-register mode table (both reverse-engineered from the QTI Chromatix
    com.surface.sensormodule.ffc_imx681.bin in the Windows DriverStore, decoder
    available), Windows' own PLL config, 1 lane per 0x0114 = 0.
  • Proof of internal streaming: frame_count (0x0005) increments ~61/s while
    streaming; VIDIOC_STREAMON succeeds end-to-end through camss.

Why I believe the link is C-PHY

  • Windows' validated init table writes 0x0111 = 3 (CCS: CSI-2 C-PHY signalling).
  • The Windows laneAssign field for the front camera is 0x0000 (single lane/trio 0);
    isComboMode = 0.
  • x1e80100 CSIPHYs are D/C combo PHYs; the sensor's own capability register claims
    D-PHY-only (0x04), but it comes from the same block with four provably-broken
    registers, and IMX681 modules exist in both modes (Leopard Imaging sells a 2-lane
    D-PHY module).
  • Exhaustive D-PHY reception tests all failed silently (below) — exactly what a
    C-PHY transmitter into a D-PHY-configured receiver looks like: no activity, no
    errors.

Receiver-side matrix (all negative, all measured via CSID registers during stream)

D-PHY (mainline camss receive path):

  • CSIPHY4, physical lanes DL0..DL3 (DL0_INPUT_SEL swept, confirmed in CFG0): 0.
  • CSIPHY0/1/2 (camss port + DT moved per PHY, PHY_NUM_SEL confirmed): 0.
  • 1-lane and 2-lane configs; 17 computed link freqs in the sensor's feasible
    window (810–892 MHz) plus Windows' own PLL config: 0.

C-PHY (ported by me — mainline has no C-PHY receive; this kernel programs the PHY in a
separate phy_qcom_mipi_csi2 driver, not in camss):

  • Register sequence transcribed from downstream cam_csiphy_2_1_2_hwreg.h
    (the x1e80100 is driven by the 2.1.2 tables in mainline; its D-PHY table is
    byte-identical, PHY reports HW version 0x40010000). Full downstream ordering
    replicated from cam_csiphy_core.c: reset-enter (CTRL0=0x01) → lane enable
    CTRL5 = odd bit per trio (CPHY_LANE_n = BIT(1)/BIT(3)/BIT(5)) → common block
    0x1084=0, 0x108C=0, CTRL7(0x101C)=0x7A, CTRL6(0x1018)=0x01 → per-datarate AFE
    table then static 3ph table → reset-exit CTRL0=0x0E + 3.05 ms.
  • CSID PHY_TYPE_SEL bit set, DL0_INPUT_SEL follows the trio.
  • Swept at runtime: trio 0/1/2 × AFE tables 1.0/1.2/1.5/1.7/2.0 Gsps ×
    matching CSID input: CSI2_RX_IRQ_STATUS = 0 in every combination, zero
    packet/CRC counters. Sensor confirmed transmitting during these tests
    (0x0111=3 read back, MODE_SELECT=1, frame counter ticking).
  • PHY 3ph status registers during stream: trio1 cphy_lane_status (0x758) reads
    a static 0x12 (others 0x00/0x01) — looks like DC line levels, no reception.

Also ruled out: MCLK (19.2 MHz, verified running and pinmuxed), rails (Windows
power sequence replicated, sensor answers i2c), reset GPIOs, GDSCs/clocks during
stream (IFE at 727 MHz, camnoc 400 MHz), the cam-indicator GPIO 225 interlock
theory (LED toggles, no effect), TPG (x1e80100 TPG appears non-functional in this
tree — separate issue), exposure=0, missing vendor registers (all 365 delay fields
are zero; the four loose regSettings are standard stream-on/group-hold).

Open questions

  1. Does anyone know the Denali camera wiring? Which CSIPHY does the front
    camera land on, and which trio/pads? (ACPI would tell, but the machine boots
    DT-mode; the Windows platform INF doesn't contain it, and the CRD analogy
    suggests csiphy4 — unverified for this board.)
  2. Is there anything x1e80100-specific to C-PHY receive beyond the 2.1.2 tables —
    e.g. a combo-pad mux register that selects 3-phase mode per pad group, outside
    the csiphy register block? (The downstream techpack has no sc8380xp target to
    compare against.)
  3. For the camss C-PHY WIP series (David Heidelberg et al.): I have a working,
    hang-free 2.1.2/Gen2-2.x C-PHY init flow for x1e80100 that could become the
    first user of the series on this SoC — happy to test/contribute once reception
    is proven.

Next on my list

C-PHY reception attempts on csiphy0/1/2 (DTB variants ready, one reboot each).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions