From 08364e38dec37cb77ccc873e897c69d23b33c3e5 Mon Sep 17 00:00:00 2001 From: Daniel Palmer Date: Fri, 31 Jul 2026 21:19:12 +0900 Subject: [PATCH] fbdev: tdfxfb: Manually boot unbooted cards If the card is detected as being unbooted it isn't too difficult to use the config table in its BIOS to fire it up so do it. Signed-off-by: Daniel Palmer Signed-off-by: Helge Deller --- drivers/video/fbdev/tdfxfb.c | 40 +++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c index 913624ebf805..74a8dfef1d9d 100644 --- a/drivers/video/fbdev/tdfxfb.c +++ b/drivers/video/fbdev/tdfxfb.c @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -418,9 +419,13 @@ static bool tdfxfb_get_bios_cfg(struct pci_dev *pdev, * Try to work out if the card was booted or not, just checks if * one of the dram config registers matches what is in the config * table if there is one. + * + * If we have a BIOS config table attempt to manually boot the + * card if needed. */ static int tdfxfb_hw_init(struct fb_info *info, struct pci_dev *pdev) { + u32 mempll, gfxpll, draminit0, draminit1, miscinit1, dram_mode; struct tdfx_par *par = info->par; struct tdfx_bios_cfg cfg; bool have_cfg = tdfxfb_get_bios_cfg(pdev, &cfg); @@ -436,10 +441,39 @@ static int tdfxfb_hw_init(struct fb_info *info, struct pci_dev *pdev) if (tdfx_inl(par, DRAMINIT0) == le32_to_cpu(cfg.draminit0)) return 0; - dev_err(&pdev->dev, - "Card hasn't booted and is unusable\n"); + dev_info(&pdev->dev, + "Manually booting card using config table\n"); - return -ENODEV; + mempll = le32_to_cpu(cfg.pllctrl1); + gfxpll = le32_to_cpu(cfg.pllctrl2); + draminit0 = le32_to_cpu(cfg.draminit0); + draminit1 = le32_to_cpu(cfg.draminit1); + miscinit1 = le32_to_cpu(cfg.miscinit1); + dram_mode = le32_to_cpu(cfg.sgrammode); + tdfx_outl(par, PCIINIT0, le32_to_cpu(cfg.pciinit0)); + tdfx_outl(par, AGPINIT, le32_to_cpu(cfg.agpinit0)); + + /* memory clock, and the graphics clock if the card wants one */ + tdfx_outl(par, PLLCTRL1, mempll); + if (gfxpll) + tdfx_outl(par, PLLCTRL2, gfxpll); + /* flush posted writes */ + tdfx_inl(par, PLLCTRL1); + /* PLL lock */ + udelay(100); + + tdfx_outl(par, MISCINIT1, miscinit1); + tdfx_outl(par, DRAMINIT0, draminit0); + tdfx_outl(par, DRAMINIT1, draminit1); + + /* SDRAM/SGRAM wake up: load the mode register */ + tdfx_outl(par, DRAMDATA, dram_mode); + tdfx_outl(par, DRAMCOMMAND, 0x10d); + + tdfx_outl(par, LFBMEMORYCONFIG, 0x00001fff); + tdfx_outl(par, MISCINIT0, le32_to_cpu(cfg.miscinit0)); + + return 0; } static void do_write_regs(struct fb_info *info, struct banshee_reg *reg)