Opened 6 years ago
Last modified 6 years ago
#15044 new bug
Radeon RX Vega M GH: Monitor going out of sync.
Reported by: | bga | Owned by: | kallisti5 |
---|---|---|---|
Priority: | normal | Milestone: | Unscheduled |
Component: | Drivers/Graphics/radeon_hd | Version: | R1/Development |
Keywords: | Cc: | ||
Blocked By: | Blocking: | ||
Platform: | All |
Description
I have a NUC 8 computer that has the card mentioned in the summary. The PCI ID (0x694c) was not present in the existing driver so I added it:
diff --git a/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp b/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp index 6e00eb6511..a7ccd6ef3c 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp @@ -544,7 +544,8 @@ const struct supported_device { {0x6867, 13, 0, RADEON_VEGA, CHIP_STD, "Radeon RX Vega 56"}, {0x687f, 13, 0, RADEON_VEGA, CHIP_STD, "Radeon RX Vega 64"}, {0x684c, 13, 0, RADEON_VEGA, CHIP_STD, "Radeon RX Vega M GH"}, - {0x684e, 13, 0, RADEON_VEGA, CHIP_STD, "Radeon RX Vega M GL"} + {0x684e, 13, 0, RADEON_VEGA, CHIP_STD, "Radeon RX Vega M GL"}, + {0x694c, 13, 0, RADEON_VEGA, CHIP_STD, "Radeon RX Vega M GH"} };
The driver then detects and tries to initialize the graphics card, but my monitor goes out of sync.
Attached is the radeon_hd information from syslog (from the point it detected the monitor connected to the HDMI port to when log information for radeon_hd finished. Let me know if you need the log before that too).
In case it matters, the monitor is connected to the computer through a KVM (but the KVM has EDID emulation so it should not be an issue and works with other OSs).
Let me kinow if you need more information.
Attachments (1)
Change History (10)
by , 6 years ago
comment:1 by , 6 years ago
Forgot to include at least the basic monitor information. Sorry.
Monitor has a maximum resolution of 4k@30Hz. All other resolutions are locked to 60Hz.
comment:2 by , 6 years ago
I connected the monitor directly to the computer (bypassing the KVM). Same issue.
comment:3 by , 6 years ago
Ah, I don't have any Vega cards to test here. However, this is the most telling part:
WARNING: CHECK NEW DCE mmDC_GPIO_HPD_A value!
That warning means the accelerant has detected an unknown define/instruction coming from the AtomBIOS on the card.
Someone likely needs to look at the linux drm code for radeon_hd and see what additions have been made around mmDC_GPIO_HPD_A or in the AtomBIOS headers.
comment:4 by , 6 years ago
comment:5 by , 6 years ago
Hmmm, that patchset only seems to define mmDC_GPIO_HPD_A, but I can not find it being used anywhere.
comment:7 by , 6 years ago
Or maybe this?
static bool offset_to_id( uint32_t offset, uint32_t mask, enum gpio_id *id, uint32_t *en) { switch (offset) { /* GENERIC */ case mmDC_GPIO_GENERIC_A: *id = GPIO_ID_GENERIC; switch (mask) { case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: *en = GPIO_GENERIC_A; return true; case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: *en = GPIO_GENERIC_B; return true; case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: *en = GPIO_GENERIC_C; return true; case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: *en = GPIO_GENERIC_D; return true; case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: *en = GPIO_GENERIC_E; return true; case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: *en = GPIO_GENERIC_F; return true; case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: *en = GPIO_GENERIC_G; return true; default: ASSERT_CRITICAL(false); return false; } break; /* HPD */ case mmDC_GPIO_HPD_A: *id = GPIO_ID_HPD; switch (mask) { case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: *en = GPIO_HPD_1; return true; case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: *en = GPIO_HPD_2; return true; case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: *en = GPIO_HPD_3; return true; case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: *en = GPIO_HPD_4; return true; case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: *en = GPIO_HPD_5; return true; case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: *en = GPIO_HPD_6; return true; default: ASSERT_CRITICAL(false); return false; } break; /* SYNCA */ case mmDC_GPIO_SYNCA_A: *id = GPIO_ID_SYNC; switch (mask) { case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: *en = GPIO_SYNC_HSYNC_A; return true; case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: *en = GPIO_SYNC_VSYNC_A; return true; default: ASSERT_CRITICAL(false); return false; } break; /* mmDC_GPIO_GENLK_MASK */ case mmDC_GPIO_GENLK_A: *id = GPIO_ID_GSL; switch (mask) { case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: *en = GPIO_GSL_GENLOCK_CLOCK; return true; case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: *en = GPIO_GSL_GENLOCK_VSYNC; return true; case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: *en = GPIO_GSL_SWAPLOCK_A; return true; case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: *en = GPIO_GSL_SWAPLOCK_B; return true; default: ASSERT_CRITICAL(false); return false; } break; /* DDC */ /* we don't care about the GPIO_ID for DDC * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK * directly in the create method */ case mmDC_GPIO_DDC1_A: *en = GPIO_DDC_LINE_DDC1; return true; case mmDC_GPIO_DDC2_A: *en = GPIO_DDC_LINE_DDC2; return true; case mmDC_GPIO_DDC3_A: *en = GPIO_DDC_LINE_DDC3; return true; case mmDC_GPIO_DDC4_A: *en = GPIO_DDC_LINE_DDC4; return true; case mmDC_GPIO_DDC5_A: *en = GPIO_DDC_LINE_DDC5; return true; case mmDC_GPIO_DDC6_A: *en = GPIO_DDC_LINE_DDC6; return true; case mmDC_GPIO_DDCVGA_A: *en = GPIO_DDC_LINE_DDC_VGA; return true; /* GPIO_I2CPAD */ case mmDC_GPIO_I2CPAD_A: *en = GPIO_DDC_LINE_I2C_PAD; return true; /* Not implemented */ case mmDC_GPIO_PWRSEQ_A: case mmDC_GPIO_PAD_STRENGTH_1: case mmDC_GPIO_PAD_STRENGTH_2: case mmDC_GPIO_DEBUG: return false; /* UNEXPECTED */ default: ASSERT_CRITICAL(false); return false; } }
And this:
static bool id_to_offset( enum gpio_id id, uint32_t en, struct gpio_pin_info *info) { bool result = true; switch (id) { case GPIO_ID_DDC_DATA: info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; switch (en) { case GPIO_DDC_LINE_DDC1: info->offset = mmDC_GPIO_DDC1_A; break; case GPIO_DDC_LINE_DDC2: info->offset = mmDC_GPIO_DDC2_A; break; case GPIO_DDC_LINE_DDC3: info->offset = mmDC_GPIO_DDC3_A; break; case GPIO_DDC_LINE_DDC4: info->offset = mmDC_GPIO_DDC4_A; break; case GPIO_DDC_LINE_DDC5: info->offset = mmDC_GPIO_DDC5_A; break; case GPIO_DDC_LINE_DDC6: info->offset = mmDC_GPIO_DDC6_A; break; case GPIO_DDC_LINE_DDC_VGA: info->offset = mmDC_GPIO_DDCVGA_A; break; case GPIO_DDC_LINE_I2C_PAD: info->offset = mmDC_GPIO_I2CPAD_A; break; default: ASSERT_CRITICAL(false); result = false; } break; case GPIO_ID_DDC_CLOCK: info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; switch (en) { case GPIO_DDC_LINE_DDC1: info->offset = mmDC_GPIO_DDC1_A; break; case GPIO_DDC_LINE_DDC2: info->offset = mmDC_GPIO_DDC2_A; break; case GPIO_DDC_LINE_DDC3: info->offset = mmDC_GPIO_DDC3_A; break; case GPIO_DDC_LINE_DDC4: info->offset = mmDC_GPIO_DDC4_A; break; case GPIO_DDC_LINE_DDC5: info->offset = mmDC_GPIO_DDC5_A; break; case GPIO_DDC_LINE_DDC6: info->offset = mmDC_GPIO_DDC6_A; break; case GPIO_DDC_LINE_DDC_VGA: info->offset = mmDC_GPIO_DDCVGA_A; break; case GPIO_DDC_LINE_I2C_PAD: info->offset = mmDC_GPIO_I2CPAD_A; break; default: ASSERT_CRITICAL(false); result = false; } break; case GPIO_ID_GENERIC: info->offset = mmDC_GPIO_GENERIC_A; switch (en) { case GPIO_GENERIC_A: info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; break; case GPIO_GENERIC_B: info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; break; case GPIO_GENERIC_C: info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; break; case GPIO_GENERIC_D: info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; break; case GPIO_GENERIC_E: info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; break; case GPIO_GENERIC_F: info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; break; case GPIO_GENERIC_G: info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; break; default: ASSERT_CRITICAL(false); result = false; } break; case GPIO_ID_HPD: info->offset = mmDC_GPIO_HPD_A; switch (en) { case GPIO_HPD_1: info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; break; case GPIO_HPD_2: info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; break; case GPIO_HPD_3: info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; break; case GPIO_HPD_4: info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; break; case GPIO_HPD_5: info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; break; case GPIO_HPD_6: info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; break; default: ASSERT_CRITICAL(false); result = false; } break; case GPIO_ID_SYNC: switch (en) { case GPIO_SYNC_HSYNC_A: info->offset = mmDC_GPIO_SYNCA_A; info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; break; case GPIO_SYNC_VSYNC_A: info->offset = mmDC_GPIO_SYNCA_A; info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; break; case GPIO_SYNC_HSYNC_B: case GPIO_SYNC_VSYNC_B: default: ASSERT_CRITICAL(false); result = false; } break; case GPIO_ID_GSL: switch (en) { case GPIO_GSL_GENLOCK_CLOCK: info->offset = mmDC_GPIO_GENLK_A; info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; break; case GPIO_GSL_GENLOCK_VSYNC: info->offset = mmDC_GPIO_GENLK_A; info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; break; case GPIO_GSL_SWAPLOCK_A: info->offset = mmDC_GPIO_GENLK_A; info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; break; case GPIO_GSL_SWAPLOCK_B: info->offset = mmDC_GPIO_GENLK_A; info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; break; default: ASSERT_CRITICAL(false); result = false; } break; case GPIO_ID_VIP_PAD: default: ASSERT_CRITICAL(false); result = false; } if (result) { info->offset_y = info->offset + 2; info->offset_en = info->offset + 1; info->offset_mask = info->offset - 1; info->mask_y = info->mask; info->mask_en = info->mask; info->mask_mask = info->mask; } return result; }
If you have any ideas about what these are doing and how to do the same in the Haiku radeon driver, I can give it a go *although it would be mostly cargo-cult).
comment:8 by , 6 years ago
ALl references to this in the Linux kernel:
https://github.com/torvalds/linux/search?q=mmDC_GPIO_HPD_A&unscoped_q=mmDC_GPIO_HPD_A
comment:9 by , 6 years ago
Also, the Linux considers this card to be a VEGAM. In case it matters, here are all references to VEGAM:
https://github.com/torvalds/linux/search?q=VEGAM&unscoped_q=VEGAM
radeon_hd partial syslog