Skip to contentSkip to conversation

Resurrect Intel740 driver: i740fb

PATCH Superseded Ondrej Zary 2 participants 2 messages Dec 7, 2011 – Dec 17, 2011 Framebuffer layer

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 Resurrect Intel740 driver: i740fb

This is a resurrection of an old (like 2.4.19) out-of-tree driver for Intel740 graphics cards and modify it for recent kernels. The old driver is located at: http://sourceforge.net/projects/i740fbdev/files/

This is a new driver based on skeletonfb, using most of the low level HW code from the old driver. The DDC code is completely new.

The driver was tested on two 8MB cards: Protac AG240D and Diamond Stealth II G460.

---
Changes in v4:
- shortened many lines to fit 80-char limit
- removed useless inb_p and outb_p functions
- converted DDC (and some other) code to i740outreg_mask
- removed useless wm initialization in i740_calc_fifo()
- ALIGN macro is used instead of manual alignment
- removed inactive code
- simplified i740_setcolreg()
- info->var used for panning
- fixed out-of-video-memory checking

drivers/video/Kconfig +11 -0
@@ -1114,6 +1114,17 @@ config FB_RIVA_BACKLIGHT
 	help
 	  Say Y here if you want to control the backlight of your display.
 
+config FB_I740
+	tristate "Intel740 support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && FB && PCI
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select VGASTATE
+	help
+	  This driver supports graphics cards based on Intel740 chip.
+
 config FB_I810
 	tristate "Intel 810/815 support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
drivers/video/Makefile +1 -0
@@ -36,6 +36,7 @@ obj-$(CONFIG_FB_CYBER2000)        += cyb
 obj-$(CONFIG_FB_PM2)              += pm2fb.o
 obj-$(CONFIG_FB_PM3)		  += pm3fb.o
 
+obj-$(CONFIG_FB_I740)		  += i740fb.o
 obj-$(CONFIG_FB_MATROX)		  += matrox/
 obj-$(CONFIG_FB_RIVA)		  += riva/
 obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
drivers/video/i740fb.c new file +1277 -0

1,277 lines not on this page · raw message

drivers/video/i740_reg.h new file +309 -0

309 lines not on this page · raw message

Signature · 1 line
Ondrej Zary
#1 lore raw
Quoted 11 lines · On Thu, 8 Dec 2011 00:24:18 +0100 Ondrej Zary <[email protected]>…

This is a resurrection of an old (like 2.4.19) out-of-tree driver for Intel740 graphics cards and modify it for recent kernels. The old driver is located at: http://sourceforge.net/projects/i740fbdev/files/

This is a new driver based on skeletonfb, using most of the low level HW code from the old driver. The DDC code is completely new.

The driver was tested on two 8MB cards: Protac AG240D and Diamond Stealth II G460.

The original driver appears to have been written by Andrey Ulanov. It would be nice to mention that in the changelog and it is desirable that you seek his Signed-off-by:, please.

Quoted 10 lines

Changes in v4:
- shortened many lines to fit 80-char limit
- removed useless inb_p and outb_p functions
- converted DDC (and some other) code to i740outreg_mask
- removed useless wm initialization in i740_calc_fifo()
- ALIGN macro is used instead of manual alignment
- removed inactive code
- simplified i740_setcolreg()
- info->var used for panning
- fixed out-of-video-memory checking

It still generates a large number of checkpatch errors. If you've reviewed those and made the decision to ignore them then OK(ish). Otherwise, please check.

Quoted 6 lines

...

drivers/video/i740fb.c new file +3 -0
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>

drivers/video/i740fb.c line 26

Quoted 10 lines
drivers/video/i740fb.c new file +10 -0
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>

Should there have been a dependency on i2c in the Kconfig entry? If not, has the driver been tested with is2 disabled?

drivers/video/i740fb.c line 306

Quoted 12 lines
drivers/video/i740fb.c new file +9 -0
+#include <linux/console.h>
+#include <video/vga.h>
+
 
...
 
