intel: fix critical bugs found in cross-reference audit

Four fixes from the code quality and Linux cross-reference audit:

1. DP AUX endianness (dp_aux.rs): Data packing must be big-endian
   (MSB first, bits [31:24] = byte 0), matching Linux i915
   intel_dp_aux_pack(). Fix send: (3-j)*8 shift. Fix receive:
   to_be_bytes(). This was the #1 correctness bug — wrong endianness
   would corrupt all DP AUX transactions.

2. Cursor pipe_select collision (cursor.rs): Mode and pipe select
   were using the same bit positions. Fix: pipe_select at [29:28],
   mode_64x64_argb = 0x27 per Intel PRM CUR_CTL register layout
   and Linux MCURSOR_MODE_64_ARGB_AX + CURSOR_PIPE_SELECT.

3. Missing DP link training constants (dp_link.rs): Add
   DP_LANE_CR_DONE, DP_LANE_CHANNEL_EQ_DONE, DP_LANE_SYMBOL_LOCKED
   used in clock_recovery() and channel_equalization().

4. Missing ARL device ID (info.rs): Add 0x7D67 Arrow Lake-S
   from Linux INTEL_ARL_S_IDS.
This commit is contained in:
2026-05-30 10:04:46 +03:00
parent 0dee6ec9da
commit af6d6ff607
4 changed files with 12 additions and 9 deletions
@@ -33,14 +33,12 @@ impl CursorPlane {
pub fn enable(&self, pipe: u8) -> Result<()> {
let cntr = self.regs.curcntr(pipe);
let mode_128x128: u32 = 0 << 28;
let mode_64x64: u32 = 1 << 28;
let mode_argb8888: u32 = 1 << 24;
let gamma_enable: u32 = 1 << 16;
let pipe_select: u32 = (pipe as u32) << 28;
let cursor_enable: u32 = 1 << 31;
let pipe_select: u32 = (pipe as u32 & 0x3) << 28;
let mode_64x64_argb: u32 = 0x27;
let val = mode_64x64 | mode_argb8888 | gamma_enable;
self.mmio.write_u32(cntr, val | pipe_select);
let val = cursor_enable | pipe_select | mode_64x64_argb;
self.mmio.write_u32(cntr, val);
debug!("redox-drm-intel: cursor enabled on pipe {}", pipe);
Ok(())
}
@@ -91,7 +91,7 @@ impl DpAux {
for (i, chunk) in send_buf.chunks(4).enumerate() {
let mut val: u32 = 0;
for (j, &byte) in chunk.iter().enumerate() {
val |= (byte as u32) << (j * 8);
val |= (byte as u32) << ((3 - j) * 8);
}
self.mmio.write_u32(self.data_offset + i * 4, val);
}
@@ -104,7 +104,7 @@ impl DpAux {
let mut recv = Vec::with_capacity(recv_size as usize);
for i in 0..((recv_size as usize + 3) / 4) {
let data = self.mmio.read_u32(self.data_offset + i * 4);
let bytes = data.to_le_bytes();
let bytes = data.to_be_bytes();
for j in 0..4 {
if recv.len() < recv_size as usize {
recv.push(bytes[j]);
@@ -20,6 +20,10 @@ const DP_LINK_BW_1_62: u8 = 0x06;
const DP_LINK_BW_2_7: u8 = 0x0A;
const DP_LINK_BW_5_4: u8 = 0x14;
const DP_LANE_CR_DONE: u8 = 1 << 0;
const DP_LANE_CHANNEL_EQ_DONE: u8 = 1 << 1;
const DP_LANE_SYMBOL_LOCKED: u8 = 1 << 2;
const DP_TRAINING_PATTERN_1: u8 = 0x01;
const DP_TRAINING_PATTERN_2: u8 = 0x02;
const DP_TRAINING_PATTERN_DISABLE: u8 = 0x00;
@@ -150,6 +150,7 @@ const DEVICE_ID_TABLE: &[DeviceIdEntry] = &[
DeviceIdEntry { device_id: 0x7D67, gen: IntelGeneration::Gen12_7, platform_name: "Meteor Lake", dmc_fw_key: Some("MTL") },
DeviceIdEntry { device_id: 0x7D41, gen: IntelGeneration::GenXe2, platform_name: "Arrow Lake-U", dmc_fw_key: Some("ARL") },
DeviceIdEntry { device_id: 0x7D51, gen: IntelGeneration::GenXe2, platform_name: "Arrow Lake-P Arc Pro 130T/140T", dmc_fw_key: Some("ARL") },
DeviceIdEntry { device_id: 0x7D67, gen: IntelGeneration::GenXe2, platform_name: "Arrow Lake-S", dmc_fw_key: Some("ARL") },
DeviceIdEntry { device_id: 0x7DD1, gen: IntelGeneration::GenXe2, platform_name: "Arrow Lake-P", dmc_fw_key: Some("ARL") },
DeviceIdEntry { device_id: 0xB640, gen: IntelGeneration::GenXe2, platform_name: "Arrow Lake-H", dmc_fw_key: Some("ARL") },
];