gpu: populate more EDID info
... which is required to pass the Android framework's EDID
validation (frameworks/native/libs/ui/DisplayIdentification.cpp).
Also, remove additional hard-coded extra resolutions which were
unused.
BUG=b:242931783
TEST=boot Cuttlefish with EDID re-enabled
(aosp/2189577 reverted)
Change-Id: Ib9cda60882fc3921c8424d10fd45d7dceae28a2f
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3846058
Tested-by: Jason Macnak <natsu@google.com>
Commit-Queue: Jason Macnak <natsu@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Kaiyi Li <kaiyili@google.com>
diff --git a/devices/src/virtio/gpu/edid.rs b/devices/src/virtio/gpu/edid.rs
index 9cfdd19..1430df6 100644
--- a/devices/src/virtio/gpu/edid.rs
+++ b/devices/src/virtio/gpu/edid.rs
@@ -125,34 +125,29 @@
populate_header(&mut edid);
populate_edid_version(&mut edid);
- populate_detailed_timings(&mut edid, info);
populate_standard_timings(&mut edid)?;
+ // 4 available descriptor blocks
+ let block0 = &mut edid[54..72];
+ populate_detailed_timing(block0, info);
+
+ let block1 = &mut edid[72..90];
+ populate_display_name(block1);
+
calculate_checksum(&mut edid);
Ok(OkEdid(Self { bytes: edid }))
}
}
-fn populate_detailed_timings(edid: &mut [u8], info: &DisplayInfo) {
- // Eventually we probably want to grab the display's underlying supported resolutions.
- let detailed_resolutions = [
- info.resolution,
- Resolution::new(1920, 1080),
- Resolution::new(1366, 768),
- Resolution::new(2560, 1600),
- ];
-
- let mut info: DisplayInfo = *info;
- for (block, resolution) in detailed_resolutions.iter().enumerate() {
- info.resolution = *resolution;
- populate_detailed_timing(edid, &info, block)
- }
+fn populate_display_name(edid_block: &mut [u8]) {
+ // Display Product Name String Descriptor Tag
+ edid_block[0..5].clone_from_slice(&[0x00, 0x00, 0x00, 0xFC, 0x00]);
+ edid_block[5..].clone_from_slice("CrosvmDisplay".as_bytes());
}
-fn populate_detailed_timing(edid: &mut [u8], info: &DisplayInfo, block: usize) {
- const DETAILED_TIMING_BLOCK_SIZE: usize = 18;
- let block_offset: usize = 54 + (DETAILED_TIMING_BLOCK_SIZE * block);
+fn populate_detailed_timing(edid_block: &mut [u8], info: &DisplayInfo) {
+ assert_eq!(edid_block.len(), 18);
// Detailed timings
//
@@ -196,28 +191,28 @@
let mut clock: u16 = ((info.refresh_rate * htotal * vtotal) / 10000) as u16;
// Round to nearest 10khz.
clock = ((clock + 5) / 10) * 10;
- edid[block_offset..block_offset + 2].copy_from_slice(&clock.to_le_bytes());
+ edid_block[0..2].copy_from_slice(&clock.to_le_bytes());
let width_lsb: u8 = (info.width() & 0xFF) as u8;
let width_msb: u8 = ((info.width() >> 8) & 0x0F) as u8;
// Horizointal Addressable Video in pixels.
- edid[block_offset + 2] = width_lsb;
+ edid_block[2] = width_lsb;
// Horizontal blanking in pixels.
- edid[block_offset + 3] = horizontal_blanking_lsb;
+ edid_block[3] = horizontal_blanking_lsb;
// Upper bits of the two above vals.
- edid[block_offset + 4] = horizontal_blanking_msb | (width_msb << 4) as u8;
+ edid_block[4] = horizontal_blanking_msb | (width_msb << 4) as u8;
let vertical_active: u32 = info.height();
let vertical_active_lsb: u8 = (vertical_active & 0xFF) as u8;
let vertical_active_msb: u8 = ((vertical_active >> 8) & 0x0F) as u8;
// Vertical addressable video in *lines*
- edid[block_offset + 5] = vertical_active_lsb;
+ edid_block[5] = vertical_active_lsb;
// Vertical blanking in lines
- edid[block_offset + 6] = vertical_blanking_lsb;
+ edid_block[6] = vertical_blanking_lsb;
// Sigbits of the above.
- edid[block_offset + 7] = vertical_blanking_msb | (vertical_active_msb << 4);
+ edid_block[7] = vertical_blanking_msb | (vertical_active_msb << 4);
let horizontal_front_lsb: u8 = (info.horizontal_front & 0xFF) as u8; // least sig 8 bits
let horizontal_front_msb: u8 = ((info.horizontal_front >> 8) & 0x03) as u8; // most sig 2 bits
@@ -230,13 +225,13 @@
let vertical_sync_msb: u8 = ((info.vertical_sync >> 8) & 0x0F) as u8; // most sig 2 bits
// Horizontal front porch in pixels.
- edid[block_offset + 8] = horizontal_front_lsb;
+ edid_block[8] = horizontal_front_lsb;
// Horizontal sync pulse width in pixels.
- edid[block_offset + 9] = horizontal_sync_lsb;
+ edid_block[9] = horizontal_sync_lsb;
// LSB of vertical front porch and sync pulse
- edid[block_offset + 10] = vertical_sync_lsb | (vertical_front_lsb << 4);
+ edid_block[10] = vertical_sync_lsb | (vertical_front_lsb << 4);
// Upper 2 bits of these values.
- edid[block_offset + 11] = vertical_sync_msb
+ edid_block[11] = vertical_sync_msb
| (vertical_front_msb << 2)
| (horizontal_sync_msb << 4)
| (horizontal_front_msb << 6);
@@ -252,6 +247,26 @@
edid[5] = 0xFF;
edid[6] = 0xFF;
edid[7] = 0x00;
+
+ let manufacturer_name: [char; 3] = ['G', 'G', 'L'];
+ // 00001 -> A, 00010 -> B, etc
+ let manufacturer_id: u16 = manufacturer_name
+ .iter()
+ .map(|c| (*c as u8 - b'A' + 1) & 0x1F)
+ .fold(0u16, |res, lsb| (res << 5) | (lsb as u16));
+ edid[8..10].copy_from_slice(&manufacturer_id.to_be_bytes());
+
+ let manufacture_product_id: u16 = 1;
+ edid[10..12].copy_from_slice(&manufacture_product_id.to_le_bytes());
+
+ let serial_id: u32 = 1;
+ edid[12..16].copy_from_slice(&serial_id.to_le_bytes());
+
+ let manufacture_week: u8 = 8;
+ edid[16] = manufacture_week;
+
+ let manufacture_year: u32 = 2022;
+ edid[17] = (manufacture_year - 1990u32) as u8;
}
// The standard timings are 8 timing modes with a lower priority (and different data format)