[PATCH 2/9] savagefb: Driver updates

DORMANTno replies

From: "Antonino A. Daplas" <adaplas@gmail.com>
Date: 2005-08-20 00:31:52
Subsystem: framebuffer layer, the rest · Maintainers: Helge Deller, Linus Torvalds

   1. Fallback to firmware EDID if chipset has no DDC/I2C support or if I2C
   probing failed

   2. Add fb_blank hook

   3. Fix savagefb_suspend/resume to enable driver to successfully suspend
   and resume from S3, memory or disk

   Signed-off-by: Antonino Daplas [off-list ref]
---

savagefb-i2c.c    |   16 ++++--
savagefb.h        |   13 ++++-
savagefb_driver.c |  139 +++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 147 insertions(+), 21 deletions(-)
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -259,8 +259,9 @@ static u8 *savage_do_probe_i2c_edid(stru
	return buf;
}

-int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
+int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
{
+	struct savagefb_par *par = info->par;
	u8 *edid = NULL;
	int i;
@@ -270,12 +271,19 @@ int savagefb_probe_i2c_connector(struct 		if (edid)
			break;
	}
+
+	if (!edid) {
+		/* try to get from firmware */
+		edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+		if (edid)
+			memcpy(edid, fb_firmware_edid(info->device),
+			       EDID_LENGTH);
+	}
+
	if (out_edid)
		*out_edid = edid;
-	if (!edid)
-		return 1;

-	return 0;
+	return (edid) ? 0 : 1;
}

MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -60,6 +60,7 @@
#define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))

+#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR))

/* Chip tags.  These are used to group the adapters into
 * related families.
@@ -73,6 +74,8 @@ typedef enum {
  S3_PROSAVAGE,
  S3_SUPERSAVAGE,
  S3_SAVAGE2000,
+  S3_PROSAVAGEDDR,
+  S3_TWISTER,
  S3_LAST
} savage_chipset;
@@ -128,6 +131,10 @@ typedef enum {
#define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
#define BCI_CMD_SEND_COLOR           0x00008000

+#define DISP_CRT     1
+#define DISP_LCD     2
+#define DISP_DFP     3
+
struct xtimings {
	unsigned int Clock;
	unsigned int HDisplay;
@@ -166,6 +173,10 @@ struct savagefb_par {
	struct savagefb_i2c_chan chan;
	unsigned char   *edid;
	u32 pseudo_palette[16];
+	int pm_state;
+	int display_type;
+	int dvi;
+	int crtonly;
	int dacSpeedBpp;
	int maxClock;
	int minClock;
@@ -338,7 +349,7 @@ do {                       \
	} \
}

-extern int savagefb_probe_i2c_connector(struct savagefb_par *par,
+extern int savagefb_probe_i2c_connector(struct fb_info *info,
					u8 **out_edid);
extern void savagefb_create_i2c_busses(struct fb_info *info);
extern void savagefb_delete_i2c_busses(struct fb_info *info);
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1400,6 +1400,58 @@ static int savagefb_pan_display (struct 	return 0;
}

+static int savagefb_blank(int blank, struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	u8 sr8 = 0, srd = 0;
+
+	if (par->display_type == DISP_CRT) {
+		vga_out8(0x3c4, 0x08);
+		sr8 = vga_in8(0x3c5);
+		sr8 |= 0x06;
+		vga_out8(0x3c5, sr8);
+		vga_out8(0x3c4, 0x0d);
+		srd = vga_in8(0x3c5);
+		srd &= 0x03;
+
+		switch (blank) {
+		case FB_BLANK_UNBLANK:
+		case FB_BLANK_NORMAL:
+			break;
+		case FB_BLANK_VSYNC_SUSPEND:
+			srd |= 0x10;
+			break;
+		case FB_BLANK_HSYNC_SUSPEND:
+			srd |= 0x40;
+			break;
+		case FB_BLANK_POWERDOWN:
+			srd |= 0x50;
+			break;
+		}
+
+		vga_out8(0x3c4, 0x0d);
+		vga_out8(0x3c5, srd);
+	}
+
+	if (par->display_type == DISP_LCD ||
+	    par->display_type == DISP_DFP) {
+		switch(blank) {
+		case FB_BLANK_UNBLANK:
+		case FB_BLANK_NORMAL:
+			vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+			vga_out8(0x3c5, vga_in8(0x3c5) | 0x10);
+			break;
+		case FB_BLANK_VSYNC_SUSPEND:
+		case FB_BLANK_HSYNC_SUSPEND:
+		case FB_BLANK_POWERDOWN:
+			vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+			vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10);
+			break;
+		}
+	}
+
+	return (blank == FB_BLANK_NORMAL) ? 1 : 0;
+}

static struct fb_ops savagefb_ops = {
	.owner          = THIS_MODULE,
@@ -1407,6 +1459,7 @@ static struct fb_ops savagefb_ops = {
	.fb_set_par     = savagefb_set_par,
	.fb_setcolreg   = savagefb_setcolreg,
	.fb_pan_display = savagefb_pan_display,
+	.fb_blank       = savagefb_blank,
#if defined(CONFIG_FB_SAVAGE_ACCEL)
	.fb_fillrect    = savagefb_fillrect,
	.fb_copyarea    = savagefb_copyarea,
@@ -1583,8 +1636,7 @@ static int __devinit savage_init_hw (str
	static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
	static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
	static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
-
-	int videoRam, videoRambytes;
+	int videoRam, videoRambytes, dvi;

	DBG("savage_init_hw");
@@ -1705,6 +1757,30 @@ static int __devinit savage_init_hw (str
	printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
		par->MCLK);

+	/* check for DVI/flat panel */
+	dvi = 0;
+
+	if (par->chip == S3_SAVAGE4) {
+		unsigned char sr30 = 0x00;
+
+		vga_out8(0x3c4, 0x30);
+		/* clear bit 1 */
+		vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02);
+		sr30 = vga_in8(0x3c5);
+		if (sr30 & 0x02 /*0x04 */) {
+			dvi = 1;
+			printk("savagefb: Digital Flat Panel Detected\n");
+		}
+	}
+
+	if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+	    (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly))
+		par->display_type = DISP_LCD;
+	else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
+		par->display_type = DISP_DFP;
+	else
+		par->display_type = DISP_CRT;
+
	/* Check LCD panel parrmation */

	if (par->chip == S3_SAVAGE_MX) {
@@ -1759,7 +1835,8 @@ static int __devinit savage_init_hw (str
			par->SavagePanelWidth = panelX;
			par->SavagePanelHeight = panelY;

-		}
+		} else
+			par->display_type = DISP_CRT;
	}

	savage_get_default_par (par);
