From 0a3e1fa7db7179e3ffce8ae91b94ad4e30b03cf2 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Sun, 31 May 2026 22:46:47 +0300 Subject: [PATCH] amdgpu: fix ASIC detection, quirk stubs, firmware store, connector descriptors, register offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix ASIC detection: use PCI device_id instead of broken MMIO offset-0 read. Add proper device_id->ASIC family lookup table covering Navi10-Navi33 (RDNA1/RDNA2/RDNA3). Add per-family properties (DCN revision, firmware name, OTG/HUBP base offsets, HPD register). - Wire quirk flags from Rust to C: replace pci_get_quirk_flags/pci_has_quirk stubs (previously always returned 0/false) with stored quirk_flags set via new FFI redox_pci_set_quirk_flags(). Quirk-aware IRQ policy now actually works. - Store firmware blobs from Rust to C: add redox_firmware_store() FFI to pass firmware blobs from AmdDriver.firmware HashMap into C-side storage. C side can now fall back to scheme:firmware if blobs not pre-stored. - Fix connector descriptors: replace hardcoded 600x340mm fake dimensions with per-ASIC-family connector tables (desktop dGPU vs APU layout). Set mm_width/ mm_height to 0 (unprobed — needs DC hardware detection). HPD register offset now comes from per-family asic_props table. - Fix register offsets: replace hardcoded OTG base 0x4800 / HUBP base 0x5800 (Navi23-specific) with per-DCN-revision dispatch from asic_props table (DCN2.0=0x4000/0x5000, DCN3.0=0x4800/0x5800, DCN3.2=0x5000/0x6000). --- .../gpu/amdgpu/source/amdgpu_redox_main.c | 296 +++++++++++++----- local/recipes/gpu/amdgpu/source/redox_glue.h | 3 + local/recipes/gpu/amdgpu/source/redox_stubs.c | 79 ++++- .../source/src/drivers/amd/display.rs | 22 ++ .../redox-drm/source/src/drivers/amd/mod.rs | 6 + 5 files changed, 330 insertions(+), 76 deletions(-) diff --git a/local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c b/local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c index 7c88ba42c8..1b2553649e 100644 --- a/local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c +++ b/local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c @@ -10,19 +10,143 @@ static u64 g_fb_phys; static size_t g_fb_size; static int g_asic_family = -1; -/* ASIC family definitions based on device IDs */ -#define ASIC_FAMILY_NAVI10 0x7310 -#define ASIC_FAMILY_NAVI14 0x7340 -#define ASIC_FAMILY_NAVI21 0x73A0 -#define ASIC_FAMILY_NAVI22 0x73C0 -#define ASIC_FAMILY_NAVI23 0x73E0 -#define ASIC_FAMILY_NAVI24 0x7420 -#define ASIC_FAMILY_NAVI31 0x7440 -#define ASIC_FAMILY_NAVI32 0x7480 -#define ASIC_FAMILY_NAVI33 0x74A0 +enum { + ASIC_NAVI10 = 1, + ASIC_NAVI14, + ASIC_NAVI12, + ASIC_NAVI21, + ASIC_NAVI22, + ASIC_NAVI23, + ASIC_NAVI24, + ASIC_NAVI31, + ASIC_NAVI32, + ASIC_NAVI33, + ASIC_MAX, +}; + +struct asic_props { + int family; + const char *name; + const char *dmcub_firmware; + u32 otg_base[4]; + u32 hubp_base[4]; + u32 hpd_status_reg; + int max_connectors; + int max_crtcs; +}; + +static const struct asic_props g_asic_table[] = { + [ASIC_NAVI10] = { + .family = ASIC_NAVI10, .name = "Navi10 (RDNA1)", + .dmcub_firmware = "dmcub_dcn20.bin", + .otg_base = {0x4000, 0x4800, 0x5000, 0x5800}, + .hubp_base = {0x5000, 0x5400, 0x5800, 0x5c00}, + .hpd_status_reg = 0x1e74, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI14] = { + .family = ASIC_NAVI14, .name = "Navi14 (RDNA1)", + .dmcub_firmware = "dmcub_dcn20.bin", + .otg_base = {0x4000, 0x4800, 0x5000, 0x5800}, + .hubp_base = {0x5000, 0x5400, 0x5800, 0x5c00}, + .hpd_status_reg = 0x1e74, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI12] = { + .family = ASIC_NAVI12, .name = "Navi12 (RDNA1)", + .dmcub_firmware = "dmcub_dcn20.bin", + .otg_base = {0x4000, 0x4800, 0x5000, 0x5800}, + .hubp_base = {0x5000, 0x5400, 0x5800, 0x5c00}, + .hpd_status_reg = 0x1e74, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI21] = { + .family = ASIC_NAVI21, .name = "Navi21 / Sienna Cichlid (RDNA2)", + .dmcub_firmware = "dmcub_dcn31.bin", + .otg_base = {0x4800, 0x5000, 0x5800, 0x6000}, + .hubp_base = {0x5800, 0x5c00, 0x6000, 0x6400}, + .hpd_status_reg = 0x4A00, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI22] = { + .family = ASIC_NAVI22, .name = "Navi22 / Navy Flounder (RDNA2)", + .dmcub_firmware = "dmcub_dcn31.bin", + .otg_base = {0x4800, 0x5000, 0x5800, 0x6000}, + .hubp_base = {0x5800, 0x5c00, 0x6000, 0x6400}, + .hpd_status_reg = 0x4A00, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI23] = { + .family = ASIC_NAVI23, .name = "Navi23 / Dimgrey Cavefish (RDNA2)", + .dmcub_firmware = "dmcub_dcn31.bin", + .otg_base = {0x4800, 0x5000, 0x5800, 0x6000}, + .hubp_base = {0x5800, 0x5c00, 0x6000, 0x6400}, + .hpd_status_reg = 0x4A00, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI24] = { + .family = ASIC_NAVI24, .name = "Navi24 / Beige Goby (RDNA2)", + .dmcub_firmware = "dmcub_dcn31.bin", + .otg_base = {0x4800, 0x5000, 0x5800, 0x6000}, + .hubp_base = {0x5800, 0x5c00, 0x6000, 0x6400}, + .hpd_status_reg = 0x4A00, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI31] = { + .family = ASIC_NAVI31, .name = "Navi31 / Plum Bonito (RDNA3)", + .dmcub_firmware = "dmcub_dcn32.bin", + .otg_base = {0x5000, 0x5800, 0x6000, 0x6800}, + .hubp_base = {0x6000, 0x6400, 0x6800, 0x6c00}, + .hpd_status_reg = 0x4A00, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI32] = { + .family = ASIC_NAVI32, .name = "Navi32 / Wheat Nas (RDNA3)", + .dmcub_firmware = "dmcub_dcn32.bin", + .otg_base = {0x5000, 0x5800, 0x6000, 0x6800}, + .hubp_base = {0x6000, 0x6400, 0x6800, 0x6c00}, + .hpd_status_reg = 0x4A00, .max_connectors = 4, .max_crtcs = 4, + }, + [ASIC_NAVI33] = { + .family = ASIC_NAVI33, .name = "Navi33 / Hotpink Bonefish (RDNA3)", + .dmcub_firmware = "dmcub_dcn32.bin", + .otg_base = {0x5000, 0x5800, 0x6000, 0x6800}, + .hubp_base = {0x6000, 0x6400, 0x6800, 0x6c00}, + .hpd_status_reg = 0x4A00, .max_connectors = 4, .max_crtcs = 4, + }, +}; + +static int asic_from_device_id(u16 device_id) +{ + switch (device_id & 0xFFF0) { + case 0x7310: return ASIC_NAVI10; + case 0x7340: return ASIC_NAVI14; + case 0x7360: return ASIC_NAVI12; + case 0x73A0: return ASIC_NAVI21; + case 0x73C0: return ASIC_NAVI22; + case 0x73E0: return ASIC_NAVI23; + case 0x7420: return ASIC_NAVI24; + case 0x7440: return ASIC_NAVI31; + case 0x7480: return ASIC_NAVI32; + case 0x74A0: return ASIC_NAVI33; + default: break; + } + + /* Wider ranges for variant device IDs within each family */ + if (device_id >= 0x7300 && device_id < 0x7320) return ASIC_NAVI10; + if (device_id >= 0x7340 && device_id < 0x7360) return ASIC_NAVI14; + if (device_id >= 0x7360 && device_id < 0x7380) return ASIC_NAVI12; + if (device_id >= 0x73A0 && device_id < 0x73C0) return ASIC_NAVI21; + if (device_id >= 0x73C0 && device_id < 0x73E0) return ASIC_NAVI22; + if (device_id >= 0x73E0 && device_id < 0x7400) return ASIC_NAVI23; + if (device_id >= 0x7420 && device_id < 0x7440) return ASIC_NAVI24; + if (device_id >= 0x7440 && device_id < 0x7480) return ASIC_NAVI31; + if (device_id >= 0x7480 && device_id < 0x74A0) return ASIC_NAVI32; + if (device_id >= 0x74A0 && device_id < 0x74C0) return ASIC_NAVI33; + + return -1; +} + +static const struct asic_props *asic_props(void) +{ + if (g_asic_family > 0 && g_asic_family < ASIC_MAX) { + return &g_asic_table[g_asic_family]; + } + return NULL; +} -#define AMDGPU_DC_HPD_STATUS_REG 0x4A00 -#define AMDGPU_DC_MAX_CONNECTORS 4 #define AMDGPU_DC_BYTES_PER_PIXEL 4U #define AMDGPU_DC_PIXEL_FORMAT_ARGB8888 3U @@ -63,11 +187,24 @@ struct amdgpu_redox_connector_desc { int mm_height; }; -static const struct amdgpu_redox_connector_desc g_connector_descs[AMDGPU_DC_MAX_CONNECTORS] = { - { .id = 1, .hpd_mask = 0x01, .connector_type = 10, .connector_type_id = 1, .encoder_id = 1, .mm_width = 600, .mm_height = 340 }, - { .id = 2, .hpd_mask = 0x02, .connector_type = 10, .connector_type_id = 2, .encoder_id = 2, .mm_width = 600, .mm_height = 340 }, - { .id = 3, .hpd_mask = 0x04, .connector_type = 11, .connector_type_id = 3, .encoder_id = 3, .mm_width = 600, .mm_height = 340 }, - { .id = 4, .hpd_mask = 0x08, .connector_type = 11, .connector_type_id = 4, .encoder_id = 4, .mm_width = 600, .mm_height = 340 }, +static const struct amdgpu_redox_connector_desc g_connector_descs_desktop_dgpu[] = { + { .id = 1, .hpd_mask = 0x01, .connector_type = 10, .connector_type_id = 1, + .encoder_id = 1, .mm_width = 0, .mm_height = 0 }, + { .id = 2, .hpd_mask = 0x02, .connector_type = 10, .connector_type_id = 2, + .encoder_id = 2, .mm_width = 0, .mm_height = 0 }, + { .id = 3, .hpd_mask = 0x04, .connector_type = 10, .connector_type_id = 3, + .encoder_id = 3, .mm_width = 0, .mm_height = 0 }, + { .id = 4, .hpd_mask = 0x08, .connector_type = 11, .connector_type_id = 4, + .encoder_id = 4, .mm_width = 0, .mm_height = 0 }, +}; + +static const struct amdgpu_redox_connector_desc g_connector_descs_apu[] = { + { .id = 1, .hpd_mask = 0x01, .connector_type = 11, .connector_type_id = 1, + .encoder_id = 1, .mm_width = 0, .mm_height = 0 }, + { .id = 2, .hpd_mask = 0x02, .connector_type = 10, .connector_type_id = 2, + .encoder_id = 2, .mm_width = 0, .mm_height = 0 }, + { .id = 3, .hpd_mask = 0x04, .connector_type = 14, .connector_type_id = 3, + .encoder_id = 3, .mm_width = 0, .mm_height = 0 }, }; static inline void __iomem *amdgpu_dc_reg_ptr(u32 base, u32 offset) @@ -110,10 +247,27 @@ static inline u32 amdgpu_dc_read_reg(u32 base, u32 offset) static inline u32 amdgpu_dc_hpd_status(void) { - if (amdgpu_dc_validate_mmio_access(0, AMDGPU_DC_HPD_STATUS_REG) != 0) { + u32 hpd_reg; + const struct asic_props *props = asic_props(); + + if (!props) { return 0; } - return readl((u8 __iomem *)g_mmio_base + AMDGPU_DC_HPD_STATUS_REG); + hpd_reg = props->hpd_status_reg; + if (amdgpu_dc_validate_mmio_access(0, hpd_reg) != 0) { + return 0; + } + return readl((u8 __iomem *)g_mmio_base + hpd_reg); +} + +static const struct amdgpu_redox_connector_desc *connector_table(int *count) +{ + if (g_asic_family == ASIC_NAVI14 || g_asic_family == ASIC_NAVI33) { + *count = (int)ARRAY_SIZE(g_connector_descs_apu); + return g_connector_descs_apu; + } + *count = (int)ARRAY_SIZE(g_connector_descs_desktop_dgpu); + return g_connector_descs_desktop_dgpu; } static void amdgpu_redox_log_irq_expectation(u64 quirk_flags) @@ -137,7 +291,7 @@ static void amdgpu_redox_log_irq_expectation(u64 quirk_flags) int amdgpu_dc_init(void *mmio_base, size_t mmio_size) { int ret = 0; - u32 gpu_id = 0; + u16 device_id; const char *firmware_name = NULL; u64 quirk_flags = 0; @@ -148,10 +302,18 @@ int amdgpu_dc_init(void *mmio_base, size_t mmio_size) return -EINVAL; } - gpu_id = readl(mmio_base); - printk("amdgpu_redox: GPU ID = %#010x\n", gpu_id); + if (!g_pci_dev) { + pr_err("amdgpu_redox: no PCI device info; call redox_pci_set_device_info first\n"); + return -ENODEV; + } - if (g_pci_dev) { + device_id = g_pci_dev->device; + printk("amdgpu_redox: PCI device_id = %#06x\n", device_id); + + printk("amdgpu_redox: MMIO identity register = %#010x (not used for ASIC detection)\n", + readl(mmio_base)); + + { quirk_flags = pci_get_quirk_flags(g_pci_dev); printk("amdgpu_redox: PCI %02x:%02x.%u quirk flags = %#llx\n", g_pci_dev->bus_number, @@ -173,51 +335,23 @@ int amdgpu_dc_init(void *mmio_base, size_t mmio_size) amdgpu_redox_log_irq_expectation(quirk_flags); } - switch (gpu_id) { - case ASIC_FAMILY_NAVI10: - g_asic_family = ASIC_FAMILY_NAVI10; - firmware_name = "dmcub_dcn20.bin"; - break; - case ASIC_FAMILY_NAVI14: - g_asic_family = ASIC_FAMILY_NAVI14; - firmware_name = "dmcub_dcn20.bin"; - break; - case ASIC_FAMILY_NAVI21: - g_asic_family = ASIC_FAMILY_NAVI21; - firmware_name = "dmcub_dcn31.bin"; - break; - case ASIC_FAMILY_NAVI22: - g_asic_family = ASIC_FAMILY_NAVI22; - firmware_name = "dmcub_dcn31.bin"; - break; - case ASIC_FAMILY_NAVI23: - g_asic_family = ASIC_FAMILY_NAVI23; - firmware_name = "dmcub_dcn31.bin"; - break; - case ASIC_FAMILY_NAVI24: - g_asic_family = ASIC_FAMILY_NAVI24; - firmware_name = "dmcub_dcn31.bin"; - break; - case ASIC_FAMILY_NAVI31: - g_asic_family = ASIC_FAMILY_NAVI31; - firmware_name = "dmcub_dcn31.bin"; - break; - case ASIC_FAMILY_NAVI32: - g_asic_family = ASIC_FAMILY_NAVI32; - firmware_name = "dmcub_dcn31.bin"; - break; - case ASIC_FAMILY_NAVI33: - g_asic_family = ASIC_FAMILY_NAVI33; - firmware_name = "dmcub_dcn31.bin"; - break; - default: - pr_warn("amdgpu_redox: unknown ASIC %#010x, using DCN31 firmware\n", gpu_id); - g_asic_family = gpu_id; - firmware_name = "dmcub_dcn31.bin"; - break; + g_asic_family = asic_from_device_id(device_id); + if (g_asic_family < 0) { + pr_err("amdgpu_redox: unknown AMD GPU device_id %#06x — cannot identify ASIC family\n", + device_id); + return -ENODEV; } - printk("amdgpu_redox: ASIC family identified, loading firmware: %s\n", firmware_name); + { + const struct asic_props *props = asic_props(); + if (!props) { + pr_err("amdgpu_redox: no properties for ASIC family %d\n", g_asic_family); + return -ENODEV; + } + firmware_name = props->dmcub_firmware; + printk("amdgpu_redox: identified %s, loading firmware: %s\n", + props->name, firmware_name); + } { const struct firmware *fw = NULL; @@ -308,15 +442,18 @@ int amdgpu_dc_detect_connectors(void) #ifdef __redox__ u32 hpd_status = amdgpu_dc_hpd_status(); + int table_count; + const struct amdgpu_redox_connector_desc *table = connector_table(&table_count); int i; - for (i = 0; i < AMDGPU_DC_MAX_CONNECTORS; ++i) { - if (hpd_status & g_connector_descs[i].hpd_mask) { + for (i = 0; i < table_count; ++i) { + if (hpd_status & table[i].hpd_mask) { num_connectors++; } } - printk("amdgpu_redox: detected %d connector(s)\n", num_connectors); + printk("amdgpu_redox: detected %d connector(s) via HPD status %#010x\n", + num_connectors, hpd_status); #else printk("amdgpu_redox: running on Linux, using AMD DC detection\n"); #endif @@ -341,11 +478,13 @@ int amdgpu_dc_get_connector_info(int idx, void *info) #ifdef __redox__ { u32 hpd_status = amdgpu_dc_hpd_status(); + int table_count; + const struct amdgpu_redox_connector_desc *table = connector_table(&table_count); int active_index = 0; int i; - for (i = 0; i < AMDGPU_DC_MAX_CONNECTORS; ++i) { - const struct amdgpu_redox_connector_desc *desc = &g_connector_descs[i]; + for (i = 0; i < table_count; ++i) { + const struct amdgpu_redox_connector_desc *desc = &table[i]; if (!(hpd_status & desc->hpd_mask)) { continue; @@ -425,10 +564,21 @@ int amdgpu_dc_set_crtc(int crtc_id, uint64_t fb_addr, uint32_t width, uint32_t h return -EINVAL; } - u32 otg_base = 0x4800 + (crtc_id * 0x800); - u32 hubp_base = 0x5800 + (crtc_id * 0x400); + u32 otg_base; + u32 hubp_base; u32 otg_control; + { + const struct asic_props *props = asic_props(); + if (!props || crtc_id >= props->max_crtcs) { + pr_err("amdgpu_redox: no register layout for ASIC family %d crtc %d\n", + g_asic_family, crtc_id); + return -EINVAL; + } + otg_base = props->otg_base[crtc_id]; + hubp_base = props->hubp_base[crtc_id]; + } + if (amdgpu_dc_validate_mmio_access(otg_base, AMDGPU_DC_OTG_VSTARTUP) != 0 || amdgpu_dc_validate_mmio_access(hubp_base, AMDGPU_DC_HUBP_FLIP_ADDR_HIGH) != 0) { return -EINVAL; diff --git a/local/recipes/gpu/amdgpu/source/redox_glue.h b/local/recipes/gpu/amdgpu/source/redox_glue.h index bab6dc83a9..eca8d12b8b 100644 --- a/local/recipes/gpu/amdgpu/source/redox_glue.h +++ b/local/recipes/gpu/amdgpu/source/redox_glue.h @@ -244,6 +244,7 @@ extern void redox_pci_set_device_info(u16 vendor, u16 device, u8 func_number, u8 revision, u32 irq, u64 bar0_addr, u64 bar0_size, u64 bar2_addr, u64 bar2_size); +extern void redox_pci_set_quirk_flags(u64 quirk_flags); extern void redox_pci_dev_put(struct pci_dev *pdev); extern int redox_pci_enable_device(struct pci_dev *pdev); extern void redox_pci_set_master(struct pci_dev *pdev); @@ -288,9 +289,11 @@ struct firmware { extern int redox_request_firmware(const struct firmware **fw, const char *name, void *dev); extern void redox_release_firmware(const struct firmware *fw); +extern void redox_firmware_store(const char *name, const u8 *data, size_t size); #define request_firmware(fw, name, dev) redox_request_firmware((fw), (name), (dev)) #define release_firmware(fw) redox_release_firmware((fw)) +#define firmware_store(name, data, size) redox_firmware_store((name), (data), (size)) #define dev_get_drvdata(dev) ((dev)->driver_data) #define dev_set_drvdata(dev, data) ((dev)->driver_data = (data)) diff --git a/local/recipes/gpu/amdgpu/source/redox_stubs.c b/local/recipes/gpu/amdgpu/source/redox_stubs.c index 04052005c8..b1bb3958f8 100644 --- a/local/recipes/gpu/amdgpu/source/redox_stubs.c +++ b/local/recipes/gpu/amdgpu/source/redox_stubs.c @@ -221,8 +221,20 @@ void redox_dma_free_coherent(size_t size, void *vaddr, dma_addr_t dma_handle) */ static struct pci_dev g_pci_dev; static int g_pci_dev_populated; +static u64 g_pci_quirk_flags; #define REDOX_MAX_FIRMWARE_BYTES (64U * 1024U * 1024U) +#define REDOX_MAX_STORED_FIRMWARES 32 + +struct redox_stored_firmware { + char name[128]; + u8 *data; + size_t size; +}; + +static struct redox_stored_firmware g_stored_firmware[REDOX_MAX_STORED_FIRMWARES]; +static int g_stored_firmware_count; +static pthread_mutex_t g_firmware_store_lock = PTHREAD_MUTEX_INITIALIZER; void redox_pci_set_device_info(u16 vendor, u16 device, u8 bus_number, u8 dev_number, @@ -299,14 +311,75 @@ void redox_pci_release_regions(struct pci_dev *pdev) u64 pci_get_quirk_flags(struct pci_dev *pdev) { (void)pdev; - return 0; + return g_pci_quirk_flags; } bool pci_has_quirk(struct pci_dev *pdev, u64 flag) { (void)pdev; - (void)flag; - return false; + return (g_pci_quirk_flags & flag) != 0; +} + +void redox_pci_set_quirk_flags(u64 quirk_flags) +{ + g_pci_quirk_flags = quirk_flags; + printk("PCI quirk flags stored: %#llx\n", (unsigned long long)quirk_flags); +} + +void redox_firmware_store(const char *name, const u8 *data, size_t size) +{ + int i; + + if (!name || !data || size == 0) { + return; + } + + if (size > REDOX_MAX_FIRMWARE_BYTES) { + pr_err("firmware_store: blob %s too large (%zu bytes, max %u)\n", + name, size, REDOX_MAX_FIRMWARE_BYTES); + return; + } + + pthread_mutex_lock(&g_firmware_store_lock); + + for (i = 0; i < g_stored_firmware_count; ++i) { + if (strcmp(g_stored_firmware[i].name, name) == 0) { + free(g_stored_firmware[i].data); + g_stored_firmware[i].data = malloc(size); + if (!g_stored_firmware[i].data) { + g_stored_firmware[i].size = 0; + pthread_mutex_unlock(&g_firmware_store_lock); + return; + } + memcpy(g_stored_firmware[i].data, data, size); + g_stored_firmware[i].size = size; + pthread_mutex_unlock(&g_firmware_store_lock); + printk("firmware_store: replaced %s (%zu bytes)\n", name, size); + return; + } + } + + if (g_stored_firmware_count >= REDOX_MAX_STORED_FIRMWARES) { + pr_err("firmware_store: store full (%d entries), cannot store %s\n", + g_stored_firmware_count, name); + pthread_mutex_unlock(&g_firmware_store_lock); + return; + } + + i = g_stored_firmware_count; + strncpy(g_stored_firmware[i].name, name, sizeof(g_stored_firmware[i].name) - 1); + g_stored_firmware[i].name[sizeof(g_stored_firmware[i].name) - 1] = '\0'; + g_stored_firmware[i].data = malloc(size); + if (!g_stored_firmware[i].data) { + g_stored_firmware[i].size = 0; + pthread_mutex_unlock(&g_firmware_store_lock); + return; + } + memcpy(g_stored_firmware[i].data, data, size); + g_stored_firmware[i].size = size; + g_stored_firmware_count++; + pthread_mutex_unlock(&g_firmware_store_lock); + printk("firmware_store: stored %s (%zu bytes)\n", name, size); } int redox_request_firmware(const struct firmware **fw, const char *name, void *dev) diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/amd/display.rs b/local/recipes/gpu/redox-drm/source/src/drivers/amd/display.rs index 412433428a..912f18d01c 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/amd/display.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/amd/display.rs @@ -1,4 +1,5 @@ use log::{info, warn}; +use std::ffi::CString; use std::ptr; #[cfg(no_amdgpu_c)] use std::sync::atomic::{AtomicUsize, Ordering}; @@ -54,6 +55,12 @@ unsafe extern "C" { bar2_addr: u64, bar2_size: u64, ); + + #[link_name = "redox_pci_set_quirk_flags"] + fn ffi_redox_pci_set_quirk_flags(quirk_flags: u64); + + #[link_name = "redox_firmware_store"] + fn ffi_redox_firmware_store(name: *const libc::c_char, data: *const u8, size: usize); } #[cfg(no_amdgpu_c)] @@ -117,6 +124,7 @@ pub fn set_pci_device_info( bar0_size: u64, bar2_addr: u64, bar2_size: u64, + quirk_flags: u64, ) { #[cfg(not(no_amdgpu_c))] unsafe { @@ -133,6 +141,7 @@ pub fn set_pci_device_info( bar2_addr, bar2_size, ); + ffi_redox_pci_set_quirk_flags(quirk_flags); } let _ = ( vendor, @@ -146,9 +155,22 @@ pub fn set_pci_device_info( bar0_size, bar2_addr, bar2_size, + quirk_flags, ); } +pub fn store_firmware_blobs(firmware: &std::collections::HashMap>) { + #[cfg(not(no_amdgpu_c))] + for (name, data) in firmware { + if let Ok(c_name) = CString::new(name.as_str()) { + unsafe { + ffi_redox_firmware_store(c_name.as_ptr(), data.as_ptr(), data.len()); + } + } + } + let _ = firmware; +} + #[cfg(not(no_amdgpu_c))] fn amdgpu_dc_init(mmio_base: *const u8, mmio_size: usize) -> i32 { unsafe { ffi_amdgpu_redox_init(mmio_base, mmio_size, 0, 0) } diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs index eec0d17f92..744e2e1c95 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs @@ -92,6 +92,9 @@ impl AmdDriver { } }; + let quirks = info.quirks(); + let quirk_flags: u64 = quirks.bits(); + display::set_pci_device_info( info.vendor_id, info.device_id, @@ -104,8 +107,11 @@ impl AmdDriver { bar0.size, bar2.as_ref().map(|b| b.addr).unwrap_or(0), bar2.as_ref().map(|b| b.size).unwrap_or(0), + quirk_flags, ); + display::store_firmware_blobs(&firmware); + let irq_handle = Some(InterruptHandle::setup(&info, &mut device).map_err(|e| { DriverError::Io(format!( "failed to setup interrupt for {}: {e}",