[PATCH v2 3/5] fbdev: tdfxfb: Manually boot unbooted cards
Daniel Palmer <[email protected]> Fri, 31 Jul 2026 21:19:12 +0900
| Newsgroups | org.kernel.vger.linux-fbdev,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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 465c46edf6e7..4d92ab5b5430 100644 --- a/drivers/video/fbdev/tdfxfb.c +++ b/drivers/video/fbdev/tdfxfb.c @@ -67,6 +67,7 @@ #include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> +#include <linux/delay.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> @@ -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"); + + 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 -ENODEV; + return 0; } static void do_write_regs(struct fb_info *info, struct banshee_reg *reg) -- 2.53.0