@@ -1845,15 +1922,15 @@ static int __devinit savage_init_fb_info
		snprintf (info->fix.id, 16, "ProSavageKM");
		break;
	case FB_ACCEL_S3TWISTER_P:
-		par->chip = S3_PROSAVAGE;
+		par->chip = S3_TWISTER;
		snprintf (info->fix.id, 16, "TwisterP");
		break;
	case FB_ACCEL_S3TWISTER_K:
-		par->chip = S3_PROSAVAGE;
+		par->chip = S3_TWISTER;
		snprintf (info->fix.id, 16, "TwisterK");
		break;
	case FB_ACCEL_PROSAVAGE_DDR:
-		par->chip = S3_PROSAVAGE;
+		par->chip = S3_PROSAVAGEDDR;
		snprintf (info->fix.id, 16, "ProSavageDDR");
		break;
	case FB_ACCEL_PROSAVAGE_DDRK:
@@ -1959,7 +2036,8 @@ static int __devinit savagefb_probe (str
	INIT_LIST_HEAD(&info->modelist);
#if defined(CONFIG_FB_SAVAGE_I2C)
	savagefb_create_i2c_busses(info);
-	savagefb_probe_i2c_connector(par, &par->edid);
+	savagefb_probe_i2c_connector(info, &par->edid);
+	kfree(par->edid);
	fb_edid_to_monspecs(par->edid, &info->monspecs);
	fb_videomode_to_modelist(info->monspecs.modedb,
				 info->monspecs.modedb_len,
@@ -2111,13 +2189,30 @@ static int savagefb_suspend (struct pci_
	DBG("savagefb_suspend");

+
+	par->pm_state = state.event;
+
+	/*
+	 * For PM_EVENT_FREEZE, do not power down so the console
+	 * can remain active.
+	 */
+	if (state.event == PM_EVENT_FREEZE) {
+		dev->dev.power.power_state = state;
+		return 0;
+	}
+
	acquire_console_sem();
-	fb_set_suspend(info, pci_choose_state(dev, state));
-	savage_disable_mmio(par);
-	release_console_sem();
+	fb_set_suspend(info, 1);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);

+	savagefb_blank(FB_BLANK_POWERDOWN, info);
+	savage_disable_mmio(par);
+	pci_save_state(dev);
	pci_disable_device(dev);
	pci_set_power_state(dev, pci_choose_state(dev, state));
+	release_console_sem();

	return 0;
}
@@ -2127,22 +2222,34 @@ static int savagefb_resume (struct pci_d
	struct fb_info *info =
		(struct fb_info *)pci_get_drvdata(dev);
	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int cur_state = par->pm_state;

	DBG("savage_resume");

-	pci_set_power_state(dev, 0);
-	pci_restore_state(dev);
-	if(pci_enable_device(dev))
-		DBG("err");
+	par->pm_state = PM_EVENT_ON;

-	SavagePrintRegs();
+	/*
+	 * The adapter was not powered down coming back from a
+	 * PM_EVENT_FREEZE.
+	 */
+	if (cur_state == PM_EVENT_FREEZE) {
+		pci_set_power_state(dev, PCI_D0);
+		return 0;
+	}

	acquire_console_sem();

+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+
+	if(pci_enable_device(dev))
+		DBG("err");
+
+	pci_set_master(dev);
	savage_enable_mmio(par);
	savage_init_hw(par);
	savagefb_set_par (info);
-
+	savagefb_blank(FB_BLANK_UNBLANK, info);
	fb_set_suspend (info, 0);
	release_console_sem();




-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help