+#define I740_RFREQ (1e6)
+#define TARGET_MAX_N 30
+
+#define I740_FFIX		8
+#define I740_REF_FREQ		(u32) (66.66666666667 * (1 << I740_FFIX) + 0.5)
+#define I740_MAX_VCO_FREQ	(u32)(450.00000000000 * (1 << I740_FFIX) + 0.5)

There should be no floating point in the kernel, normally. Given the casts, these will obviously not get any further than the compiler. But if these could be redone to avoid the float, that would be nice.

Quoted 1 line

+#define I740_CALC_VCLKfix(m, n, p, d) ((((((m) * I740_REF_FREQ * (4 << ((d) << 1)))) / (n)) + ((1 << (p)) / 2)) / (1 << (p)))

This macro should be dragged out and shot. And it will cause bugs if invoked using an expression with side-effects. There's no need to do this to ourselves - please turn it into a nice, lower-case-named C function with proper identifiers, code comments, etc.

drivers/video/i740fb.c line 322

Quoted 13 lines
drivers/video/i740fb.c new file +13 -0
+static void i740_calc_vclk(u32 freq_hz, struct i740fb_par *par)
+{
+	u32 freq = freq_hz / (u32)(1e6 / I740_RFREQ);
+	const u32 err_max > +		freq / (u32)(I740_RFREQ / 0.005 / (1 << I740_FFIX) + 0.5);
+	const u32 err_target > +		freq / (u32)(I740_RFREQ / 0.001 / (1 << I740_FFIX) + 0.5);
+	u32 err_best = (u32)(512.0 * (1 << I740_FFIX));
+	u32 f_err, f_vco;
+	int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
+	int m, n, i;
+
+	/* find log2(MAX_VCO_FREQ/f_target) */
+	for (i = 0; i < 16; i++)
+		if ((I740_MAX_VCO_FREQ) / (1 << i) < freq / (u32)(I740_RFREQ / (1 << I740_FFIX)))

Use the existing ilog2()?

Quoted 70 lines
drivers/video/i740fb.c new file +67 -0
+			break;
+	i--;
+	p_best = i;
+
+	d_best = 0;
+	f_vco = (freq * (1 << p_best)) / (u32)(I740_RFREQ / (1 << I740_FFIX));
+	freq = freq / (u32)(I740_RFREQ / (1 << I740_FFIX));
+
+	n = 2;
+	do {
+		n++;
+		m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
+
+		if (m < 3)
+			m = 3;
+
+		{
+			u32 f_out = I740_CALC_VCLKfix(m, n, p_best, d_best);
+
+			f_err = (freq - f_out);
+
+			if (abs(f_err) < err_max) {
+				m_best = m;
+				n_best = n;
+				err_best = f_err;
+			}
+		}
+	} while ((abs(f_err) >= err_target) &&
+		 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
+
+	if (abs(f_err) < err_target) {
+		m_best = m;
+		n_best = n;
+	}
+
+	par->video_clk2_m = (m_best-2) & 0xFF;
+	par->video_clk2_n = (n_best-2) & 0xFF;
+	par->video_clk2_mn_msbs = ((((n_best-2) >> 4) & VCO_N_MSBS)
+				 | (((m_best-2) >> 8) & VCO_M_MSBS));
+	par->video_clk2_div_sel > +		((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
+}
+
 
...
 
+#ifndef MODULE
+static int  __init i740fb_setup(char *options)
+{
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+		if (!*opt)
+			continue;
+#ifdef CONFIG_MTRR
+		else if (!strncmp(opt, "mtrr:", 5))
+			mtrr = simple_strtoul(opt + 5, NULL, 0);
+#endif
+		else
+			mode_option = opt;
+	}
+
+	return 0;
+}
+#endif
+
+int __init i740fb_init(void)
+{

drivers/video/i740fb.c line 511

Quoted 10 lines
drivers/video/i740fb.c new file +10 -0
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("i740fb", &option))
+		return -ENODEV;
+	i740fb_setup(option);
+#endif
+
+	return pci_register_driver(&i740fb_driver);
+}

hm, the "ifdef MODULE" stuff looks old-fashioned, but quite a few fbdev drivers appear to be doing it.

Quoted 3 lines

...

Should we also be adding a documentation file for thei driver? Tell people what the various module options do?