summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Palmer <daniel@0x0f.com>2026-07-31 21:19:12 +0900
committerHelge Deller <deller@gmx.de>2026-08-10 08:13:26 +0200
commit08364e38dec37cb77ccc873e897c69d23b33c3e5 (patch)
treea3992c126d59bb990b5471569209b43cb2908045
parent28c1d44af69705936f00826e0b60fb6aec95f008 (diff)
downloadlinux-next-08364e38dec37cb77ccc873e897c69d23b33c3e5.tar.gz
linux-next-08364e38dec37cb77ccc873e897c69d23b33c3e5.zip
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 <daniel@0x0f.com> Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--drivers/video/fbdev/tdfxfb.c40
1 files 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 <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 @@ out:
* 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)