* fb_setcolreg(), CNVT_TOHW() and chan_to_field()
From: Rabin Vincent @ 2011-10-25 7:46 UTC (permalink / raw)
To: linux-fbdev
I'm trying to figure out the best way to implement fb_setcolreg() for
FB_VISUAL_TRUECOLOR.
14 or so drivers copy/paste the CNVT_TOHW from skeletonfb.c:
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
...
red = CNVT_TOHW(red, info->var.red.length);
Another 18 or so drivers copy/paste a chan_to_field() function which has
a straightforward shift:
static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
{
chan &= 0xffff;
chan >>= 16 - bf->length;
return chan << bf->offset;
}
...
val = chan_to_field(red, &info->var.red);
Both methods return similar values, except that with CNVT_TOHW() the
extreme values seem to have a smaller range than the other values, while
with the chan_to_field() shift all the values have an equal range.
What's the reason behind choosing one over the other? Could/should a
common function be provided for all the drivers to use?
^ permalink raw reply
* Re: fb_setcolreg(), CNVT_TOHW() and chan_to_field()
From: Geert Uytterhoeven @ 2011-10-25 11:15 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20111025073349.GB6027@debian>
On Tue, Oct 25, 2011 at 09:34, Rabin Vincent <rabin@rab.in> wrote:
> I'm trying to figure out the best way to implement fb_setcolreg() for
> FB_VISUAL_TRUECOLOR.
FB_VISUAL_TRUECOLOR implies the colormap is read-only.
Perhaps you meant FB_VISUAL_DIRECTCOLOR?
> 14 or so drivers copy/paste the CNVT_TOHW from skeletonfb.c:
>
> #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
> ...
> red = CNVT_TOHW(red, info->var.red.length);
>
> Another 18 or so drivers copy/paste a chan_to_field() function which has
> a straightforward shift:
>
> static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
> {
> chan &= 0xffff;
> chan >>= 16 - bf->length;
> return chan << bf->offset;
> }
> ...
> val = chan_to_field(red, &info->var.red);
>
> Both methods return similar values, except that with CNVT_TOHW() the
> extreme values seem to have a smaller range than the other values, while
> with the chan_to_field() shift all the values have an equal range.
>
> What's the reason behind choosing one over the other? Could/should a
> common function be provided for all the drivers to use?
The idea is to use the full dynamic range of the 16-bit values. I.e. 'all ones'
in the hardware-specific value should map to 'all ones' in the 16-bit expanded
value. So the macros are preferred.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: fb_setcolreg(), CNVT_TOHW() and chan_to_field()
From: Rabin Vincent @ 2011-10-25 15:25 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20111025073349.GB6027@debian>
On Tue, Oct 25, 2011 at 01:15:41PM +0200, Geert Uytterhoeven wrote:
> On Tue, Oct 25, 2011 at 09:34, Rabin Vincent <rabin@rab.in> wrote:
> > I'm trying to figure out the best way to implement fb_setcolreg() for
> > FB_VISUAL_TRUECOLOR.
>
> FB_VISUAL_TRUECOLOR implies the colormap is read-only.
> Perhaps you meant FB_VISUAL_DIRECTCOLOR?
I was referring to the pseudo palette usage for FB_VISUAL_TRUECOLOR, which is
where most of the drivers use chan_to_field(), for example in s3c2410fb.c:
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
/* true-colour, use pseudo-palette */
if (regno < 16) {
u32 *pal = info->pseudo_palette;
val = chan_to_field(red, &info->var.red);
>
> > 14 or so drivers copy/paste the CNVT_TOHW from skeletonfb.c:
> >
> > #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
> > ...
> > red = CNVT_TOHW(red, info->var.red.length);
> >
> > Another 18 or so drivers copy/paste a chan_to_field() function which has
> > a straightforward shift:
> >
> > static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
> > {
> > chan &= 0xffff;
> > chan >>= 16 - bf->length;
> > return chan << bf->offset;
> > }
> > ...
> > val = chan_to_field(red, &info->var.red);
> >
> > Both methods return similar values, except that with CNVT_TOHW() the
> > extreme values seem to have a smaller range than the other values, while
> > with the chan_to_field() shift all the values have an equal range.
> >
> > What's the reason behind choosing one over the other? Could/should a
> > common function be provided for all the drivers to use?
>
> The idea is to use the full dynamic range of the 16-bit values. I.e. 'all ones'
> in the hardware-specific value should map to 'all ones' in the 16-bit expanded
> value. So the macros are preferred.
I'm not sure I follow. In the pseudo palette, where the bf->length is less
than 16, both CNVT_TOHW() and the plain shift return the same values for the
all-ones case.
^ permalink raw reply
* [PATCH] fbtest: fix test011 with xpanstep or ypanstep greater than 1
From: Ondrej Zary @ 2011-10-27 20:31 UTC (permalink / raw)
To: linux-fbdev
Hello,
this patch fixes test011 in fbtest if framebuffer driver requires xpanstep or
ypanstep to be greater than 1. Without this, test011 fails on savagefb:
ioctl FBIOPAN_DISPLAY: Invalid argument
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
--- fbtest-orig/tests/test011.c 2011-10-27 22:20:47.000000000 +0200
+++ fbtest/tests/test011.c 2011-10-27 22:22:16.000000000 +0200
@@ -93,16 +93,25 @@ static int linegen_next(struct linegen *
return 1;
}
-static void move(u32 cx, u32 cy, u32 x1, u32 y1, u32 x2, u32 y2)
+static void move(u32 cx, u32 cy, u32 x1, u32 y1, u32 x2, u32 y2, u32 xpanstep, u32 ypanstep)
{
struct linegen gen;
u32 x, y;
static int cnt = 0;
+ if (xpanstep = 0)
+ xpanstep = 1;
+ if (ypanstep = 0)
+ ypanstep = 1;
+ x1 /= xpanstep;
+ x2 /= xpanstep;
+ y1 /= ypanstep;
+ y2 /= ypanstep;
+
linegen_init(&gen, x1, y1, x2, y2);
while (linegen_next(&gen, &x, &y)) {
fill_circle(cx+x, cy+y, 2, cnt & 4 ? black_pixel : white_pixel);
- fb_pan(x, y);
+ fb_pan(x * xpanstep, y * ypanstep);
wait_ms(SLEEP_MS);
cnt++;
}
@@ -137,29 +146,29 @@ static enum test_res test011_func(void)
dy = fb_fix.ypanstep ? fb_var.yres_virtual-fb_var.yres : 0;
/* move right */
- move(cx, cy, 0, 0, dx, 0);
+ move(cx, cy, 0, 0, dx, 0, fb_fix.xpanstep, fb_fix.ypanstep);
/* move down */
- move(cx, cy, dx, 0, dx, dy);
+ move(cx, cy, dx, 0, dx, dy, fb_fix.xpanstep, fb_fix.ypanstep);
/* move left */
- move(cx, cy, dx, dy, 0, dy);
+ move(cx, cy, dx, dy, 0, dy, fb_fix.xpanstep, fb_fix.ypanstep);
if (dx >= 2 && dy >= 2) {
/* move up and right */
- move(cx, cy, 0, dy, dx/2, 0);
+ move(cx, cy, 0, dy, dx/2, 0, fb_fix.xpanstep, fb_fix.ypanstep);
/* move right and down */
- move(cx, cy, dx/2, 0, dx, dy/2);
+ move(cx, cy, dx/2, 0, dx, dy/2, fb_fix.xpanstep, fb_fix.ypanstep);
/* move left and down */
- move(cx, cy, dx, dy/2, dx/2, dy);
+ move(cx, cy, dx, dy/2, dx/2, dy, fb_fix.xpanstep, fb_fix.ypanstep);
/* move up and left */
- move(cx, cy, dx/2, dy, 0, 0);
+ move(cx, cy, dx/2, dy, 0, 0, fb_fix.xpanstep, fb_fix.ypanstep);
} else {
/* move up */
- move(cx, cy, 0, dy, 0, 0);
+ move(cx, cy, 0, dy, 0, 0, fb_fix.xpanstep, fb_fix.ypanstep);
}
wait_for_key(10);
--
Ondrej Zary
^ permalink raw reply
* Hello
From: lisa hedstrand @ 2011-10-28 11:36 UTC (permalink / raw)
To: linux-fbdev
My name is Miss Lisa Please accept my apology if my mode of contacting you will in any way offend you. I am compelled to contact you via this medium because i needed a friend from that part of the world. We will get to know each other in details if my proposition accepted. l am a student in UK but originally from USA.
^ permalink raw reply
* [PATCH v3] Resurrect Intel740 driver: i740fb
From: Ondrej Zary @ 2011-10-28 18:43 UTC (permalink / raw)
To: linux-fbdev
Cc: Florian Tobias Schandinat, Paul Mundt, Kernel development list
Hello,
this is an v3 attempt to resurrect 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/
It was easier to create 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 v3:
- added suspend/resume support
- fixed x panning
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
--- linux-2.6.39-rc2-orig/drivers/video/Kconfig 2011-04-06 03:30:43.000000000 +0200
+++ linux-2.6.39-rc2/drivers/video/Kconfig 2011-10-24 23:29:42.000000000 +0200
@@ -1117,6 +1117,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
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740fb.c 2011-10-28 20:03:34.000000000 +0200
@@ -0,0 +1,1286 @@
+/*
+ * i740fb - framebuffer driver for Intel740
+ * Copyright (c) 2011 Ondrej Zary
+ *
+ * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru> which was partially based on:
+ * VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * i740fb by Patrick LERDA, v0.9
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#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>
+#include <linux/console.h>
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "i740_reg.h"
+
+static char *mode_option __devinitdata;
+
+#ifdef CONFIG_MTRR
+static int mtrr __devinitdata = 1;
+#endif
+
+struct i740fb_par {
+ unsigned char __iomem *regs;
+ bool has_sgram;
+#ifdef CONFIG_MTRR
+ int mtrr_reg;
+#endif
+ bool ddc_registered;
+ struct i2c_adapter ddc_adapter;
+ struct i2c_algo_bit_data ddc_algo;
+ u32 pseudo_palette[16];
+ struct mutex open_lock;
+ unsigned int ref_count;
+
+ u8 crtc[VGA_CRT_C];
+ u8 atc[VGA_ATT_C];
+ u8 gdc[VGA_GFX_C];
+ u8 seq[VGA_SEQ_C];
+ u8 misc;
+ u8 vss;
+
+ /* i740 specific registers */
+ u8 display_cntl;
+ u8 pixelpipe_cfg0;
+ u8 pixelpipe_cfg1;
+ u8 pixelpipe_cfg2;
+ u8 video_clk2_m;
+ u8 video_clk2_n;
+ u8 video_clk2_mn_msbs;
+ u8 video_clk2_div_sel;
+ u8 pll_cntl;
+ u8 address_mapping;
+ u8 io_cntl;
+ u8 bitblt_cntl;
+ u8 ext_vert_total;
+ u8 ext_vert_disp_end;
+ u8 ext_vert_sync_start;
+ u8 ext_vert_blank_start;
+ u8 ext_horiz_total;
+ u8 ext_horiz_blank;
+ u8 ext_offset;
+ u8 interlace_cntl;
+ u32 lmi_fifo_watermark;
+ u8 ext_start_addr;
+ u8 ext_start_addr_hi;
+};
+
+#define DACSPEED8 203
+#define DACSPEED16 163
+#define DACSPEED24_SG 136
+#define DACSPEED24_SD 128
+#define DACSPEED32 86
+
+static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
+ .id = "i740fb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 8,
+ .ypanstep = 1,
+ .accel = FB_ACCEL_NONE,
+};
+
+static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb(struct i740fb_par *par, u16 port)
+{
+ return vga_mm_r(par->regs, port);
+}
+static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
+{
+ vga_mm_w_fast(par->regs, port, reg, val);
+}
+static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
+{
+ vga_mm_w(par->regs, port, reg);
+ return vga_mm_r(par->regs, port+1);
+}
+static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg, u8 val, u8 mask)
+{
+ vga_mm_w_fast(par->regs, port, reg, (val & mask) | (i740inreg(par, port, reg) & ~mask));
+}
+static inline void i740outb_p(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb_p(struct i740fb_par *par, unsigned short port)
+{
+ return vga_mm_r(par->regs, port);
+}
+
+#define REG_DDC_DRIVE 0x62
+#define REG_DDC_STATE 0x63
+#define DDC_SCL (1 << 3)
+#define DDC_SDA (1 << 2)
+
+static void i740fb_ddc_setscl(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SCL);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SCL;
+ else
+ reg &= ~DDC_SCL;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static void i740fb_ddc_setsda(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SDA);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SDA;
+ else
+ reg &= ~DDC_SDA;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static int i740fb_ddc_getscl(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SCL);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
+}
+
+static int i740fb_ddc_getsda(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SDA);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
+}
+
+static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ strlcpy(par->ddc_adapter.name, info->fix.id,
+ sizeof(par->ddc_adapter.name));
+ par->ddc_adapter.owner = THIS_MODULE;
+ par->ddc_adapter.class = I2C_CLASS_DDC;
+ par->ddc_adapter.algo_data = &par->ddc_algo;
+ par->ddc_adapter.dev.parent = info->device;
+ par->ddc_algo.setsda = i740fb_ddc_setsda;
+ par->ddc_algo.setscl = i740fb_ddc_setscl;
+ par->ddc_algo.getsda = i740fb_ddc_getsda;
+ par->ddc_algo.getscl = i740fb_ddc_getscl;
+ par->ddc_algo.udelay = 10;
+ par->ddc_algo.timeout = 20;
+ par->ddc_algo.data = par;
+
+ i2c_set_adapdata(&par->ddc_adapter, par);
+
+ return i2c_bit_add_bus(&par->ddc_adapter);
+}
+
+static int i740fb_open(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ par->ref_count++;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static int i740fb_release(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ return -EINVAL;
+ }
+
+ par->ref_count--;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
+{
+ /*
+ * Would like to calculate these values automatically, but a generic
+ * algorithm does not seem possible. Note: These FIFO water mark
+ * values were tested on several cards and seem to eliminate the
+ * all of the snow and vertical banding, but fine adjustments will
+ * probably be required for other cards.
+ */
+
+ u32 wm = 0x18120000;
+
+ switch (bpp) {
+ case 8:
+ if (freq > 200) wm = 0x18120000;
+ else if (freq > 175) wm = 0x16110000;
+ else if (freq > 135) wm = 0x120E0000;
+ else wm = 0x100D0000;
+ break;
+ case 15:
+ case 16:
+ if (par->has_sgram) {
+ if (freq > 140) wm = 0x2C1D0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24160000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ } else {
+ if (freq > 160) wm = 0x28200000;
+ else if (freq > 140) wm = 0x2A1E0000;
+ else if (freq > 130) wm = 0x2B1A0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24180000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ }
+ break;
+ case 24:
+ if (par->has_sgram) {
+ if (freq > 130) wm = 0x31200000;
+ else if (freq > 120) wm = 0x2E200000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ } else {
+ if (freq > 120) wm = 0x311F0000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ }
+ break;
+ case 32:
+ if (par->has_sgram) {
+ if (freq > 80) wm = 0x2A200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ } else {
+ if (freq > 80) wm = 0x29200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ }
+ break;
+ }
+
+ return wm;
+}
+
+/* clock calculation from i740fb by Patrick LERDA */
+
+#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)
+
+#define I740_CALC_VCLKfix(m, n, p, d) ((((((m) * I740_REF_FREQ * (4 << ((d) << 1)))) / (n)) + ((1 << (p)) / 2)) / (1 << (p)))
+
+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)))
+ 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);
+}
+
+static int i740fb_decode_var(const struct fb_var_screeninfo *var, struct i740fb_par *par, struct fb_info *info)
+{
+ /*
+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
+ * if it's too big, return -EINVAL.
+ */
+
+ u32 xres, right, hslen, left, xtotal;
+ u32 yres, lower, vslen, upper, ytotal;
+ u32 vxres, xoffset, vyres, yoffset;
+ u32 bpp, base, dacspeed24;
+ u8 r7;
+ int i;
+
+ dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
+ var->xres, var->yres, var->xres_virtual, var->xres_virtual);
+ dev_dbg(info->device, " xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
+ var->xoffset, var->yoffset, var->bits_per_pixel, var->grayscale);
+ dev_dbg(info->device, " activate: %i, nonstd: %i, vmode: %i\n",
+ var->activate, var->nonstd, var->vmode);
+ dev_dbg(info->device, " pixclock: %i, hsynclen:%i, vsynclen:%i\n",
+ var->pixclock, var->hsync_len, var->vsync_len);
+ dev_dbg(info->device, " left: %i, right: %i, up:%i, lower:%i\n",
+ var->left_margin, var->right_margin, var->upper_margin, var->lower_margin);
+
+
+ bpp = var->bits_per_pixel;
+ switch (bpp) {
+ case 1 ... 8:
+ bpp = 8;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED8) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n", 1000000 / var->pixclock, DACSPEED8);
+ return -EINVAL;
+ }
+ break;
+ case 9 ... 15:
+ bpp = 15;
+ case 16:
+ if ((((u32)1e6) / var->pixclock) > DACSPEED16) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n", 1000000 / var->pixclock, DACSPEED16);
+ return -EINVAL;
+ }
+ break;
+ case 17 ... 24:
+ bpp = 24;
+ dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
+ if ((((u32)1e6) / var->pixclock) > dacspeed24) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n", 1000000 / var->pixclock, dacspeed24);
+ return -EINVAL;
+ }
+ break;
+ case 25 ... 32:
+ bpp = 32;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED32) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n", 1000000 / var->pixclock, DACSPEED32);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ xres = (var->xres + 7) & ~7;
+ vxres = (var->xres_virtual + 0xF) & ~0xF;
+ if (vxres < xres)
+ vxres = xres;
+
+ xoffset = (var->xoffset + 7) & ~7;
+ xoffset = var->xoffset;
+ if (xres + xoffset > vxres)
+ xoffset = vxres - xres;
+
+ left = (var->left_margin + 7) & ~7;
+ right = (var->right_margin + 7) & ~7;
+ hslen = (var->hsync_len + 7) & ~7;
+
+ yres = var->yres;
+ vyres = var->yres_virtual;
+ if (yres > vyres)
+ vyres = yres;
+
+ yoffset = var->yoffset;
+ if (yres + yoffset > vyres)
+ yoffset = vyres - yres;
+
+ lower = var->lower_margin;
+ vslen = var->vsync_len;
+ upper = var->upper_margin;
+
+ if (vxres * vyres * ((bpp + 1) / 8) > info->screen_size || vyres = yres) {
+ vyres = info->screen_size / vxres / ((bpp + 1) / 8);
+ if (vyres < yres)
+ return -ENOMEM;
+ }
+
+ if (yoffset + yres > vyres)
+ yoffset = vyres - yres;
+
+ xtotal = xres + right + hslen + left;
+ ytotal = yres + lower + vslen + upper;
+
+ par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
+ par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
+ par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
+ par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
+ par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
+ | ((((xres + right + hslen) >> 3) & 0x20) << 2);
+ par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F) | 0x80;
+
+ par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
+
+ r7 = 0x10; /* disable linecompare */
+ if (ytotal & 0x100)
+ r7 |= 0x01;
+ if (ytotal & 0x200)
+ r7 |= 0x20;
+
+ par->crtc[VGA_CRTC_PRESET_ROW] = 0;
+ par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
+ if (var->vmode & FB_VMODE_DOUBLE)
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
+ par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
+ par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
+ if ((yres-1) & 0x100)
+ r7 |= 0x02;
+ if ((yres-1) & 0x200)
+ r7 |= 0x40;
+
+ par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
+ par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
+ if ((yres + lower - 1) & 0x100)
+ r7 |= 0x0C;
+ if ((yres + lower - 1) & 0x200) {
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
+ r7 |= 0x80;
+ }
+
+ par->crtc[VGA_CRTC_V_SYNC_END] = ((yres + lower - 1 + vslen) & 0x0F) & ~0x10; /* disabled IRQ */
+ par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF; /* 0x7F for original VGA, but some SVGA chips requires all 8 bits to set */
+
+ par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
+ par->crtc[VGA_CRTC_MODE] = 0xC3 ;
+ par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
+ par->crtc[VGA_CRTC_OVERFLOW] = r7;
+
+ par->vss = 0x00; /* 3DA */
+
+ for (i = 0x00; i < 0x10; i++)
+ par->atc[i] = i;
+ par->atc[VGA_ATC_MODE] = 0x81;
+ par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
+ par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
+ /*par->atc[VGA_ATC_PEL] = xoffset & 7;*/
+ par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
+
+ par->misc = 0xC3;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ par->misc &= ~0x40;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ par->misc &= ~0x80;
+
+ par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
+ par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
+ par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+ par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
+
+ par->gdc[VGA_GFX_SR_VALUE] = 0x00;
+ par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
+ par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
+ par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
+ par->gdc[VGA_GFX_PLANE_READ] = 0;
+ par->gdc[VGA_GFX_MODE] = 0x02;
+ par->gdc[VGA_GFX_MISC] = 0x05;
+ par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
+ par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
+
+ base = (yoffset * vxres + (xoffset & ~7)) >> 2;
+ switch (bpp) {
+ case 8:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
+ par->ext_offset = vxres >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
+ par->bitblt_cntl = COLEXP_8BPP;
+ break;
+ case 15: /* 0rrrrrgg gggbbbbb */
+ case 16: /* rrrrrggg gggbbbbb */
+ par->pixelpipe_cfg1 = (var->green.length = 6) ? DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
+ par->ext_offset = vxres >> 10;
+ par->bitblt_cntl = COLEXP_16BPP;
+ base *= 2;
+ break;
+ case 24:
+ par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
+ par->ext_offset = (vxres * 3) >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
+ par->bitblt_cntl = COLEXP_24BPP;
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
+ par->ext_offset = vxres >> 9;
+ par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
+ par->bitblt_cntl = COLEXP_RESERVED; /* Not implemented on i740 */
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+
+ par->pixelpipe_cfg0 = DAC_8_BIT;
+
+ par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
+ par->io_cntl = EXTENDED_CRTC_CNTL;
+ par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
+ par->display_cntl = HIRES_MODE;
+
+ /* Set the MCLK freq */
+ par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
+
+ /* Calculate the extended CRTC regs */
+ par->ext_vert_total = (ytotal - 2) >> 8;
+ par->ext_vert_disp_end = (yres - 1) >> 8;
+ par->ext_vert_sync_start = (yres + lower) >> 8;
+ par->ext_vert_blank_start = (yres + lower) >> 8;
+ par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
+ par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
+
+ par->interlace_cntl = INTERLACE_DISABLE;
+
+ /* Set the overscan color to 0. (NOTE: This only affects >8bpp mode.) */
+ par->atc[VGA_ATC_OVERSCAN] = 0;
+
+ /* Calculate VCLK that most closely matches the requested dot clock */
+ i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ par->misc |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ par->lmi_fifo_watermark = i740_calc_fifo(par, ((int)1e6) / var->pixclock, bpp);
+
+ /*if (!fbmon_valid_timings(var->pixclock, ytotal, xtotal, info))
+ return -EINVAL;*/
+
+ return 0;
+}
+
+static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 16:
+ switch (var->green.length) {
+ default:
+ case 5:
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 5;
+ break;
+ case 6:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->green.length = 6;
+ var->red.length = var->blue.length = 5;
+ break;
+ }
+ break;
+ case 24:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 32:
+ var->transp.offset = 24;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->transp.length = var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ if (info->monspecs.hfmax && info->monspecs.vfmax &&
+ info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void vga_protect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) | 0x20); /* disable the display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x00); /* enable pallete access */
+}
+
+static void vga_unprotect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) & 0xDF); /* reenable display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x20); /* disable pallete access */
+}
+
+static int i740fb_set_par(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 itemp;
+ int i;
+
+ i = i740fb_decode_var(&info->var, par, info);
+ if (i)
+ return i;
+
+ memset(info->screen_base, 0, info->screen_size);
+
+ vga_protect(par);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
+
+ mdelay(1);
+
+ i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
+ i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
+ i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
+ i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
+
+ i740inb(par, 0x3DA);
+ i740outb(par, 0x3C0, 0x00);
+
+ /* update misc output register */
+ i740outb(par, VGA_MIS_W, par->misc | 0x01);
+
+ /* synchronous reset on */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
+ /* write sequencer registers */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
+ for (i = 2; i < VGA_SEQ_C; i++)
+ i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
+
+ /* synchronous reset off */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
+
+ /* deprotect CRT registers 0-7 */
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
+
+ /* write CRT registers */
+ for (i = 0; i < VGA_CRT_C; i++)
+ i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
+
+ /* write graphics controller registers */
+ for (i = 0; i < VGA_GFX_C; i++)
+ i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
+
+ /* write attribute controller registers */
+ for (i = 0; i < VGA_ATT_C; i++) {
+ i740inb_p(par, VGA_IS1_RC); /* reset flip-flop */
+ i740outb_p(par, VGA_ATT_IW, i);
+ i740outb_p(par, VGA_ATT_IW, par->atc[i]);
+ }
+
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE]);
+
+ i740inb(par, VGA_IS1_RC);
+ i740outb(par, VGA_ATT_IW, 0x20);
+
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START, par->ext_vert_sync_start);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START, par->ext_vert_blank_start);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
+ i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
+
+ i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL, par->interlace_cntl, INTERLACE_ENABLE);
+ i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
+ i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
+ i740outreg_mask(par, XRX, DISPLAY_CNTL, par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
+
+ i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1, par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
+
+ itemp = readl(par->regs + FWATER_BLC);
+ itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
+ itemp |= par->lmi_fifo_watermark;
+ writel(itemp, par->regs + FWATER_BLC);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
+
+ i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
+ i740outreg_mask(par, XRX, IO_CTNL, par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+
+ if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
+ i740outb(par, VGA_PEL_MSK, 0xFF);
+ i740outb(par, VGA_PEL_IW, 0x00);
+ for (i = 0; i < 256; i++) {
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ }
+ }
+
+ /* Wait for screen to stabilize. */
+ mdelay(50);
+ vga_unprotect(par);
+
+ info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
+ if (info->var.bits_per_pixel = 8)
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+ return 0;
+}
+
+static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n", regno, red, green, blue, transp, info->var.bits_per_pixel);
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ if (regno >= 256)
+ return 1;
+ i740outb(info->par, VGA_PEL_IW, regno);
+ i740outb(info->par, VGA_PEL_D, red >> 8);
+ i740outb(info->par, VGA_PEL_D, green >> 8);
+ i740outb(info->par, VGA_PEL_D, blue >> 8);
+ break;
+ case 15:
+ case 16:
+ if (regno >= 16)
+ return 0;
+ if (info->var.green.length = 5)
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+ else if (info->var.green.length = 6)
+ ((u32 *)info->pseudo_palette)[regno] = (red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+ else
+ return -EINVAL;
+ break;
+ case 24:
+ case 32:
+ if (regno >= 16)
+ return 0;
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int i740fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 base = (var->yoffset * var->xres_virtual + (var->xoffset & ~7)) >> 2;
+
+ dev_dbg(info->device, "pan_display: xoffset: %i, yoffset: %i base: %i\n", var->xoffset, var->yoffset, base);
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ break;
+ case 15:
+ case 16:
+ base *= 2;
+ break;
+ case 24:
+ /*
+ * The last bit does not seem to have any effect on the start
+ * address register in 24bpp mode, so...
+ */
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ /*par->atc[VGA_ATC_PEL] = var->xoffset & 7;*/
+
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO, base & 0x000000FF);
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI, (base & 0x0000FF00) >> 8);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, (base & 0x3FC00000) >> 22);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
+ /*i740outreg(par, VGA_ATT_W, VGA_ATC_PEL, var->xoffset & 7);*/
+
+ return 0;
+}
+
+static int i740fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ unsigned char SEQ01;
+ int DPMSSyncSelect;
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+ break;
+ case FB_BLANK_POWERDOWN:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Turn the screen on/off */
+ i740outb(par, SRX, 0x01);
+ SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
+ i740outb(par, SRX, 0x01);
+ i740outb(par, SRX + 1, SEQ01);
+
+ /* Set the DPMS mode */
+ i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
+
+ /* Let fbcon do a soft blank for us */
+ return (blank_mode = FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops i740fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = i740fb_open,
+ .fb_release = i740fb_release,
+ .fb_check_var = i740fb_check_var,
+ .fb_set_par = i740fb_set_par,
+ .fb_setcolreg = i740fb_setcolreg,
+ .fb_blank = i740fb_blank,
+ .fb_pan_display = i740fb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int __devinit i740fb_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ struct fb_info *info;
+ struct i740fb_par *par;
+ int ret;
+ bool found = false;
+ u8 *edid;
+
+ info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
+ if (!info) {
+ dev_err(&(dev->dev), "cannot allocate framebuffer\n");
+ return -ENOMEM;
+ }
+
+ par = info->par;
+ mutex_init(&par->open_lock);
+
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.bits_per_pixel = 8;
+ info->fbops = &i740fb_ops;
+ info->pseudo_palette = par->pseudo_palette;
+
+ ret = pci_enable_device(dev);
+ if (ret) {
+ dev_err(info->device, "cannot enable PCI device\n");
+ goto err_enable_device;
+ }
+
+ ret = pci_request_regions(dev, info->fix.id);
+ if (ret) {
+ dev_err(info->device, "error requesting regions\n");
+ goto err_request_regions;
+ }
+
+ info->screen_base = pci_ioremap_bar(dev, 0);
+ if (!info->screen_base) {
+ dev_err(info->device, "error remapping base\n");
+ ret = -ENOMEM;
+ goto err_ioremap_1;
+ }
+
+ par->regs = pci_ioremap_bar(dev, 1);
+ if (!par->regs) {
+ dev_err(info->device, "error remapping MMIO\n");
+ ret = -ENOMEM;
+ goto err_ioremap_2;
+ }
+
+ /* detect memory size */
+ if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1) = DRAM_ROW_1_SDRAM)
+ i740outb(par, XRX, DRAM_ROW_BNDRY_1);
+ else
+ i740outb(par, XRX, DRAM_ROW_BNDRY_0);
+ info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
+ /* detect memory type */
+ par->has_sgram = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
+ par->has_sgram = !((par->has_sgram & DRAM_RAS_TIMING) ||
+ (par->has_sgram & DRAM_RAS_PRECHARGE));
+
+ printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
+ pci_name(dev), info->screen_size >> 10,
+ par->has_sgram ? "SGRAM" : "SDRAM");
+
+ info->fix = i740fb_fix;
+ info->fix.mmio_start = pci_resource_start(dev, 1);
+ info->fix.mmio_len = pci_resource_len(dev, 1);
+ info->fix.smem_start = pci_resource_start(dev, 0);
+ info->fix.smem_len = info->screen_size;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ if (i740fb_setup_ddc_bus(info) = 0) {
+ par->ddc_registered = true;
+ edid = fb_ddc_read(&par->ddc_adapter);
+ if (edid) {
+ fb_edid_to_monspecs(edid, &info->monspecs);
+ kfree(edid);
+ if (!info->monspecs.modedb)
+ dev_err(info->device, "error getting mode database\n");
+ else {
+ const struct fb_videomode *m;
+
+ fb_videomode_to_modelist(info->monspecs.modedb,
+ info->monspecs.modedb_len,
+ &info->modelist);
+ m = fb_find_best_display(&info->monspecs, &info->modelist);
+ if (m) {
+ fb_videomode_to_var(&info->var, m);
+ /* fill all other info->var's fields */
+ if (i740fb_check_var(&info->var, info) = 0)
+ found = true;
+ }
+ }
+ }
+ }
+
+ if (!mode_option && !found)
+ mode_option = "640x480-8@60";
+
+ if (mode_option) {
+ ret = fb_find_mode(&info->var, info, mode_option,
+ info->monspecs.modedb, info->monspecs.modedb_len,
+ NULL, info->var.bits_per_pixel);
+ if (!ret || ret = 4) {
+ dev_err(info->device, "mode %s not found\n", mode_option);
+ ret = -EINVAL;
+ }
+ }
+
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+
+ /* maximize virtual vertical size for fast scrolling */
+ info->var.yres_virtual = info->fix.smem_len * 8 /
+ (info->var.bits_per_pixel * info->var.xres_virtual);
+
+ if (ret = -EINVAL)
+ goto err_find_mode;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ dev_err(info->device, "cannot allocate colormap\n");
+ goto err_alloc_cmap;
+ }
+
+ ret = register_framebuffer(info);
+ if (ret) {
+ dev_err(info->device, "error registering framebuffer\n");
+ goto err_reg_framebuffer;
+ }
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ pci_set_drvdata(dev, info);
+#ifdef CONFIG_MTRR
+ if (mtrr) {
+ par->mtrr_reg = -1;
+ par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+ }
+#endif
+ return 0;
+
+err_reg_framebuffer:
+ fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+err_ioremap_2:
+ pci_iounmap(dev, info->screen_base);
+err_ioremap_1:
+ pci_release_regions(dev);
+err_request_regions:
+/* pci_disable_device(dev); */
+err_enable_device:
+ framebuffer_release(info);
+ return ret;
+}
+
+static void __devexit i740fb_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+
+ if (info) {
+#ifdef CONFIG_MTRR
+ struct i740fb_par *par = info->par;
+
+ if (par->mtrr_reg >= 0) {
+ mtrr_del(par->mtrr_reg, 0, 0);
+ par->mtrr_reg = -1;
+ }
+#endif
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+ pci_iounmap(dev, info->screen_base);
+ pci_release_regions(dev);
+/* pci_disable_device(dev); */
+ pci_set_drvdata(dev, NULL);
+ framebuffer_release(info);
+ }
+}
+
+#ifdef CONFIG_PM
+static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ /* don't disable console during hibernation and wakeup from it */
+ if (state.event = PM_EVENT_FREEZE || state.event = PM_EVENT_PRETHAW)
+ return 0;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ /* do nothing if framebuffer is not active */
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+ }
+
+ fb_set_suspend(info, 1);
+
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+
+ return 0;
+}
+
+static int i740fb_resume(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ if (par->ref_count = 0)
+ goto fail;
+
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+ if (pci_enable_device(dev))
+ goto fail;
+
+ i740fb_set_par(info);
+ fb_set_suspend(info, 0);
+
+fail:
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+}
+#else
+#define i740fb_suspend NULL
+#define i740fb_resume NULL
+#endif /* CONFIG_PM */
+
+#define I740_ID_PCI 0x00d1
+#define I740_ID_AGP 0x7800
+
+static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, i740fb_id_table);
+
+static struct pci_driver i740fb_driver = {
+ .name = "i740fb",
+ .id_table = i740fb_id_table,
+ .probe = i740fb_probe,
+ .remove = __devexit_p(i740fb_remove),
+ .suspend = i740fb_suspend,
+ .resume = i740fb_resume,
+};
+
+#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)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("i740fb", &option))
+ return -ENODEV;
+ i740fb_setup(option);
+#endif
+
+ return pci_register_driver(&i740fb_driver);
+}
+
+static void __exit i740fb_exit(void)
+{
+ pci_unregister_driver(&i740fb_driver);
+}
+
+module_init(i740fb_init);
+module_exit(i740fb_exit);
+
+MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for Intel740");
+
+module_param(mode_option, charp, 0444);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740_reg.h 2011-08-14 23:47:48.000000000 +0200
@@ -0,0 +1,309 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ */
+
+/* I/O register offsets */
+#define SRX VGA_SEQ_I
+#define GRX VGA_GFX_I
+#define ARX VGA_ATT_IW
+#define XRX 0x3D6
+#define MRX 0x3D2
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6
+#define DACSTATE 0x3C7
+#define DACRX 0x3C7
+#define DACWX 0x3C8
+#define DACDATA 0x3C9
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C
+#define START_ADDR_LO 0x0D
+#define VERT_SYNC_END 0x11
+#define EXT_VERT_TOTAL 0x30
+#define EXT_VERT_DISPLAY 0x31
+#define EXT_VERT_SYNC_START 0x32
+#define EXT_VERT_BLANK_START 0x33
+#define EXT_HORIZ_TOTAL 0x35
+#define EXT_HORIZ_BLANK 0x39
+#define EXT_START_ADDR 0x40
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41
+#define EXT_START_ADDR_HI 0x42
+#define INTERLACE_CNTL 0x70
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register */
+#define MSR_R 0x3CC
+#define MSR_W 0x3C2
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0
+#define CGA_BASE 0x3D0
+
+/* System Configuration Extension Registers (XRX) */
+#define IO_CTNL 0x09
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+#define ADDRESS_MAPPING 0x0A
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+#define BITBLT_CNTL 0x20
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define CHIP_RESET 0x02
+#define BITBLT_STATUS 0x01
+
+#define DISPLAY_CNTL 0x40
+#define VGA_WRAP_MODE 0x02
+#define VGA_WRAP_AT_256KB 0x00
+#define VGA_NO_WRAP 0x02
+#define GUI_MODE 0x01
+#define STANDARD_VGA_MODE 0x00
+#define HIRES_MODE 0x01
+
+#define DRAM_ROW_TYPE 0x50
+#define DRAM_ROW_0 0x07
+#define DRAM_ROW_0_SDRAM 0x00
+#define DRAM_ROW_0_EMPTY 0x07
+#define DRAM_ROW_1 0x38
+#define DRAM_ROW_1_SDRAM 0x00
+#define DRAM_ROW_1_EMPTY 0x38
+#define DRAM_ROW_CNTL_LO 0x51
+#define DRAM_CAS_LATENCY 0x10
+#define DRAM_RAS_TIMING 0x08
+#define DRAM_RAS_PRECHARGE 0x04
+#define DRAM_ROW_CNTL_HI 0x52
+#define DRAM_EXT_CNTL 0x53
+#define DRAM_REFRESH_RATE 0x03
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x01
+#define DRAM_REFRESH_FAST_TEST 0x02
+#define DRAM_REFRESH_RESERVED 0x03
+#define DRAM_TIMING 0x54
+#define DRAM_ROW_BNDRY_0 0x55
+#define DRAM_ROW_BNDRY_1 0x56
+
+#define DPMS_SYNC_SELECT 0x61
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+#define PIXPIPE_CONFIG_0 0x80
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+#define PIXPIPE_CONFIG_1 0x81
+#define DISPLAY_COLOR_MODE 0x0F
+#define DISPLAY_VGA_MODE 0x00
+#define DISPLAY_8BPP_MODE 0x02
+#define DISPLAY_15BPP_MODE 0x04
+#define DISPLAY_16BPP_MODE 0x05
+#define DISPLAY_24BPP_MODE 0x06
+#define DISPLAY_32BPP_MODE 0x07
+
+#define PIXPIPE_CONFIG_2 0x82
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+#define CURSOR_CONTROL 0xA0
+#define CURSOR_ORIGIN_SCREEN 0x00
+#define CURSOR_ORIGIN_DISPLAY 0x10
+#define CURSOR_MODE 0x07
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01
+#define CURSOR_MODE_128_2C 0x02
+#define CURSOR_MODE_128_1C 0x03
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_RESERVED 0x07
+#define CURSOR_BASEADDR_LO 0xA2
+#define CURSOR_BASEADDR_HI 0xA3
+#define CURSOR_X_LO 0xA4
+#define CURSOR_X_HI 0xA5
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0xA6
+#define CURSOR_Y_HI 0xA7
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+#define VCLK2_VCO_M 0xC8
+#define VCLK2_VCO_N 0xC9
+#define VCLK2_VCO_MN_MSBS 0xCA
+#define VCO_N_MSBS 0x30
+#define VCO_M_MSBS 0x03
+#define VCLK2_VCO_DIV_SEL 0xCB
+#define POST_DIV_SELECT 0x70
+#define POST_DIV_1 0x00
+#define POST_DIV_2 0x10
+#define POST_DIV_4 0x20
+#define POST_DIV_8 0x30
+#define POST_DIV_16 0x40
+#define POST_DIV_32 0x50
+#define VCO_LOOP_DIV_BY_4M 0x00
+#define VCO_LOOP_DIV_BY_16M 0x04
+#define REF_CLK_DIV_BY_5 0x02
+#define REF_DIV_4 0x00
+#define REF_DIV_1 0x01
+
+#define PLL_CNTL 0xCE
+#define PLL_MEMCLK_SEL 0x03
+#define PLL_MEMCLK__66667KHZ 0x00
+#define PLL_MEMCLK__75000KHZ 0x01
+#define PLL_MEMCLK__88889KHZ 0x02
+#define PLL_MEMCLK_100000KHZ 0x03
+
+/* Multimedia Extension Registers (MRX) */
+#define ACQ_CNTL_1 0x02
+#define ACQ_CNTL_2 0x03
+#define FRAME_CAP_MODE 0x01
+#define CONT_CAP_MODE 0x00
+#define SINGLE_CAP_MODE 0x01
+#define ACQ_CNTL_3 0x04
+#define COL_KEY_CNTL_1 0x3C
+#define BLANK_DISP_OVERLAY 0x20
+
+/* FIFOs */
+#define LP_FIFO 0x1000
+#define HP_FIFO 0x2000
+#define INSTPNT 0x3040
+#define LP_FIFO_COUNT 0x3040
+#define HP_FIFO_COUNT 0x3041
+
+/* FIFO Commands */
+#define CLIENT 0xE0000000
+#define CLIENT_2D 0x60000000
+
+/* Command Parser Mode Register */
+#define COMPARS 0x3038
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+
+/* Interrupt Control Registers */
+#define IER 0x3030
+#define IIR 0x3032
+#define IMR 0x3034
+#define ISR 0x3036
+#define VMIINTB_EVENT 0x2000
+#define GPIO4_INT 0x1000
+#define DISP_FLIP_EVENT 0x0800
+#define DVD_PORT_DMA 0x0400
+#define DISP_VBLANK 0x0200
+#define FIFO_EMPTY_DMA_DONE 0x0100
+#define INST_PARSER_ERROR 0x0080
+#define USER_DEFINED 0x0040
+#define BREAKPOINT 0x0020
+#define DISP_HORIZ_COUNT 0x0010
+#define DISP_VSYNC 0x0008
+#define CAPTURE_HORIZ_COUNT 0x0004
+#define CAPTURE_VSYNC 0x0002
+#define THREE_D_PIPE_FLUSHED 0x0001
+
+/* FIFO Watermark and Burst Length Control Register */
+#define FWATER_BLC 0x00006000
+#define LMI_BURST_LENGTH 0x7F000000
+#define LMI_FIFO_WATERMARK 0x003F0000
+#define AGP_BURST_LENGTH 0x00007F00
+#define AGP_FIFO_WATERMARK 0x0000003F
+
+/* BitBLT Registers */
+#define SRC_DST_PITCH 0x00040000
+#define DST_PITCH 0x1FFF0000
+#define SRC_PITCH 0x00001FFF
+#define COLEXP_BG_COLOR 0x00040004
+#define COLEXP_FG_COLOR 0x00040008
+#define MONO_SRC_CNTL 0x0004000C
+#define MONO_USE_COLEXP 0x00000000
+#define MONO_USE_SRCEXP 0x08000000
+#define MONO_DATA_ALIGN 0x07000000
+#define MONO_BIT_ALIGN 0x01000000
+#define MONO_BYTE_ALIGN 0x02000000
+#define MONO_WORD_ALIGN 0x03000000
+#define MONO_DWORD_ALIGN 0x04000000
+#define MONO_QWORD_ALIGN 0x05000000
+#define MONO_SRC_INIT_DSCRD 0x003F0000
+#define MONO_SRC_RIGHT_CLIP 0x00003F00
+#define MONO_SRC_LEFT_CLIP 0x0000003F
+#define BITBLT_CONTROL 0x00040010
+#define BLTR_STATUS 0x80000000
+#define DYN_DEPTH 0x03000000
+#define DYN_DEPTH_8BPP 0x00000000
+#define DYN_DEPTH_16BPP 0x01000000
+#define DYN_DEPTH_24BPP 0x02000000
+#define DYN_DEPTH_32BPP 0x03000000 /* Not implemented on the i740 */
+#define DYN_DEPTH_ENABLE 0x00800000
+#define PAT_VERT_ALIGN 0x00700000
+#define SOLID_PAT_SELECT 0x00080000
+#define PAT_IS_IN_COLOR 0x00000000
+#define PAT_IS_MONO 0x00040000
+#define MONO_PAT_TRANSP 0x00020000
+#define COLOR_TRANSP_ROP 0x00000000
+#define COLOR_TRANSP_DST 0x00008000
+#define COLOR_TRANSP_EQ 0x00000000
+#define COLOR_TRANSP_NOT_EQ 0x00010000
+#define COLOR_TRANSP_ENABLE 0x00004000
+#define MONO_SRC_TRANSP 0x00002000
+#define SRC_IS_IN_COLOR 0x00000000
+#define SRC_IS_MONO 0x00001000
+#define SRC_USE_SRC_ADDR 0x00000000
+#define SRC_USE_BLTDATA 0x00000400
+#define BLT_TOP_TO_BOT 0x00000000
+#define BLT_BOT_TO_TOP 0x00000200
+#define BLT_LEFT_TO_RIGHT 0x00000000
+#define BLT_RIGHT_TO_LEFT 0x00000100
+#define BLT_ROP 0x000000FF
+#define BLT_PAT_ADDR 0x00040014
+#define BLT_SRC_ADDR 0x00040018
+#define BLT_DST_ADDR 0x0004001C
+#define BLT_DST_H_W 0x00040020
+#define BLT_DST_HEIGHT 0x1FFF0000
+#define BLT_DST_WIDTH 0x00001FFF
+#define SRCEXP_BG_COLOR 0x00040024
+#define SRCEXP_FG_COLOR 0x00040028
+#define BLTDATA 0x00050000
--
Ondrej Zary
^ permalink raw reply
* [PATCH v3.1] Resurrect Intel740 driver: i740fb
From: Ondrej Zary @ 2011-10-28 20:50 UTC (permalink / raw)
To: linux-fbdev
Cc: Florian Tobias Schandinat, Paul Mundt, Kernel development list
Hello,
this is an v3 attempt to resurrect 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/
It was easier to create 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 v3:
- added suspend/resume support
- fixed x panning
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
this time with Makefile patch
--- linux-2.6.39-rc2-orig/drivers/video/Makefile 2011-04-06 03:30:43.000000000 +0200
+++ linux-2.6.39-rc2/drivers/video/Makefile 2011-07-30 11:34:10.000000000 +0200
@@ -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/
--- linux-2.6.39-rc2-orig/drivers/video/Kconfig 2011-04-06 03:30:43.000000000 +0200
+++ linux-2.6.39-rc2/drivers/video/Kconfig 2011-10-24 23:29:42.000000000 +0200
@@ -1117,6 +1117,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
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740fb.c 2011-10-28 20:03:34.000000000 +0200
@@ -0,0 +1,1286 @@
+/*
+ * i740fb - framebuffer driver for Intel740
+ * Copyright (c) 2011 Ondrej Zary
+ *
+ * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru> which was partially based on:
+ * VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * i740fb by Patrick LERDA, v0.9
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#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>
+#include <linux/console.h>
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "i740_reg.h"
+
+static char *mode_option __devinitdata;
+
+#ifdef CONFIG_MTRR
+static int mtrr __devinitdata = 1;
+#endif
+
+struct i740fb_par {
+ unsigned char __iomem *regs;
+ bool has_sgram;
+#ifdef CONFIG_MTRR
+ int mtrr_reg;
+#endif
+ bool ddc_registered;
+ struct i2c_adapter ddc_adapter;
+ struct i2c_algo_bit_data ddc_algo;
+ u32 pseudo_palette[16];
+ struct mutex open_lock;
+ unsigned int ref_count;
+
+ u8 crtc[VGA_CRT_C];
+ u8 atc[VGA_ATT_C];
+ u8 gdc[VGA_GFX_C];
+ u8 seq[VGA_SEQ_C];
+ u8 misc;
+ u8 vss;
+
+ /* i740 specific registers */
+ u8 display_cntl;
+ u8 pixelpipe_cfg0;
+ u8 pixelpipe_cfg1;
+ u8 pixelpipe_cfg2;
+ u8 video_clk2_m;
+ u8 video_clk2_n;
+ u8 video_clk2_mn_msbs;
+ u8 video_clk2_div_sel;
+ u8 pll_cntl;
+ u8 address_mapping;
+ u8 io_cntl;
+ u8 bitblt_cntl;
+ u8 ext_vert_total;
+ u8 ext_vert_disp_end;
+ u8 ext_vert_sync_start;
+ u8 ext_vert_blank_start;
+ u8 ext_horiz_total;
+ u8 ext_horiz_blank;
+ u8 ext_offset;
+ u8 interlace_cntl;
+ u32 lmi_fifo_watermark;
+ u8 ext_start_addr;
+ u8 ext_start_addr_hi;
+};
+
+#define DACSPEED8 203
+#define DACSPEED16 163
+#define DACSPEED24_SG 136
+#define DACSPEED24_SD 128
+#define DACSPEED32 86
+
+static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
+ .id = "i740fb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 8,
+ .ypanstep = 1,
+ .accel = FB_ACCEL_NONE,
+};
+
+static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb(struct i740fb_par *par, u16 port)
+{
+ return vga_mm_r(par->regs, port);
+}
+static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
+{
+ vga_mm_w_fast(par->regs, port, reg, val);
+}
+static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
+{
+ vga_mm_w(par->regs, port, reg);
+ return vga_mm_r(par->regs, port+1);
+}
+static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg, u8 val, u8 mask)
+{
+ vga_mm_w_fast(par->regs, port, reg, (val & mask) | (i740inreg(par, port, reg) & ~mask));
+}
+static inline void i740outb_p(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb_p(struct i740fb_par *par, unsigned short port)
+{
+ return vga_mm_r(par->regs, port);
+}
+
+#define REG_DDC_DRIVE 0x62
+#define REG_DDC_STATE 0x63
+#define DDC_SCL (1 << 3)
+#define DDC_SDA (1 << 2)
+
+static void i740fb_ddc_setscl(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SCL);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SCL;
+ else
+ reg &= ~DDC_SCL;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static void i740fb_ddc_setsda(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SDA);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SDA;
+ else
+ reg &= ~DDC_SDA;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static int i740fb_ddc_getscl(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SCL);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
+}
+
+static int i740fb_ddc_getsda(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SDA);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
+}
+
+static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ strlcpy(par->ddc_adapter.name, info->fix.id,
+ sizeof(par->ddc_adapter.name));
+ par->ddc_adapter.owner = THIS_MODULE;
+ par->ddc_adapter.class = I2C_CLASS_DDC;
+ par->ddc_adapter.algo_data = &par->ddc_algo;
+ par->ddc_adapter.dev.parent = info->device;
+ par->ddc_algo.setsda = i740fb_ddc_setsda;
+ par->ddc_algo.setscl = i740fb_ddc_setscl;
+ par->ddc_algo.getsda = i740fb_ddc_getsda;
+ par->ddc_algo.getscl = i740fb_ddc_getscl;
+ par->ddc_algo.udelay = 10;
+ par->ddc_algo.timeout = 20;
+ par->ddc_algo.data = par;
+
+ i2c_set_adapdata(&par->ddc_adapter, par);
+
+ return i2c_bit_add_bus(&par->ddc_adapter);
+}
+
+static int i740fb_open(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ par->ref_count++;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static int i740fb_release(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ return -EINVAL;
+ }
+
+ par->ref_count--;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
+{
+ /*
+ * Would like to calculate these values automatically, but a generic
+ * algorithm does not seem possible. Note: These FIFO water mark
+ * values were tested on several cards and seem to eliminate the
+ * all of the snow and vertical banding, but fine adjustments will
+ * probably be required for other cards.
+ */
+
+ u32 wm = 0x18120000;
+
+ switch (bpp) {
+ case 8:
+ if (freq > 200) wm = 0x18120000;
+ else if (freq > 175) wm = 0x16110000;
+ else if (freq > 135) wm = 0x120E0000;
+ else wm = 0x100D0000;
+ break;
+ case 15:
+ case 16:
+ if (par->has_sgram) {
+ if (freq > 140) wm = 0x2C1D0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24160000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ } else {
+ if (freq > 160) wm = 0x28200000;
+ else if (freq > 140) wm = 0x2A1E0000;
+ else if (freq > 130) wm = 0x2B1A0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24180000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ }
+ break;
+ case 24:
+ if (par->has_sgram) {
+ if (freq > 130) wm = 0x31200000;
+ else if (freq > 120) wm = 0x2E200000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ } else {
+ if (freq > 120) wm = 0x311F0000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ }
+ break;
+ case 32:
+ if (par->has_sgram) {
+ if (freq > 80) wm = 0x2A200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ } else {
+ if (freq > 80) wm = 0x29200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ }
+ break;
+ }
+
+ return wm;
+}
+
+/* clock calculation from i740fb by Patrick LERDA */
+
+#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)
+
+#define I740_CALC_VCLKfix(m, n, p, d) ((((((m) * I740_REF_FREQ * (4 << ((d) << 1)))) / (n)) + ((1 << (p)) / 2)) / (1 << (p)))
+
+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)))
+ 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);
+}
+
+static int i740fb_decode_var(const struct fb_var_screeninfo *var, struct i740fb_par *par, struct fb_info *info)
+{
+ /*
+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
+ * if it's too big, return -EINVAL.
+ */
+
+ u32 xres, right, hslen, left, xtotal;
+ u32 yres, lower, vslen, upper, ytotal;
+ u32 vxres, xoffset, vyres, yoffset;
+ u32 bpp, base, dacspeed24;
+ u8 r7;
+ int i;
+
+ dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
+ var->xres, var->yres, var->xres_virtual, var->xres_virtual);
+ dev_dbg(info->device, " xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
+ var->xoffset, var->yoffset, var->bits_per_pixel, var->grayscale);
+ dev_dbg(info->device, " activate: %i, nonstd: %i, vmode: %i\n",
+ var->activate, var->nonstd, var->vmode);
+ dev_dbg(info->device, " pixclock: %i, hsynclen:%i, vsynclen:%i\n",
+ var->pixclock, var->hsync_len, var->vsync_len);
+ dev_dbg(info->device, " left: %i, right: %i, up:%i, lower:%i\n",
+ var->left_margin, var->right_margin, var->upper_margin, var->lower_margin);
+
+
+ bpp = var->bits_per_pixel;
+ switch (bpp) {
+ case 1 ... 8:
+ bpp = 8;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED8) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n", 1000000 / var->pixclock, DACSPEED8);
+ return -EINVAL;
+ }
+ break;
+ case 9 ... 15:
+ bpp = 15;
+ case 16:
+ if ((((u32)1e6) / var->pixclock) > DACSPEED16) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n", 1000000 / var->pixclock, DACSPEED16);
+ return -EINVAL;
+ }
+ break;
+ case 17 ... 24:
+ bpp = 24;
+ dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
+ if ((((u32)1e6) / var->pixclock) > dacspeed24) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n", 1000000 / var->pixclock, dacspeed24);
+ return -EINVAL;
+ }
+ break;
+ case 25 ... 32:
+ bpp = 32;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED32) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n", 1000000 / var->pixclock, DACSPEED32);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ xres = (var->xres + 7) & ~7;
+ vxres = (var->xres_virtual + 0xF) & ~0xF;
+ if (vxres < xres)
+ vxres = xres;
+
+ xoffset = (var->xoffset + 7) & ~7;
+ xoffset = var->xoffset;
+ if (xres + xoffset > vxres)
+ xoffset = vxres - xres;
+
+ left = (var->left_margin + 7) & ~7;
+ right = (var->right_margin + 7) & ~7;
+ hslen = (var->hsync_len + 7) & ~7;
+
+ yres = var->yres;
+ vyres = var->yres_virtual;
+ if (yres > vyres)
+ vyres = yres;
+
+ yoffset = var->yoffset;
+ if (yres + yoffset > vyres)
+ yoffset = vyres - yres;
+
+ lower = var->lower_margin;
+ vslen = var->vsync_len;
+ upper = var->upper_margin;
+
+ if (vxres * vyres * ((bpp + 1) / 8) > info->screen_size || vyres = yres) {
+ vyres = info->screen_size / vxres / ((bpp + 1) / 8);
+ if (vyres < yres)
+ return -ENOMEM;
+ }
+
+ if (yoffset + yres > vyres)
+ yoffset = vyres - yres;
+
+ xtotal = xres + right + hslen + left;
+ ytotal = yres + lower + vslen + upper;
+
+ par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
+ par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
+ par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
+ par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
+ par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
+ | ((((xres + right + hslen) >> 3) & 0x20) << 2);
+ par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F) | 0x80;
+
+ par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
+
+ r7 = 0x10; /* disable linecompare */
+ if (ytotal & 0x100)
+ r7 |= 0x01;
+ if (ytotal & 0x200)
+ r7 |= 0x20;
+
+ par->crtc[VGA_CRTC_PRESET_ROW] = 0;
+ par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
+ if (var->vmode & FB_VMODE_DOUBLE)
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
+ par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
+ par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
+ if ((yres-1) & 0x100)
+ r7 |= 0x02;
+ if ((yres-1) & 0x200)
+ r7 |= 0x40;
+
+ par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
+ par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
+ if ((yres + lower - 1) & 0x100)
+ r7 |= 0x0C;
+ if ((yres + lower - 1) & 0x200) {
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
+ r7 |= 0x80;
+ }
+
+ par->crtc[VGA_CRTC_V_SYNC_END] = ((yres + lower - 1 + vslen) & 0x0F) & ~0x10; /* disabled IRQ */
+ par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF; /* 0x7F for original VGA, but some SVGA chips requires all 8 bits to set */
+
+ par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
+ par->crtc[VGA_CRTC_MODE] = 0xC3 ;
+ par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
+ par->crtc[VGA_CRTC_OVERFLOW] = r7;
+
+ par->vss = 0x00; /* 3DA */
+
+ for (i = 0x00; i < 0x10; i++)
+ par->atc[i] = i;
+ par->atc[VGA_ATC_MODE] = 0x81;
+ par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
+ par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
+ /*par->atc[VGA_ATC_PEL] = xoffset & 7;*/
+ par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
+
+ par->misc = 0xC3;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ par->misc &= ~0x40;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ par->misc &= ~0x80;
+
+ par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
+ par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
+ par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+ par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
+
+ par->gdc[VGA_GFX_SR_VALUE] = 0x00;
+ par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
+ par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
+ par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
+ par->gdc[VGA_GFX_PLANE_READ] = 0;
+ par->gdc[VGA_GFX_MODE] = 0x02;
+ par->gdc[VGA_GFX_MISC] = 0x05;
+ par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
+ par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
+
+ base = (yoffset * vxres + (xoffset & ~7)) >> 2;
+ switch (bpp) {
+ case 8:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
+ par->ext_offset = vxres >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
+ par->bitblt_cntl = COLEXP_8BPP;
+ break;
+ case 15: /* 0rrrrrgg gggbbbbb */
+ case 16: /* rrrrrggg gggbbbbb */
+ par->pixelpipe_cfg1 = (var->green.length = 6) ? DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
+ par->ext_offset = vxres >> 10;
+ par->bitblt_cntl = COLEXP_16BPP;
+ base *= 2;
+ break;
+ case 24:
+ par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
+ par->ext_offset = (vxres * 3) >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
+ par->bitblt_cntl = COLEXP_24BPP;
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
+ par->ext_offset = vxres >> 9;
+ par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
+ par->bitblt_cntl = COLEXP_RESERVED; /* Not implemented on i740 */
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+
+ par->pixelpipe_cfg0 = DAC_8_BIT;
+
+ par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
+ par->io_cntl = EXTENDED_CRTC_CNTL;
+ par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
+ par->display_cntl = HIRES_MODE;
+
+ /* Set the MCLK freq */
+ par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
+
+ /* Calculate the extended CRTC regs */
+ par->ext_vert_total = (ytotal - 2) >> 8;
+ par->ext_vert_disp_end = (yres - 1) >> 8;
+ par->ext_vert_sync_start = (yres + lower) >> 8;
+ par->ext_vert_blank_start = (yres + lower) >> 8;
+ par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
+ par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
+
+ par->interlace_cntl = INTERLACE_DISABLE;
+
+ /* Set the overscan color to 0. (NOTE: This only affects >8bpp mode.) */
+ par->atc[VGA_ATC_OVERSCAN] = 0;
+
+ /* Calculate VCLK that most closely matches the requested dot clock */
+ i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ par->misc |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ par->lmi_fifo_watermark = i740_calc_fifo(par, ((int)1e6) / var->pixclock, bpp);
+
+ /*if (!fbmon_valid_timings(var->pixclock, ytotal, xtotal, info))
+ return -EINVAL;*/
+
+ return 0;
+}
+
+static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 16:
+ switch (var->green.length) {
+ default:
+ case 5:
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 5;
+ break;
+ case 6:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->green.length = 6;
+ var->red.length = var->blue.length = 5;
+ break;
+ }
+ break;
+ case 24:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 32:
+ var->transp.offset = 24;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->transp.length = var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ if (info->monspecs.hfmax && info->monspecs.vfmax &&
+ info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void vga_protect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) | 0x20); /* disable the display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x00); /* enable pallete access */
+}
+
+static void vga_unprotect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) & 0xDF); /* reenable display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x20); /* disable pallete access */
+}
+
+static int i740fb_set_par(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 itemp;
+ int i;
+
+ i = i740fb_decode_var(&info->var, par, info);
+ if (i)
+ return i;
+
+ memset(info->screen_base, 0, info->screen_size);
+
+ vga_protect(par);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
+
+ mdelay(1);
+
+ i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
+ i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
+ i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
+ i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
+
+ i740inb(par, 0x3DA);
+ i740outb(par, 0x3C0, 0x00);
+
+ /* update misc output register */
+ i740outb(par, VGA_MIS_W, par->misc | 0x01);
+
+ /* synchronous reset on */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
+ /* write sequencer registers */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
+ for (i = 2; i < VGA_SEQ_C; i++)
+ i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
+
+ /* synchronous reset off */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
+
+ /* deprotect CRT registers 0-7 */
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
+
+ /* write CRT registers */
+ for (i = 0; i < VGA_CRT_C; i++)
+ i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
+
+ /* write graphics controller registers */
+ for (i = 0; i < VGA_GFX_C; i++)
+ i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
+
+ /* write attribute controller registers */
+ for (i = 0; i < VGA_ATT_C; i++) {
+ i740inb_p(par, VGA_IS1_RC); /* reset flip-flop */
+ i740outb_p(par, VGA_ATT_IW, i);
+ i740outb_p(par, VGA_ATT_IW, par->atc[i]);
+ }
+
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE]);
+
+ i740inb(par, VGA_IS1_RC);
+ i740outb(par, VGA_ATT_IW, 0x20);
+
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START, par->ext_vert_sync_start);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START, par->ext_vert_blank_start);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
+ i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
+
+ i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL, par->interlace_cntl, INTERLACE_ENABLE);
+ i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
+ i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
+ i740outreg_mask(par, XRX, DISPLAY_CNTL, par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
+
+ i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1, par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
+
+ itemp = readl(par->regs + FWATER_BLC);
+ itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
+ itemp |= par->lmi_fifo_watermark;
+ writel(itemp, par->regs + FWATER_BLC);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
+
+ i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
+ i740outreg_mask(par, XRX, IO_CTNL, par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+
+ if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
+ i740outb(par, VGA_PEL_MSK, 0xFF);
+ i740outb(par, VGA_PEL_IW, 0x00);
+ for (i = 0; i < 256; i++) {
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ }
+ }
+
+ /* Wait for screen to stabilize. */
+ mdelay(50);
+ vga_unprotect(par);
+
+ info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
+ if (info->var.bits_per_pixel = 8)
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+ return 0;
+}
+
+static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n", regno, red, green, blue, transp, info->var.bits_per_pixel);
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ if (regno >= 256)
+ return 1;
+ i740outb(info->par, VGA_PEL_IW, regno);
+ i740outb(info->par, VGA_PEL_D, red >> 8);
+ i740outb(info->par, VGA_PEL_D, green >> 8);
+ i740outb(info->par, VGA_PEL_D, blue >> 8);
+ break;
+ case 15:
+ case 16:
+ if (regno >= 16)
+ return 0;
+ if (info->var.green.length = 5)
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+ else if (info->var.green.length = 6)
+ ((u32 *)info->pseudo_palette)[regno] = (red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+ else
+ return -EINVAL;
+ break;
+ case 24:
+ case 32:
+ if (regno >= 16)
+ return 0;
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int i740fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 base = (var->yoffset * var->xres_virtual + (var->xoffset & ~7)) >> 2;
+
+ dev_dbg(info->device, "pan_display: xoffset: %i, yoffset: %i base: %i\n", var->xoffset, var->yoffset, base);
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ break;
+ case 15:
+ case 16:
+ base *= 2;
+ break;
+ case 24:
+ /*
+ * The last bit does not seem to have any effect on the start
+ * address register in 24bpp mode, so...
+ */
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ /*par->atc[VGA_ATC_PEL] = var->xoffset & 7;*/
+
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO, base & 0x000000FF);
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI, (base & 0x0000FF00) >> 8);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, (base & 0x3FC00000) >> 22);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
+ /*i740outreg(par, VGA_ATT_W, VGA_ATC_PEL, var->xoffset & 7);*/
+
+ return 0;
+}
+
+static int i740fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ unsigned char SEQ01;
+ int DPMSSyncSelect;
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+ break;
+ case FB_BLANK_POWERDOWN:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Turn the screen on/off */
+ i740outb(par, SRX, 0x01);
+ SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
+ i740outb(par, SRX, 0x01);
+ i740outb(par, SRX + 1, SEQ01);
+
+ /* Set the DPMS mode */
+ i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
+
+ /* Let fbcon do a soft blank for us */
+ return (blank_mode = FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops i740fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = i740fb_open,
+ .fb_release = i740fb_release,
+ .fb_check_var = i740fb_check_var,
+ .fb_set_par = i740fb_set_par,
+ .fb_setcolreg = i740fb_setcolreg,
+ .fb_blank = i740fb_blank,
+ .fb_pan_display = i740fb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int __devinit i740fb_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ struct fb_info *info;
+ struct i740fb_par *par;
+ int ret;
+ bool found = false;
+ u8 *edid;
+
+ info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
+ if (!info) {
+ dev_err(&(dev->dev), "cannot allocate framebuffer\n");
+ return -ENOMEM;
+ }
+
+ par = info->par;
+ mutex_init(&par->open_lock);
+
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.bits_per_pixel = 8;
+ info->fbops = &i740fb_ops;
+ info->pseudo_palette = par->pseudo_palette;
+
+ ret = pci_enable_device(dev);
+ if (ret) {
+ dev_err(info->device, "cannot enable PCI device\n");
+ goto err_enable_device;
+ }
+
+ ret = pci_request_regions(dev, info->fix.id);
+ if (ret) {
+ dev_err(info->device, "error requesting regions\n");
+ goto err_request_regions;
+ }
+
+ info->screen_base = pci_ioremap_bar(dev, 0);
+ if (!info->screen_base) {
+ dev_err(info->device, "error remapping base\n");
+ ret = -ENOMEM;
+ goto err_ioremap_1;
+ }
+
+ par->regs = pci_ioremap_bar(dev, 1);
+ if (!par->regs) {
+ dev_err(info->device, "error remapping MMIO\n");
+ ret = -ENOMEM;
+ goto err_ioremap_2;
+ }
+
+ /* detect memory size */
+ if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1) = DRAM_ROW_1_SDRAM)
+ i740outb(par, XRX, DRAM_ROW_BNDRY_1);
+ else
+ i740outb(par, XRX, DRAM_ROW_BNDRY_0);
+ info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
+ /* detect memory type */
+ par->has_sgram = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
+ par->has_sgram = !((par->has_sgram & DRAM_RAS_TIMING) ||
+ (par->has_sgram & DRAM_RAS_PRECHARGE));
+
+ printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
+ pci_name(dev), info->screen_size >> 10,
+ par->has_sgram ? "SGRAM" : "SDRAM");
+
+ info->fix = i740fb_fix;
+ info->fix.mmio_start = pci_resource_start(dev, 1);
+ info->fix.mmio_len = pci_resource_len(dev, 1);
+ info->fix.smem_start = pci_resource_start(dev, 0);
+ info->fix.smem_len = info->screen_size;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ if (i740fb_setup_ddc_bus(info) = 0) {
+ par->ddc_registered = true;
+ edid = fb_ddc_read(&par->ddc_adapter);
+ if (edid) {
+ fb_edid_to_monspecs(edid, &info->monspecs);
+ kfree(edid);
+ if (!info->monspecs.modedb)
+ dev_err(info->device, "error getting mode database\n");
+ else {
+ const struct fb_videomode *m;
+
+ fb_videomode_to_modelist(info->monspecs.modedb,
+ info->monspecs.modedb_len,
+ &info->modelist);
+ m = fb_find_best_display(&info->monspecs, &info->modelist);
+ if (m) {
+ fb_videomode_to_var(&info->var, m);
+ /* fill all other info->var's fields */
+ if (i740fb_check_var(&info->var, info) = 0)
+ found = true;
+ }
+ }
+ }
+ }
+
+ if (!mode_option && !found)
+ mode_option = "640x480-8@60";
+
+ if (mode_option) {
+ ret = fb_find_mode(&info->var, info, mode_option,
+ info->monspecs.modedb, info->monspecs.modedb_len,
+ NULL, info->var.bits_per_pixel);
+ if (!ret || ret = 4) {
+ dev_err(info->device, "mode %s not found\n", mode_option);
+ ret = -EINVAL;
+ }
+ }
+
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+
+ /* maximize virtual vertical size for fast scrolling */
+ info->var.yres_virtual = info->fix.smem_len * 8 /
+ (info->var.bits_per_pixel * info->var.xres_virtual);
+
+ if (ret = -EINVAL)
+ goto err_find_mode;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ dev_err(info->device, "cannot allocate colormap\n");
+ goto err_alloc_cmap;
+ }
+
+ ret = register_framebuffer(info);
+ if (ret) {
+ dev_err(info->device, "error registering framebuffer\n");
+ goto err_reg_framebuffer;
+ }
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ pci_set_drvdata(dev, info);
+#ifdef CONFIG_MTRR
+ if (mtrr) {
+ par->mtrr_reg = -1;
+ par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+ }
+#endif
+ return 0;
+
+err_reg_framebuffer:
+ fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+err_ioremap_2:
+ pci_iounmap(dev, info->screen_base);
+err_ioremap_1:
+ pci_release_regions(dev);
+err_request_regions:
+/* pci_disable_device(dev); */
+err_enable_device:
+ framebuffer_release(info);
+ return ret;
+}
+
+static void __devexit i740fb_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+
+ if (info) {
+#ifdef CONFIG_MTRR
+ struct i740fb_par *par = info->par;
+
+ if (par->mtrr_reg >= 0) {
+ mtrr_del(par->mtrr_reg, 0, 0);
+ par->mtrr_reg = -1;
+ }
+#endif
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+ pci_iounmap(dev, info->screen_base);
+ pci_release_regions(dev);
+/* pci_disable_device(dev); */
+ pci_set_drvdata(dev, NULL);
+ framebuffer_release(info);
+ }
+}
+
+#ifdef CONFIG_PM
+static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ /* don't disable console during hibernation and wakeup from it */
+ if (state.event = PM_EVENT_FREEZE || state.event = PM_EVENT_PRETHAW)
+ return 0;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ /* do nothing if framebuffer is not active */
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+ }
+
+ fb_set_suspend(info, 1);
+
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+
+ return 0;
+}
+
+static int i740fb_resume(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ if (par->ref_count = 0)
+ goto fail;
+
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+ if (pci_enable_device(dev))
+ goto fail;
+
+ i740fb_set_par(info);
+ fb_set_suspend(info, 0);
+
+fail:
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+}
+#else
+#define i740fb_suspend NULL
+#define i740fb_resume NULL
+#endif /* CONFIG_PM */
+
+#define I740_ID_PCI 0x00d1
+#define I740_ID_AGP 0x7800
+
+static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, i740fb_id_table);
+
+static struct pci_driver i740fb_driver = {
+ .name = "i740fb",
+ .id_table = i740fb_id_table,
+ .probe = i740fb_probe,
+ .remove = __devexit_p(i740fb_remove),
+ .suspend = i740fb_suspend,
+ .resume = i740fb_resume,
+};
+
+#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)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("i740fb", &option))
+ return -ENODEV;
+ i740fb_setup(option);
+#endif
+
+ return pci_register_driver(&i740fb_driver);
+}
+
+static void __exit i740fb_exit(void)
+{
+ pci_unregister_driver(&i740fb_driver);
+}
+
+module_init(i740fb_init);
+module_exit(i740fb_exit);
+
+MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for Intel740");
+
+module_param(mode_option, charp, 0444);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740_reg.h 2011-08-14 23:47:48.000000000 +0200
@@ -0,0 +1,309 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ */
+
+/* I/O register offsets */
+#define SRX VGA_SEQ_I
+#define GRX VGA_GFX_I
+#define ARX VGA_ATT_IW
+#define XRX 0x3D6
+#define MRX 0x3D2
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6
+#define DACSTATE 0x3C7
+#define DACRX 0x3C7
+#define DACWX 0x3C8
+#define DACDATA 0x3C9
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C
+#define START_ADDR_LO 0x0D
+#define VERT_SYNC_END 0x11
+#define EXT_VERT_TOTAL 0x30
+#define EXT_VERT_DISPLAY 0x31
+#define EXT_VERT_SYNC_START 0x32
+#define EXT_VERT_BLANK_START 0x33
+#define EXT_HORIZ_TOTAL 0x35
+#define EXT_HORIZ_BLANK 0x39
+#define EXT_START_ADDR 0x40
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41
+#define EXT_START_ADDR_HI 0x42
+#define INTERLACE_CNTL 0x70
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register */
+#define MSR_R 0x3CC
+#define MSR_W 0x3C2
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0
+#define CGA_BASE 0x3D0
+
+/* System Configuration Extension Registers (XRX) */
+#define IO_CTNL 0x09
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+#define ADDRESS_MAPPING 0x0A
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+#define BITBLT_CNTL 0x20
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define CHIP_RESET 0x02
+#define BITBLT_STATUS 0x01
+
+#define DISPLAY_CNTL 0x40
+#define VGA_WRAP_MODE 0x02
+#define VGA_WRAP_AT_256KB 0x00
+#define VGA_NO_WRAP 0x02
+#define GUI_MODE 0x01
+#define STANDARD_VGA_MODE 0x00
+#define HIRES_MODE 0x01
+
+#define DRAM_ROW_TYPE 0x50
+#define DRAM_ROW_0 0x07
+#define DRAM_ROW_0_SDRAM 0x00
+#define DRAM_ROW_0_EMPTY 0x07
+#define DRAM_ROW_1 0x38
+#define DRAM_ROW_1_SDRAM 0x00
+#define DRAM_ROW_1_EMPTY 0x38
+#define DRAM_ROW_CNTL_LO 0x51
+#define DRAM_CAS_LATENCY 0x10
+#define DRAM_RAS_TIMING 0x08
+#define DRAM_RAS_PRECHARGE 0x04
+#define DRAM_ROW_CNTL_HI 0x52
+#define DRAM_EXT_CNTL 0x53
+#define DRAM_REFRESH_RATE 0x03
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x01
+#define DRAM_REFRESH_FAST_TEST 0x02
+#define DRAM_REFRESH_RESERVED 0x03
+#define DRAM_TIMING 0x54
+#define DRAM_ROW_BNDRY_0 0x55
+#define DRAM_ROW_BNDRY_1 0x56
+
+#define DPMS_SYNC_SELECT 0x61
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+#define PIXPIPE_CONFIG_0 0x80
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+#define PIXPIPE_CONFIG_1 0x81
+#define DISPLAY_COLOR_MODE 0x0F
+#define DISPLAY_VGA_MODE 0x00
+#define DISPLAY_8BPP_MODE 0x02
+#define DISPLAY_15BPP_MODE 0x04
+#define DISPLAY_16BPP_MODE 0x05
+#define DISPLAY_24BPP_MODE 0x06
+#define DISPLAY_32BPP_MODE 0x07
+
+#define PIXPIPE_CONFIG_2 0x82
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+#define CURSOR_CONTROL 0xA0
+#define CURSOR_ORIGIN_SCREEN 0x00
+#define CURSOR_ORIGIN_DISPLAY 0x10
+#define CURSOR_MODE 0x07
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01
+#define CURSOR_MODE_128_2C 0x02
+#define CURSOR_MODE_128_1C 0x03
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_RESERVED 0x07
+#define CURSOR_BASEADDR_LO 0xA2
+#define CURSOR_BASEADDR_HI 0xA3
+#define CURSOR_X_LO 0xA4
+#define CURSOR_X_HI 0xA5
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0xA6
+#define CURSOR_Y_HI 0xA7
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+#define VCLK2_VCO_M 0xC8
+#define VCLK2_VCO_N 0xC9
+#define VCLK2_VCO_MN_MSBS 0xCA
+#define VCO_N_MSBS 0x30
+#define VCO_M_MSBS 0x03
+#define VCLK2_VCO_DIV_SEL 0xCB
+#define POST_DIV_SELECT 0x70
+#define POST_DIV_1 0x00
+#define POST_DIV_2 0x10
+#define POST_DIV_4 0x20
+#define POST_DIV_8 0x30
+#define POST_DIV_16 0x40
+#define POST_DIV_32 0x50
+#define VCO_LOOP_DIV_BY_4M 0x00
+#define VCO_LOOP_DIV_BY_16M 0x04
+#define REF_CLK_DIV_BY_5 0x02
+#define REF_DIV_4 0x00
+#define REF_DIV_1 0x01
+
+#define PLL_CNTL 0xCE
+#define PLL_MEMCLK_SEL 0x03
+#define PLL_MEMCLK__66667KHZ 0x00
+#define PLL_MEMCLK__75000KHZ 0x01
+#define PLL_MEMCLK__88889KHZ 0x02
+#define PLL_MEMCLK_100000KHZ 0x03
+
+/* Multimedia Extension Registers (MRX) */
+#define ACQ_CNTL_1 0x02
+#define ACQ_CNTL_2 0x03
+#define FRAME_CAP_MODE 0x01
+#define CONT_CAP_MODE 0x00
+#define SINGLE_CAP_MODE 0x01
+#define ACQ_CNTL_3 0x04
+#define COL_KEY_CNTL_1 0x3C
+#define BLANK_DISP_OVERLAY 0x20
+
+/* FIFOs */
+#define LP_FIFO 0x1000
+#define HP_FIFO 0x2000
+#define INSTPNT 0x3040
+#define LP_FIFO_COUNT 0x3040
+#define HP_FIFO_COUNT 0x3041
+
+/* FIFO Commands */
+#define CLIENT 0xE0000000
+#define CLIENT_2D 0x60000000
+
+/* Command Parser Mode Register */
+#define COMPARS 0x3038
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+
+/* Interrupt Control Registers */
+#define IER 0x3030
+#define IIR 0x3032
+#define IMR 0x3034
+#define ISR 0x3036
+#define VMIINTB_EVENT 0x2000
+#define GPIO4_INT 0x1000
+#define DISP_FLIP_EVENT 0x0800
+#define DVD_PORT_DMA 0x0400
+#define DISP_VBLANK 0x0200
+#define FIFO_EMPTY_DMA_DONE 0x0100
+#define INST_PARSER_ERROR 0x0080
+#define USER_DEFINED 0x0040
+#define BREAKPOINT 0x0020
+#define DISP_HORIZ_COUNT 0x0010
+#define DISP_VSYNC 0x0008
+#define CAPTURE_HORIZ_COUNT 0x0004
+#define CAPTURE_VSYNC 0x0002
+#define THREE_D_PIPE_FLUSHED 0x0001
+
+/* FIFO Watermark and Burst Length Control Register */
+#define FWATER_BLC 0x00006000
+#define LMI_BURST_LENGTH 0x7F000000
+#define LMI_FIFO_WATERMARK 0x003F0000
+#define AGP_BURST_LENGTH 0x00007F00
+#define AGP_FIFO_WATERMARK 0x0000003F
+
+/* BitBLT Registers */
+#define SRC_DST_PITCH 0x00040000
+#define DST_PITCH 0x1FFF0000
+#define SRC_PITCH 0x00001FFF
+#define COLEXP_BG_COLOR 0x00040004
+#define COLEXP_FG_COLOR 0x00040008
+#define MONO_SRC_CNTL 0x0004000C
+#define MONO_USE_COLEXP 0x00000000
+#define MONO_USE_SRCEXP 0x08000000
+#define MONO_DATA_ALIGN 0x07000000
+#define MONO_BIT_ALIGN 0x01000000
+#define MONO_BYTE_ALIGN 0x02000000
+#define MONO_WORD_ALIGN 0x03000000
+#define MONO_DWORD_ALIGN 0x04000000
+#define MONO_QWORD_ALIGN 0x05000000
+#define MONO_SRC_INIT_DSCRD 0x003F0000
+#define MONO_SRC_RIGHT_CLIP 0x00003F00
+#define MONO_SRC_LEFT_CLIP 0x0000003F
+#define BITBLT_CONTROL 0x00040010
+#define BLTR_STATUS 0x80000000
+#define DYN_DEPTH 0x03000000
+#define DYN_DEPTH_8BPP 0x00000000
+#define DYN_DEPTH_16BPP 0x01000000
+#define DYN_DEPTH_24BPP 0x02000000
+#define DYN_DEPTH_32BPP 0x03000000 /* Not implemented on the i740 */
+#define DYN_DEPTH_ENABLE 0x00800000
+#define PAT_VERT_ALIGN 0x00700000
+#define SOLID_PAT_SELECT 0x00080000
+#define PAT_IS_IN_COLOR 0x00000000
+#define PAT_IS_MONO 0x00040000
+#define MONO_PAT_TRANSP 0x00020000
+#define COLOR_TRANSP_ROP 0x00000000
+#define COLOR_TRANSP_DST 0x00008000
+#define COLOR_TRANSP_EQ 0x00000000
+#define COLOR_TRANSP_NOT_EQ 0x00010000
+#define COLOR_TRANSP_ENABLE 0x00004000
+#define MONO_SRC_TRANSP 0x00002000
+#define SRC_IS_IN_COLOR 0x00000000
+#define SRC_IS_MONO 0x00001000
+#define SRC_USE_SRC_ADDR 0x00000000
+#define SRC_USE_BLTDATA 0x00000400
+#define BLT_TOP_TO_BOT 0x00000000
+#define BLT_BOT_TO_TOP 0x00000200
+#define BLT_LEFT_TO_RIGHT 0x00000000
+#define BLT_RIGHT_TO_LEFT 0x00000100
+#define BLT_ROP 0x000000FF
+#define BLT_PAT_ADDR 0x00040014
+#define BLT_SRC_ADDR 0x00040018
+#define BLT_DST_ADDR 0x0004001C
+#define BLT_DST_H_W 0x00040020
+#define BLT_DST_HEIGHT 0x1FFF0000
+#define BLT_DST_WIDTH 0x00001FFF
+#define SRCEXP_BG_COLOR 0x00040024
+#define SRCEXP_FG_COLOR 0x00040028
+#define BLTDATA 0x00050000
--
Ondrej Zary
^ permalink raw reply
* [GIT PULL] fbdev updates for 3.2
From: Florian Tobias Schandinat @ 2011-10-30 10:14 UTC (permalink / raw)
To: Linus Torvalds; +Cc: LKML, linux-fbdev@vger.kernel.org
Hi Linus,
please pull the following changes to the fbdev subsystem. It contains
- a series from Laurent which touches many different drivers to sanitize their
panning behavior
- two patches to fix the suspend/resume locking issue
- a little fix to our EDID parsing
- a new driver for SMSC UFX6000/7000 USB display devices
- a new driver for Aeroflex Gaisler GRVGA IP core
- a lot of driver updates for OMAP, sh_mobile, fsl-diu-fb, au1200fb, udlfb and
viafb, a few patches to others
It's the same tree (only a different branch) you used to pull viafb updates from
so, I think, you can trust it. You will probably experience some (trivial) merge
conflicts related to xgifb and OMAP, please let me know if you want me to handle
them.
Thanks,
Florian Tobias Schandinat
The following changes since commit 976d167615b64e14bc1491ca51d424e2ba9a5e84:
Linux 3.1-rc9 (2011-10-04 18:11:50 -0700)
are available in the git repository at:
git://github.com/schandinat/linux-2.6.git fbdev-next
Ajay Kumar (1):
video: s3c-fb: Add S5P64X0 specific s3c_fb_driverdata
Anatolij Gustschin (1):
video: mb862xx-i2c: fix for reliable decoder register access
Andrew Kephart (1):
udlfb: Search config descriptor if not at device level
Andy Doan (1):
OMAPFB: make debug message more useful
Archit Taneja (26):
OMAP: DSS2: DISPC: Prepare dispc_dump_regs() for shortening
OMAP: DSS2: DISPC: Shorten dispc_dump_regs()
OMAP: DSS2: DISPC: dispc_save_context() and dispc_restore_context() cleanup
OMAP: DSS2: DISPC: Shorten _dispc_set_color_conv_coef()
OMAP: DSS2: Use a macro to declare size of the fifo_size array in dispc.c
OMAP: DSS2: Use MIPI DSI enums from include/video/mipi_display.h
OMAP: DSS2: DSI: Represent L4 and VP as sources of VC instead of modes
OMAP: DSS2: Create enum for DSI operation modes
OMAP: DSS2: DSI: Introduce generic write functions
OMAP: DSS2: DSI: Remove functions dsi_vc_dcs_read_1() and dsi_vc_dcs_read_2()
OMAP: DSS2: DSI: Split dsi_vc_dcs_read() into 2 functions
OMAP: DSS2: DSI: Introduce generic read functions
OMAP: DSS2: Clean up stallmode and io pad mode selection
OMAP: DSS2: Create an enum for DSI pixel formats
OMAP: DSS2: DSI: Send zero length packet in dsi_vc_send_null()
OMAP: DSS2: DSI Video mode support
OMAPDSS: DISPC: Reduce the number of arguments in dispc_ovl_setup()
OMAPDSS: DISPC: Pass overlay params as arguments to dispc_ovl_setup()
OMAPDSS: DISPC: Create helper function dispc_mgr_is_lcd()
OMAPDSS: DISPC: Get correct pixel clock for TV manager
OMAPDSS: DISPC: Remove hardcoded use of PPL in five tap clock calculation
OMAPDSS: DISPC: Clean up scaling related clock and five tap calculations
OMAPDSS: FEATURES: Create a range param to get max downscaling
OMAPDSS/OMAP_VOUT: Fix incorrect OMAP3-alpha compatibility setting
OMAPDSS: DISPC: VIDEO3 pipeline support
OMAPDSS: DISPC: zorder support for DSS overlays
Arnd Bergmann (1):
video/omap: fix build dependencies
Axel Lin (3):
video: mxsfb: add missing include of linux/module.h
video: nuc900fb: remove include of mach/clkdev.h
video: platinumfb: Add __devexit_p at necessary place
Bernie Thompson (4):
drivers/video/udlfb match class, subclass, and protocol
udlfb: add more comprehensive support for DPMS FB_BLANK_* modes
udlfb: Enable fb_defio by default
udlfb: Enable fbcon access to framebuffer by default
Bruno Prémont (1):
fb: sh-mobile: Fix deadlock risk between lock_fb_info() and console_lock()
Damian Hobson-Garcia (5):
fbdev: sh_mobile_meram: Enable runtime PM
fbdev: sh_mobile_meram: Enable/disable MERAM along with LCDC
fbdev: sh_mobile_meram: Move private data from .h to .c
fbdev: sh_mobile_meram: Backup/restore device registers on shutdown/resume
fbdev: sh_mobile_meram: Assign meram to the SH7372_A4LC power domain
Dan Carpenter (1):
smscufx: change edid data to u8 instead of char
Daniel Morsing (1):
OMAP: DSS2: Don't allow moving managers away from enabled displays
Dima Zavin (1):
OMAP: DSS: dispc: enable/disable clocks in error handler
Dr. David Alan Gilbert (1):
udlfb: fix issues found with Sparse static analysis
Florian Tobias Schandinat (21):
viafb: use display information in info not in var for panning
viafb: improve pitch handling
viafb: use more compact modesetting functions
viafb: kill viafb_load_crtc_timing
viafb: remove superfluous register unlocking/locking
viafb: remove superfluous mode lookup
viafb: simplify viafb_fill_crtc_timing
viafb: remove 640x480-60 CRT special case
viafb: add new funcions to select a single mode
viafb: eliminate viafb_get_pixclock
viafb: use information in var for modesetting
viafb: seperate hardware initialization
viafb: eliminate modetable dependancy of LCD modesetting
viafb: get rid of the remaining modetable structure assumptions
Merge commit 'v3.1-rc2' into HEAD
Merge branch 'pan-fixes' of git://linuxtv.org/pinchartl/fbdev into fbdev-next
Merge branch 'master' of git://git.kernel.org/.../lethal/fbdev-3.x into
fbdev-next
Merge branch 'sh-mobile-lcdc' of git://linuxtv.org/pinchartl/fbdev into
fbdev-next
Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6 into
fbdev-next
Merge commit 'v3.1-rc9' into fbdev-next
Merge branch 'for-florian' of git://gitorious.org/linux-omap-dss2/linux
into fbdev-next
Herton Ronaldo Krzesinski (1):
fb: avoid possible deadlock caused by fb_set_suspend
Jean Delvare (1):
carminefb: Fix module parameters permissions
Jesper Juhl (1):
Remove unneeded version.h includes from drivers/video/
Jingoo Han (1):
video: s3c-fb: Add support EXYNOS4 FIMD
Joe Perches (1):
video: Fix speficied typo
Julia Lawall (1):
drivers/video/msm/mdp.c: adjust error handling code
Kay Sievers (1):
drivers/video/udlfb bind framebuffer to interface.
Kristoffer Glembo (1):
video: Add Aeroflex Gaisler GRVGA framebuffer device driver
Laurent Pinchart (77):
vfb: use display information in info not in var for panning
staging: xgifb: use display information in info not in var for panning
acornfb: Dont BUG() on invalid pan parameters
s3fb: use display information in info not in var for panning
mx3fb: use display information in info not in var for panning
neofb: use display information in info not in var for panning
savagefb: use display information in info not in var for panning
sm501fb: use display information in info not in var for panning
imsttfb: use display information in info not in var for panning
gxt4500: use display information in info not in var for panning
pm2fb: use display information in info not in var for panning
sisfb: use display information in info not in var for panning
atmel_lcdfb: use display information in info not in var for panning
intelfb: use display information in info not in var for panning
tridentfb: use display information in info not in var for panning
vga16fb: use display information in info not in var for panning
radeonfb: use display information in info not in var for panning
hgafb: use display information in info not in var for panning
pm3fb: use display information in info not in var for panning
acornfb: use display information in info not in var for panning
fbdev: unicore32: use display information in info not in var for panning
s3c-fb: use display information in info not in var for panning
mb862xxfb: use display information in info not in var for panning
g364fb: use display information in info not in var for panning
arkfb: use display information in info not in var for panning
68328fb: use display information in info not in var for panning
vt8623fb: use display information in info not in var for panning
vt8500lcdfb: use display information in info not in var for panning
fbdev: da8xx: use display information in info not in var for panning
fbdev: sh_mobile_lcdc: Turn dot clock on before resuming from runtime PM
fbdev: sh_mobile_lcdc: Replace hardcoded register values with macros
fbdev: sh_mobile_lcdc: Don't acknowlege interrupts unintentionally
fbdev: sh_mobile_lcdc: Compute clock pattern using divider denominator
fbdev: sh_mobile_lcdc: Split LCDC start code from sh_mobile_lcdc_start
fbdev: sh_mobile_lcdc: Store the frame buffer base address when panning
fbdev: sh_mobile_lcdc: Restart LCDC in runtime PM resume handler
fbdev: sh_mobile_meram: Replace hardcoded register values with macros
fbdev: sh_mobile_meram: Validate ICB configuration outside mutex
fbdev: sh_mobile_meram: Fix MExxCTL register save on runtime PM suspend
fbdev: sh_mobile_meram: Remove unneeded sh_mobile_meram.h
68328fb: use display information in info not in var for panning
acornfb: Dont BUG() on invalid pan parameters
acornfb: use display information in info not in var for panning
arkfb: use display information in info not in var for panning
atmel_lcdfb: use display information in info not in var for panning
radeonfb: use display information in info not in var for panning
fbdev: da8xx: use display information in info not in var for panning
fbdev: unicore32: use display information in info not in var for panning
g364fb: use display information in info not in var for panning
gxt4500: use display information in info not in var for panning
hgafb: use display information in info not in var for panning
imsttfb: use display information in info not in var for panning
intelfb: use display information in info not in var for panning
mb862xxfb: use display information in info not in var for panning
mx3fb: use display information in info not in var for panning
neofb: use display information in info not in var for panning
pm2fb: use display information in info not in var for panning
pm3fb: use display information in info not in var for panning
s3c-fb: use display information in info not in var for panning
s3fb: use display information in info not in var for panning
savagefb: use display information in info not in var for panning
sisfb: use display information in info not in var for panning
sm501fb: use display information in info not in var for panning
tridentfb: use display information in info not in var for panning
vfb: use display information in info not in var for panning
vga16fb: use display information in info not in var for panning
vt8500lcdfb: use display information in info not in var for panning
vt8623fb: use display information in info not in var for panning
staging: xgifb: use display information in info not in var for panning
sh_mobile_meram: Reset ICBs at unregistration time
fbdev: sh_mobile_lcdc: Adjust requested parameters in .fb_check_var
fbdev: sh_mobile_lcdc: Add support for format changes at runtime
fbdev: sh_mobile_lcdc: use display information in info for panning
fbdev: sh_mobile_lcdc: Update fix.line_length in .fb_set_par()
fbdev: sh_mobile_lcdc: Avoid forward declarations
fbdev: sh_mobile_lcdc: Split channel initialization from probe function
fbdev: sh_mobile_lcdc: Remove sh_mobile_lcdc_set_bpp()
Manjunathappa, Prakash (2):
video: da8xx-fb: Interrupt configuration of revised LCDC IP
video: da8xx-fb: Increased resolution configuration of revised LCDC IP
Manuel Lauss (7):
au1200fb: use framebuffer_alloc()
au1200fb: fixup PM
au1200fb: make number of windows configurable at load time.
au1200fb: switch to FB_SYS helpers
au1200fb: fix hardcoded IRQ
fbdev: au1200fb: silence debug output
fb: fix au1100fb bitrot.
Mayuresh Janorkar (1):
OMAP: DSS2: Add picodlp panel driver
Mythri P K (14):
OMAP4: DSS2: HDMI: HDMI clean up to pass base_address
OMAP4: DSS2: HDMI: Move pll and video configuration
OMAP4: DSS2: HDMI: Use specific HDMI timings structure
OMAP4: DSS2: HDMI: Move HDMI IP independent generic header
OMAP4: DSS2: HDMI: Move the EDID definition from HDMI
OMAP4: DSS2: HDMI: Split the current HDMI driver to move
OMAP4: DSS2: HDMI: Move the HDMI IP dependent audio
OMAP4: DSS2: HDMI: Rename the functions in HDMI IP library
OMAP4: DSS2: HDMI: Function pointer approach to call
OMAP4: DSS2: Rename hdmi_omap4_panel.c to hdmi_panel.c
OMAPDSS: HDMI: Move the comments in avi infoframe
OMAPDSS: HDMI: Replace hdmi_reg struct with u16
OMAPDSS: HDMI: Add missing register definitions
OMAPDSS: HDMI: Add support to dump registers through debugfs
Paul Mundt (4):
Merge branch 'fbdev/panning-fixes'
Merge branch 'fbdev/stable-updates'
Merge branch 'fbdev/stable-updates'
Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6
Steve Glendinning (2):
Add support for SMSC UFX6000/7000 USB display adapters
smscufx: reduce number of casts in ufx_raw_rect
Stuart Hopkins (1):
udlfb: Add module option to do without shadow framebuffer
Tejun Heo (1):
video: don't use flush_scheduled_work() in fb_defio
Thomas Weber (2):
OMAP: DSS2: Support for Innolux AT070TN83
OMAP: Devkit8000: Change lcd driver to AT070TN83
Timur Tabi (24):
drivers/video: use strings to specify the Freescale DIU monitor port
fbdev: fix indentation in modedb.c
drivers/video: fsl-diu-fb: clean up whitespace and formatting
drivers/video: fsl-diu-fb: clean up printk usage
drivers/video: fsl-diu-fb: remove unused ioctls
drivers/video: fsl-diu-fb: fix compilation warning
drivers/video: fsl-diu-fb: improve device tree usage
drivers/video: fsl-diu-fb: remove redundant default video mode
drivers/video: fsl-diu-fb: improve local variable usage in some functions
drivers/video: fsl-diu-fb: set the driver name to "fsl-diu-fb"
drivers/video: fsl-diu-fb: fix potential memcpy buffer overflow bug
drivers/video: fsl-diu-fb: fix memory leak on error
drivers/video: fsl-diu-fb: use a normal for-loop to uninstall framebuffers
drivers/video: fsl-diu-fb: the video buffer is not I/O memory
drivers/video: fsl-diu-fb: remove unusued MEM_ALLOC_THRESHOLD
drivers/video: fsl-diu-fb: fix some ioctls
drivers/video: fsl-diu-fb: move some definitions out of the header file
drivers/video: fsl-diu-fb: remove broken screen blanking support
drivers/video: fsl-diu-fb: add several new video modes
drivers/video: fsl-diu-fb: use an enum for the AOI index
drivers/video: fsl-diu-fb: remove unused panel operating mode support
drivers/video: fsl-diu-fb: only DIU modes 0 and 1 are supported
drivers/video: fsl-diu-fb: merge diu_hw into fsl_diu_data
drivers/video: fsl-diu-fb: merge diu_pool into fsl_diu_data
Tomi Valkeinen (64):
fbdev: fix parsing of standard timings
OMAP: DSS2: PicoDLP: fix error handling in power_on
OMAP: DSS2: check for manager when enabling display
Revert "HACK: OMAP: DSS2: clk hack for OMAP2/3"
Revert "OMAP: DSS2: HDMI: fix hdmi clock name"
OMAP: DSS2: remove unneeded fck enable/disables
OMAP: DSS2: Change DSI device naming
OMAP4: TWL: Add common omapdss supplies
OMAP: DSS2: DSI: Improve dsi_mux_pads parameters
OMAP: DSS2: Implement dsi_mux_pads for OMAP4
OMAP: OMAPFB: make omapfb start even when a display is missing a driver
OMAP: DSS2: fix clock sources on error and uninit
OMAP: DSS2: Handle manager change in apply
OMAP: DSS2: Remove "EXPERIMENTAL" from Kconfig
OMAP: DSS2: Remove support for non-DISPC overlays
OMAP: DSS2: DISPC: use lookup tables for bit shifts
OMAP: DSS2: Add overlay caps to DSS features
OMAP: DSS2: Add GLOBAL_ALPHA & PRE_MULT_ALPHA to ovl caps
OMAP: DSS2: string parsing cleanups
OMAP: OMAPFB: string parsing cleanups
OMAP: DSS2: DISPC: remove non-existing func prototypes
OMAP: DSS2: DISPC: rename overlay related funcs
OMAP: DSS2: DISPC: rename manager related funcs
OMAP: DSS2: reorganize functions in dss.h
OMAP: DSS2: DISPC: Fix minimum PCD value
OMAP: DSS2: HDMI: use default dividers
OMAP: DSS2: HDMI: change regn definition
OMAP: DSS2: DSI: Add comment about regn
OMAP: DSS2: DISPC: Add missing IRQ definitions
OMAP: DSS2: add dss_get_hdmi_venc_clk_source()
OMAP: DSS2: DISPC: improve dispc_mgr_enable_digit_out()
OMAP: DSS2: HDMI: improve hdmi output enable
OMAP: DSS2: add read_edid() to omap_dss_driver struct
OMAP: DSS2: add detect() to omap_dss_driver struct
OMAP: DSS2: HDMI: make set_timing saner
OMAP: DSS2: HDMI: implement read_edid()
OMAP: DSS2: HDMI: remove edid parsing
OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
OMAP: DSS2: HDMI: clean up edid reading & fix checksum
OMAP: DSS2: HDMI: remove error prints in check_timings
OMAP: DSS2: HDMI: implement detect()
OMAP: DSS2: add panel-dvi driver
OMAP: use dvi panel driver instead of generic-dpi
OMAP: stalker: Remove LCD device from board file
OMAP: DSS2: panel-generic-dpi: remove "generic" panel
OMAP: Add DDC i2c_bus_num to board files
OMAPFB: find best mode from edid
OMAPDSS: Taal: remove external backlight support
OMAPFB: Remove unused lcd drivers
OMAPDSS: Port 2430sdp display driver to DSS2
OMAPDSS: Port the H4 display driver to DSS2
OMAPDSS: Port the Apollon display driver to DSS2
OMAPDSS: Add N800 panel driver
OMAPDSS: remove vaddr from overlay info
OMAP: 4430SDP: Remove unneeded lcd config
OMAP4: 4430SDP: Add panel support to board file
OMAP4: 4430SDP: Add picodlp support to board file
OMAP: RX51: Remove unused old omapfb stuff
OMAP: omap3touchbook: Remove unused lcd stuff
OMAP: 2420SDP: Port the display driver to new DSS2
OMAP: LDP: Port the display driver to new DSS2
OMAP: H4: Port the display driver to new DSS2
OMAP: Apollon: Port the display driver to new DSS2
OMAPDSS: picodlp: add missing #include <linux/module.h>
Wang Shaoyan (2):
viafb: fix pointer type missmatch
viafb: replace strict_strtoul to kstrto* and check return value
Wolfram Sang (1):
video: s3c2410: remove unused variable
Wolfram Stering (1):
mx3fb: fix NULL pointer dereference in screen blanking.
Yong Zhang (1):
video: irq: Remove IRQF_DISABLED
Documentation/fb/udlfb.txt | 39 +-
MAINTAINERS | 6 +
arch/arm/mach-omap2/board-2430sdp.c | 78 +-
arch/arm/mach-omap2/board-3430sdp.c | 7 +-
arch/arm/mach-omap2/board-4430sdp.c | 208 ++-
arch/arm/mach-omap2/board-am3517evm.c | 6 +-
arch/arm/mach-omap2/board-apollon.c | 35 +-
arch/arm/mach-omap2/board-cm-t35.c | 6 +-
arch/arm/mach-omap2/board-devkit8000.c | 10 +-
arch/arm/mach-omap2/board-h4.c | 42 +-
arch/arm/mach-omap2/board-igep0020.c | 8 +-
arch/arm/mach-omap2/board-ldp.c | 123 ++-
arch/arm/mach-omap2/board-omap3beagle.c | 8 +-
arch/arm/mach-omap2/board-omap3evm.c | 7 +-
arch/arm/mach-omap2/board-omap3pandora.c | 2 +-
arch/arm/mach-omap2/board-omap3stalker.c | 40 +-
arch/arm/mach-omap2/board-omap3touchbook.c | 18 -
arch/arm/mach-omap2/board-omap4panda.c | 8 +-
arch/arm/mach-omap2/board-overo.c | 7 +-
arch/arm/mach-omap2/board-rx51.c | 25 -
arch/arm/mach-omap2/display.c | 60 +-
arch/arm/mach-omap2/twl-common.c | 11 +-
arch/arm/mach-shmobile/board-mackerel.c | 1 +
arch/powerpc/platforms/512x/mpc512x_shared.c | 24 +-
arch/powerpc/platforms/85xx/p1022_ds.c | 47 +-
arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 55 +-
arch/powerpc/sysdev/fsl_soc.h | 25 +-
drivers/media/video/omap/omap_vout.c | 18 +-
drivers/staging/xgifb/XGI_main_26.c | 22 +-
drivers/video/68328fb.c | 4 +-
drivers/video/Kconfig | 34 +-
drivers/video/Makefile | 2 +
drivers/video/acornfb.c | 5 +-
drivers/video/arkfb.c | 9 +-
drivers/video/atmel_lcdfb.c | 15 +-
drivers/video/aty/radeon_base.c | 10 +-
drivers/video/au1100fb.c | 181 +--
drivers/video/au1100fb.h | 6 +-
drivers/video/au1200fb.c | 299 ++--
drivers/video/backlight/adp8860_bl.c | 1 -
drivers/video/backlight/adp8870_bl.c | 1 -
drivers/video/bf54x-lq043fb.c | 2 +-
drivers/video/bfin-lq035q1-fb.c | 2 +-
drivers/video/bfin-t350mcqb-fb.c | 2 +-
drivers/video/bfin_adv7393fb.c | 2 +-
drivers/video/carminefb.c | 6 +-
drivers/video/controlfb.c | 2 +-
drivers/video/da8xx-fb.c | 186 ++-
drivers/video/fb-puv3.c | 4 +-
drivers/video/fb_defio.c | 3 +-
drivers/video/fbmem.c | 3 -
drivers/video/fbmon.c | 21 +-
drivers/video/fbsysfs.c | 3 +
drivers/video/fsl-diu-fb.c | 992 +++++-----
drivers/video/g364fb.c | 5 +-
drivers/video/grvga.c | 579 ++++++
drivers/video/gxt4500.c | 4 +-
drivers/video/hgafb.c | 4 +-
drivers/video/imsttfb.c | 2 +-
drivers/video/intelfb/intelfbhw.c | 6 +-
drivers/video/mb862xx/mb862xx-i2c.c | 2 +-
drivers/video/mb862xx/mb862xxfbdrv.c | 6 +-
drivers/video/modedb.c | 444 +++---
drivers/video/msm/mddi.c | 2 +-
drivers/video/msm/mdp.c | 6 +-
drivers/video/mx3fb.c | 19 +-
drivers/video/mxsfb.c | 1 +
drivers/video/neofb.c | 4 +-
drivers/video/nuc900fb.c | 3 +-
drivers/video/omap/Kconfig | 29 -
drivers/video/omap/Makefile | 8 -
drivers/video/omap/lcd_2430sdp.c | 203 --
drivers/video/omap/lcd_apollon.c | 136 --
drivers/video/omap/lcd_h4.c | 117 --
drivers/video/omap/lcd_ldp.c | 201 --
drivers/video/omap/lcd_omap3beagle.c | 130 --
drivers/video/omap/lcd_omap3evm.c | 193 --
drivers/video/omap/lcd_overo.c | 180 --
drivers/video/omap2/displays/Kconfig | 28 +-
drivers/video/omap2/displays/Makefile | 3 +
drivers/video/omap2/displays/panel-dvi.c | 363 ++++
drivers/video/omap2/displays/panel-generic-dpi.c | 113 +-
drivers/video/omap2/displays/panel-n8x0.c | 747 ++++++++
drivers/video/omap2/displays/panel-picodlp.c | 594 ++++++
drivers/video/omap2/displays/panel-picodlp.h | 288 +++
drivers/video/omap2/displays/panel-taal.c | 125 +-
drivers/video/omap2/dss/Kconfig | 2 +-
drivers/video/omap2/dss/Makefile | 2 +-
drivers/video/omap2/dss/core.c | 4 +
drivers/video/omap2/dss/dispc.c | 1700 +++++++----------
drivers/video/omap2/dss/dispc.h | 57 +
drivers/video/omap2/dss/display.c | 31 +-
drivers/video/omap2/dss/dpi.c | 28 +-
drivers/video/omap2/dss/dsi.c | 929 ++++++----
drivers/video/omap2/dss/dss.c | 18 +-
drivers/video/omap2/dss/dss.h | 156 +-
drivers/video/omap2/dss/dss_features.c | 130 ++-
drivers/video/omap2/dss/dss_features.h | 17 +-
drivers/video/omap2/dss/hdmi.c | 1260 ++-----------
.../omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} | 68 +-
drivers/video/omap2/dss/manager.c | 191 +--
drivers/video/omap2/dss/overlay.c | 122 +-
drivers/video/omap2/dss/rfbi.c | 45 +-
drivers/video/omap2/dss/sdi.c | 19 +-
drivers/video/omap2/dss/ti_hdmi.h | 138 ++
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 1239 ++++++++++++
.../video/omap2/dss/{hdmi.h => ti_hdmi_4xxx_ip.h} | 400 ++---
drivers/video/omap2/dss/venc.c | 27 +-
drivers/video/omap2/omapfb/Kconfig | 2 +-
drivers/video/omap2/omapfb/omapfb-main.c | 134 ++-
drivers/video/omap2/omapfb/omapfb-sysfs.c | 6 +-
drivers/video/platinumfb.c | 4 +-
drivers/video/pm2fb.c | 6 +-
drivers/video/pm3fb.c | 6 +-
drivers/video/ps3fb.c | 2 +-
drivers/video/pxa3xx-gcu.c | 4 +-
drivers/video/pxafb.c | 2 +-
drivers/video/s3c-fb.c | 117 ++-
drivers/video/s3c2410fb.c | 3 +-
drivers/video/s3fb.c | 9 +-
drivers/video/sa1100fb.c | 3 +-
drivers/video/savage/savagefb_driver.c | 16 +-
drivers/video/sh_mobile_hdmi.c | 47 +-
drivers/video/sh_mobile_lcdcfb.c | 1162 ++++++------
drivers/video/sh_mobile_lcdcfb.h | 12 +-
drivers/video/sh_mobile_meram.c | 208 ++-
drivers/video/sh_mobile_meram.h | 41 -
drivers/video/sis/sis_main.c | 30 +-
drivers/video/skeletonfb.c | 2 +-
drivers/video/sm501fb.c | 6 +-
drivers/video/smscufx.c | 1994 ++++++++++++++++++++
drivers/video/tmiofb.c | 2 +-
drivers/video/tridentfb.c | 4 +-
drivers/video/udlfb.c | 187 ++-
drivers/video/valkyriefb.c | 2 +-
drivers/video/vfb.c | 4 +-
drivers/video/vga16fb.c | 2 +-
drivers/video/via/dvi.c | 34 +-
drivers/video/via/dvi.h | 3 +-
drivers/video/via/global.c | 2 +
drivers/video/via/global.h | 2 +
drivers/video/via/hw.c | 544 +-----
drivers/video/via/hw.h | 285 +---
drivers/video/via/lcd.c | 53 +-
drivers/video/via/lcd.h | 7 +-
drivers/video/via/share.h | 23 +-
drivers/video/via/via-core.c | 2 +-
drivers/video/via/via_modesetting.c | 104 +
drivers/video/via/via_modesetting.h | 23 +
drivers/video/via/viafbdev.c | 182 +-
drivers/video/via/viamode.c | 60 +-
drivers/video/via/viamode.h | 4 +-
drivers/video/vt8500lcdfb.c | 6 +-
drivers/video/vt8623fb.c | 9 +-
drivers/video/xilinxfb.c | 1 -
include/linux/fsl-diu-fb.h | 92 +-
include/video/omap-panel-dvi.h | 37 +
include/video/omap-panel-n8x0.h | 15 +
include/video/omap-panel-nokia-dsi.h | 8 +-
include/video/omap-panel-picodlp.h | 23 +
include/video/omapdss.h | 100 +-
include/video/sh_mobile_lcdc.h | 135 ++-
include/video/udlfb.h | 1 +
163 files changed, 12022 insertions(+), 7619 deletions(-)
create mode 100644 drivers/video/grvga.c
delete mode 100644 drivers/video/omap/lcd_2430sdp.c
delete mode 100644 drivers/video/omap/lcd_apollon.c
delete mode 100644 drivers/video/omap/lcd_h4.c
delete mode 100644 drivers/video/omap/lcd_ldp.c
delete mode 100644 drivers/video/omap/lcd_omap3beagle.c
delete mode 100644 drivers/video/omap/lcd_omap3evm.c
delete mode 100644 drivers/video/omap/lcd_overo.c
create mode 100644 drivers/video/omap2/displays/panel-dvi.c
create mode 100644 drivers/video/omap2/displays/panel-n8x0.c
create mode 100644 drivers/video/omap2/displays/panel-picodlp.c
create mode 100644 drivers/video/omap2/displays/panel-picodlp.h
rename drivers/video/omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} (79%)
create mode 100644 drivers/video/omap2/dss/ti_hdmi.h
create mode 100644 drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
rename drivers/video/omap2/dss/{hdmi.h => ti_hdmi_4xxx_ip.h} (54%)
delete mode 100644 drivers/video/sh_mobile_meram.h
create mode 100644 drivers/video/smscufx.c
create mode 100644 include/video/omap-panel-dvi.h
create mode 100644 include/video/omap-panel-n8x0.h
create mode 100644 include/video/omap-panel-picodlp.h
^ permalink raw reply
* Re: [RESENT][PATCH v2 0/2] fb: add early fb blank feature
From: Florian Tobias Schandinat @ 2011-10-30 11:24 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <003f01cc8280$7510c5c0$5f325140$%dae@samsung.com>
Hi Andrew,
can you take care of this patch series?
It seems like Richard does no longer handle LCD/backlight stuff (why is he
listed as maintainer?) and I really cannot say whether the patch to the LCD code
is correct and therefore I do not intend to carry such a patch without any Ack.
You can add an "Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>"
to the fb patch 2/2 (well actually I think the order should be swapped as 1 does
not compile without 2) but I ask you to handle it as well as it is useless
without the other patch.
Thanks,
Florian Tobias Schandinat
On 10/04/2011 10:29 AM, Inki Dae wrote:
> this patch adds early fb blank feature that a callback of lcd panel driver
> is called prior to specific fb driver's one. in case of MIPI-DSI based video
> mode LCD Panel, for lcd power off, the power off commands should be
> transferred to lcd panel with display and mipi-dsi controller enabled
> because the commands is set to lcd panel at vsync porch period. and in
> opposite case, the callback of fb driver should be called prior to lcd panel
> driver's one because of same issue. and also if fb_blank mode is changed to
> FB_BLANK_POWERDOWN then display controller would be off(clock disable) but
> lcd panel would be still on. at this time, you could see some issue like
> sparkling on lcd panel because video clock to be delivered to ldi module of
> lcd panel was disabled. this issue could occurs for all lcd panels.
>
> the callback order is as the following:
>
> at fb_blank function of fbmem.c
> -> fb_notifier_call_chain(FB_EARLY_EVENT_BLANK)
> -> lcd panel driver's early_set_power()
> -> info->fbops->fb_blank()
> -> spcefic fb driver's fb_blank()
> -> fb_notifier_call_chain(FB_EVENT_BLANK)
> -> lcd panel driver's set_power()
> -> fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK) if
> info->fops->fb_blank() was failed.
>
> fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK) would be called to revert the
> effects of previous FB_EARLY_EVENT_BLANK call. and note that if
> early_set_power() of lcd_ops is NULL then early fb blank callback would be
> ignored.
>
> this patch is based on git repository below:
> git://github.com/schandinat/linux-2.6.git
> branch: fbdev-next
> commit-id: 2b7a905dd0d24d14a1099653ba63b7113a82fc54
>
> Links to previous versions of the patchset:
> v1: < http://lkml.indiana.edu/hypermail/linux/kernel/1109.1/00413.html >
>
> Changelog v2:
> fb: add fb early blank event instead of early_blank_mode variable.
> fb notifier can know whether early blank mode is support or not
> checking if early_set_power callback is NULL or not.
>
> fb: add exception codes at fb_blank().
> the effects of previous FB_EARLY_EVENT_BLANK call should be reverted
> if info->fbops->fb_blank() was failed.
>
> fb: add code clean.
>
> Changelog RESEND:
> fb: fixed condition.
> this patch changes 'if (early_ret < 0)' to 'if (!early_ret)' of
> fb_blank function.
>
> these patch series are as the following:
> [RESEND][PATCH v2 0/2] fb: add early fb blank feature.
> introduce new early fb blank feature.
> [RESEND][PATCH v2 1/2] lcd: add callbacks for early fb event blank support.
> [RESEND][PATCH v2 2/2] fb: add events for early fb event support.
>
> Signed-off-by: Inki Dae <inki.dae@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Florian Tobias Schandinat @ 2011-10-30 15:53 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-fbdev, ralf
In-Reply-To: <20111020221928.0C2191DA27@solo.franken.de>
On 10/20/2011 10:19 PM, Thomas Bogendoerfer wrote:
> SGI IP22/IP28 machines have GIO busses for adding graphics and other
> extension cards. This patch adds support for GIO driver/device
> handling and converts the newport console driver to a GIO driver.
>
> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> ---
>
> Changes to last version:
> - use EXPORT_SYMBOL_GPL
> - ChallengeS has only 2 slots
> - use subsys_initcall for gio detection
>
> Florian, the whole patch should go through the MIPS tree, if it's ok for
> you.
No problem. I'm not even sure whether I'm responsible for it as it is not a
framebuffer but a console driver. Anyway I had a look at the console code so you
may add an
Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
if you like.
Best regards,
Florian Tobias Schandinat
> arch/mips/include/asm/gio_device.h | 56 +++++
> arch/mips/sgi-ip22/Makefile | 2 +-
> arch/mips/sgi-ip22/ip22-gio.c | 414 +++++++++++++++++++++++++++++++++++
> arch/mips/sgi-ip22/ip22-mc.c | 10 +-
> arch/mips/sgi-ip22/ip22-setup.c | 21 --
> drivers/video/console/newport_con.c | 61 ++++--
> 6 files changed, 518 insertions(+), 46 deletions(-)
>
> diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h
> new file mode 100644
> index 0000000..5437c84
> --- /dev/null
> +++ b/arch/mips/include/asm/gio_device.h
> @@ -0,0 +1,56 @@
> +#include <linux/device.h>
> +#include <linux/mod_devicetable.h>
> +
> +struct gio_device_id {
> + __u8 id;
> +};
> +
> +struct gio_device {
> + struct device dev;
> + struct resource resource;
> + unsigned int irq;
> + unsigned int slotno;
> +
> + const char *name;
> + struct gio_device_id id;
> + unsigned id32:1;
> + unsigned gio64:1;
> +};
> +#define to_gio_device(d) container_of(d, struct gio_device, dev)
> +
> +struct gio_driver {
> + const char *name;
> + struct module *owner;
> + const struct gio_device_id *id_table;
> +
> + int (*probe)(struct gio_device *, const struct gio_device_id *);
> + void (*remove)(struct gio_device *);
> + int (*suspend)(struct gio_device *, pm_message_t);
> + int (*resume)(struct gio_device *);
> + void (*shutdown)(struct gio_device *);
> +
> + struct device_driver driver;
> +};
> +#define to_gio_driver(drv) container_of(drv, struct gio_driver, driver)
> +
> +extern const struct gio_device_id *gio_match_device(const struct gio_device_id *,
> + const struct gio_device *);
> +extern struct gio_device *gio_dev_get(struct gio_device *);
> +extern void gio_dev_put(struct gio_device *);
> +
> +extern int gio_device_register(struct gio_device *);
> +extern void gio_device_unregister(struct gio_device *);
> +extern void gio_release_dev(struct device *);
> +
> +static inline void gio_device_free(struct gio_device *dev)
> +{
> + gio_release_dev(&dev->dev);
> +}
> +
> +extern int gio_register_driver(struct gio_driver *);
> +extern void gio_unregister_driver(struct gio_driver *);
> +
> +#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev)
> +#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data))
> +
> +extern void gio_set_master(struct gio_device *);
> diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
> index cc53849..411cda9 100644
> --- a/arch/mips/sgi-ip22/Makefile
> +++ b/arch/mips/sgi-ip22/Makefile
> @@ -4,7 +4,7 @@
> #
>
> obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \
> - ip22-platform.o ip22-reset.o ip22-setup.o
> + ip22-platform.o ip22-reset.o ip22-setup.o ip22-gio.o
>
> obj-$(CONFIG_SGI_IP22) += ip22-berr.o
> obj-$(CONFIG_SGI_IP28) += ip28-berr.o
> diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
> new file mode 100644
> index 0000000..d841529
> --- /dev/null
> +++ b/arch/mips/sgi-ip22/ip22-gio.c
> @@ -0,0 +1,414 @@
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +
> +#include <asm/addrspace.h>
> +#include <asm/paccess.h>
> +#include <asm/gio_device.h>
> +#include <asm/sgi/gio.h>
> +#include <asm/sgi/hpc3.h>
> +#include <asm/sgi/mc.h>
> +#include <asm/sgi/ip22.h>
> +
> +static struct bus_type gio_bus;
> +
> +static struct {
> + const char *name;
> + __u8 id;
> +} gio_name_table[] = {
> + { .name = "SGI Impact", .id = 0x10 },
> + { .name = "Phobos G160", .id = 0x35 },
> + /* fake IDs */
> + { .name = "SGI Newport", .id = 0x7e },
> + { .name = "SGI GR2/GR3", .id = 0x7f },
> +};
> +
> +/**
> + * gio_match_device - Tell if an of_device structure has a matching
> + * gio_match structure
> + * @ids: array of of device match structures to search in
> + * @dev: the of device structure to match against
> + *
> + * Used by a driver to check whether an of_device present in the
> + * system is in its list of supported devices.
> + */
> +const struct gio_device_id *gio_match_device(const struct gio_device_id *match,
> + const struct gio_device *dev)
> +{
> + const struct gio_device_id *ids;
> +
> + for (ids = match; ids->id != 0xff; ids++)
> + if (ids->id = dev->id.id)
> + return ids;
> +
> + return NULL;
> +}
> +EXPORT_SYMBOL_GPL(gio_match_device);
> +
> +struct gio_device *gio_dev_get(struct gio_device *dev)
> +{
> + struct device *tmp;
> +
> + if (!dev)
> + return NULL;
> + tmp = get_device(&dev->dev);
> + if (tmp)
> + return to_gio_device(tmp);
> + else
> + return NULL;
> +}
> +EXPORT_SYMBOL_GPL(gio_dev_get);
> +
> +void gio_dev_put(struct gio_device *dev)
> +{
> + if (dev)
> + put_device(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(gio_dev_put);
> +
> +static ssize_t dev_show_name(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct gio_device *giodev;
> +
> + giodev = to_gio_device(dev);
> + return sprintf(buf, "%s", giodev->name);
> +}
> +
> +static DEVICE_ATTR(name, S_IRUGO, dev_show_name, NULL);
> +
> +static ssize_t dev_show_id(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct gio_device *giodev;
> +
> + giodev = to_gio_device(dev);
> + return sprintf(buf, "%x", giodev->id.id);
> +}
> +
> +static DEVICE_ATTR(id, S_IRUGO, dev_show_id, NULL);
> +
> +/**
> + * gio_release_dev - free an gio device structure when all users of it are finished.
> + * @dev: device that's been disconnected
> + *
> + * Will be called only by the device core when all users of this gio device are
> + * done.
> + */
> +void gio_release_dev(struct device *dev)
> +{
> + struct gio_device *giodev;
> +
> + giodev = to_gio_device(dev);
> + kfree(giodev);
> +}
> +EXPORT_SYMBOL_GPL(gio_release_dev);
> +
> +int gio_device_register(struct gio_device *giodev)
> +{
> + int rc;
> +
> + giodev->dev.bus = &gio_bus;
> + rc = device_register(&giodev->dev);
> + if (rc)
> + return rc;
> +
> + rc = device_create_file(&giodev->dev, &dev_attr_name);
> + if (rc)
> + goto err;
> + rc = device_create_file(&giodev->dev, &dev_attr_id);
> + if (rc)
> + goto err;
> +
> + return 0;
> +
> +err:
> + device_unregister(&giodev->dev);
> + return rc;
> +}
> +EXPORT_SYMBOL_GPL(gio_device_register);
> +
> +void gio_device_unregister(struct gio_device *giodev)
> +{
> + device_remove_file(&giodev->dev, &dev_attr_id);
> + device_remove_file(&giodev->dev, &dev_attr_name);
> + device_unregister(&giodev->dev);
> +}
> +EXPORT_SYMBOL_GPL(gio_device_unregister);
> +
> +static int gio_bus_match(struct device *dev, struct device_driver *drv)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *gio_drv = to_gio_driver(drv);
> +
> + return gio_match_device(gio_drv->id_table, gio_dev) != NULL;
> +}
> +
> +static int gio_device_probe(struct device *dev)
> +{
> + int error = -ENODEV;
> + struct gio_driver *drv;
> + struct gio_device *gio_dev;
> + const struct gio_device_id *match;
> +
> + drv = to_gio_driver(dev->driver);
> + gio_dev = to_gio_device(dev);
> +
> + if (!drv->probe)
> + return error;
> +
> + gio_dev_get(gio_dev);
> +
> + match = gio_match_device(drv->id_table, gio_dev);
> + if (match)
> + error = drv->probe(gio_dev, match);
> + if (error)
> + gio_dev_put(gio_dev);
> +
> + return error;
> +}
> +
> +static int gio_device_remove(struct device *dev)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> +
> + if (dev->driver && drv->remove)
> + drv->remove(gio_dev);
> + return 0;
> +}
> +
> +static int gio_device_suspend(struct device *dev, pm_message_t state)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> + int error = 0;
> +
> + if (dev->driver && drv->suspend)
> + error = drv->suspend(gio_dev, state);
> + return error;
> +}
> +
> +static int gio_device_resume(struct device *dev)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> + int error = 0;
> +
> + if (dev->driver && drv->resume)
> + error = drv->resume(gio_dev);
> + return error;
> +}
> +
> +static void gio_device_shutdown(struct device *dev)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> +
> + if (dev->driver && drv->shutdown)
> + drv->shutdown(gio_dev);
> +}
> +
> +int gio_register_driver(struct gio_driver *drv)
> +{
> + /* initialize common driver fields */
> + if (!drv->driver.name)
> + drv->driver.name = drv->name;
> + if (!drv->driver.owner)
> + drv->driver.owner = drv->owner;
> + drv->driver.bus = &gio_bus;
> +
> + /* register with core */
> + return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(gio_register_driver);
> +
> +void gio_unregister_driver(struct gio_driver *drv)
> +{
> + driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(gio_unregister_driver);
> +
> +void gio_set_master(struct gio_device *dev)
> +{
> + u32 tmp = sgimc->giopar;
> +
> + switch (dev->slotno) {
> + case 0:
> + tmp |= SGIMC_GIOPAR_MASTERGFX;
> + break;
> + case 1:
> + tmp |= SGIMC_GIOPAR_MASTEREXP0;
> + break;
> + case 2:
> + tmp |= SGIMC_GIOPAR_MASTEREXP1;
> + break;
> + }
> + sgimc->giopar = tmp;
> +}
> +EXPORT_SYMBOL_GPL(gio_set_master);
> +
> +void ip22_gio_set_64bit(int slotno)
> +{
> + u32 tmp = sgimc->giopar;
> +
> + switch (slotno) {
> + case 0:
> + tmp |= SGIMC_GIOPAR_GFX64;
> + break;
> + case 1:
> + tmp |= SGIMC_GIOPAR_EXP064;
> + break;
> + case 2:
> + tmp |= SGIMC_GIOPAR_EXP164;
> + break;
> + }
> + sgimc->giopar = tmp;
> +}
> +
> +static int ip22_gio_id(unsigned long addr, u32 *res)
> +{
> + u8 tmp8;
> + u8 tmp16;
> + u32 tmp32;
> + u8 *ptr8;
> + u16 *ptr16;
> + u32 *ptr32;
> +
> + ptr32 = (void *)CKSEG1ADDR(addr);
> + if (!get_dbe(tmp32, ptr32)) {
> + /*
> + * We got no DBE, but this doesn't mean anything.
> + * If GIO is pipelined (which can't be disabled
> + * for GFX slot) we don't get a DBE, but we see
> + * the transfer size as data. So we do an 8bit
> + * and a 16bit access and check whether the common
> + * data matches
> + */
> + ptr8 = (void *)CKSEG1ADDR(addr + 3);
> + get_dbe(tmp8, ptr8);
> + ptr16 = (void *)CKSEG1ADDR(addr + 2);
> + get_dbe(tmp16, ptr16);
> + if (tmp8 = (tmp16 & 0xff) &&
> + tmp8 = (tmp32 & 0xff) &&
> + tmp16 = (tmp32 & 0xffff)) {
> + *res = tmp32;
> + return 1;
> + }
> + }
> + return 0; /* nothing here */
> +}
> +
> +#define HQ2_MYSTERY_OFFS 0x6A07C
> +#define NEWPORT_USTATUS_OFFS 0xF133C
> +
> +static int ip22_is_gr2(unsigned long addr)
> +{
> + u32 tmp;
> + u32 *ptr;
> +
> + /* HQ2 only allows 32bit accesses */
> + ptr = (void *)CKSEG1ADDR(addr + HQ2_MYSTERY_OFFS);
> + if (!get_dbe(tmp, ptr)) {
> + if (tmp = 0xdeadbeef)
> + return 1;
> + }
> + return 0;
> +}
> +
> +
> +static void ip22_check_gio(int slotno, unsigned long addr)
> +{
> + const char *name = "Unknown";
> + struct gio_device *gio_dev;
> + u32 tmp;
> + __u8 id;
> + int i;
> +
> + /* first look for GR2/GR3 by checking mystery register */
> + if (ip22_is_gr2(addr))
> + tmp = 0x7f;
> + else {
> + if (!ip22_gio_id(addr, &tmp)) {
> + /*
> + * no GIO signature at start address of slot, but
> + * Newport doesn't have one, so let's check usea
> + * status register
> + */
> + if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp))
> + tmp = 0x7e;
> + else
> + tmp = 0;
> + }
> + }
> + if (tmp) {
> + id = GIO_ID(tmp);
> + if (tmp & GIO_32BIT_ID) {
> + if (tmp & GIO_64BIT_IFACE)
> + ip22_gio_set_64bit(slotno);
> + }
> + for (i = 0; i < ARRAY_SIZE(gio_name_table); i++) {
> + if (id = gio_name_table[i].id) {
> + name = gio_name_table[i].name;
> + break;
> + }
> + }
> + printk(KERN_INFO "GIO: slot %d : %s (id %x)\n",
> + slotno, name, id);
> + gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL);
> + gio_dev->name = name;
> + gio_dev->slotno = slotno;
> + gio_dev->id.id = id;
> + gio_dev->resource.start = addr;
> + gio_dev->resource.end = addr + 0x3fffff;
> + gio_dev->resource.flags = IORESOURCE_MEM;
> + dev_set_name(&gio_dev->dev, "gio%d", slotno);
> + gio_device_register(gio_dev);
> + } else
> + printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
> +}
> +
> +static struct bus_type gio_bus = {
> + .name = "gio",
> + .match = gio_bus_match,
> + .probe = gio_device_probe,
> + .remove = gio_device_remove,
> + .suspend = gio_device_suspend,
> + .resume = gio_device_resume,
> + .shutdown = gio_device_shutdown,
> +};
> +
> +static struct resource gio_bus_resource = {
> + .start = GIO_SLOT_GFX_BASE,
> + .end = GIO_SLOT_GFX_BASE + 0x9fffff,
> + .name = "GIO Bus",
> + .flags = IORESOURCE_MEM,
> +};
> +
> +int __init ip22_gio_init(void)
> +{
> + unsigned int pbdma __maybe_unused;
> + int ret;
> +
> + ret = bus_register(&gio_bus);
> + if (!ret) {
> + request_resource(&iomem_resource, &gio_bus_resource);
> + printk(KERN_INFO "GIO: Probing bus...\n");
> +
> + if (ip22_is_fullhouse() ||
> + !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) {
> + /* Indigo2 and ChallengeS */
> + ip22_check_gio(0, GIO_SLOT_GFX_BASE);
> + ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
> + } else {
> + /* Indy */
> + ip22_check_gio(0, GIO_SLOT_GFX_BASE);
> + ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
> + ip22_check_gio(2, GIO_SLOT_EXP1_BASE);
> + }
> + }
> + return ret;
> +}
> +
> +subsys_initcall(ip22_gio_init);
> +
> diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c
> index d22262e..75ada8a 100644
> --- a/arch/mips/sgi-ip22/ip22-mc.c
> +++ b/arch/mips/sgi-ip22/ip22-mc.c
> @@ -139,11 +139,11 @@ void __init sgimc_init(void)
> * zero.
> */
> /* don't touch parity settings for IP28 */
> -#ifndef CONFIG_SGI_IP28
> tmp = sgimc->cpuctrl0;
> - tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
> - SGIMC_CCTRL0_R4KNOCHKPARR);
> +#ifndef CONFIG_SGI_IP28
> + tmp |= SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM;
> #endif
> + tmp |= SGIMC_CCTRL0_R4KNOCHKPARR;
> sgimc->cpuctrl0 = tmp;
>
> /* Step 3: Setup the MC write buffer depth, this is controlled
> @@ -178,7 +178,8 @@ void __init sgimc_init(void)
> */
>
> /* First the basic invariants across all GIO64 implementations. */
> - tmp = SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
> + tmp = sgimc->giopar & SGIMC_GIOPAR_GFX64; /* keep gfx 64bit settings */
> + tmp |= SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
> tmp |= SGIMC_GIOPAR_ONEBUS; /* Only one physical GIO bus exists */
>
> if (ip22_is_fullhouse()) {
> @@ -193,7 +194,6 @@ void __init sgimc_init(void)
> tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp[01] pipelined */
> tmp |= SGIMC_GIOPAR_PLINEEXP1;
> tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA masters */
> - tmp |= SGIMC_GIOPAR_GFX64; /* GFX at 64 bits */
> }
> } else {
> /* Guiness specific settings. */
> diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
> index 5e66213..c7bdfe4 100644
> --- a/arch/mips/sgi-ip22/ip22-setup.c
> +++ b/arch/mips/sgi-ip22/ip22-setup.c
> @@ -26,9 +26,6 @@
> #include <asm/sgi/hpc3.h>
> #include <asm/sgi/ip22.h>
>
> -unsigned long sgi_gfxaddr;
> -EXPORT_SYMBOL_GPL(sgi_gfxaddr);
> -
> extern void ip22_be_init(void) __init;
>
> void __init plat_mem_setup(void)
> @@ -78,22 +75,4 @@ void __init plat_mem_setup(void)
> prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
> add_preferred_console("arc", 0, NULL);
> }
> -
> -#if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
> - {
> - ULONG *gfxinfo;
> - ULONG * (*__vec)(void) = (void *) (long)
> - *((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20));
> -
> - gfxinfo = __vec();
> - sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000
> - && gfxinfo[1] <= 0xc0000000)
> - ? gfxinfo[1] - 0xa0000000 : 0);
> -
> - /* newport addresses? */
> - if (sgi_gfxaddr = 0x1f0f0000 || sgi_gfxaddr = 0x1f4f0000) {
> - conswitchp = &newport_con;
> - }
> - }
> -#endif
> }
> diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
> index 93317b5..628b7ec 100644
> --- a/drivers/video/console/newport_con.c
> +++ b/drivers/video/console/newport_con.c
> @@ -25,14 +25,13 @@
> #include <asm/system.h>
> #include <asm/page.h>
> #include <asm/pgtable.h>
> +#include <asm/gio_device.h>
> +
> #include <video/newport.h>
>
> #include <linux/linux_logo.h>
> #include <linux/font.h>
>
> -
> -extern unsigned long sgi_gfxaddr;
> -
> #define FONT_DATA ((unsigned char *)font_vga_8x16.data)
>
> /* borrowed from fbcon.c */
> @@ -304,12 +303,6 @@ static const char *newport_startup(void)
> {
> int i;
>
> - if (!sgi_gfxaddr)
> - return NULL;
> -
> - if (!npregs)
> - npregs = (struct newport_regs *)/* ioremap cannot fail */
> - ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
> npregs->cset.config = NPORT_CFG_GD0;
>
> if (newport_wait(npregs))
> @@ -743,26 +736,56 @@ const struct consw newport_con = {
> .con_save_screen = DUMMY
> };
>
> -#ifdef MODULE
> -static int __init newport_console_init(void)
> +static int newport_probe(struct gio_device *dev,
> + const struct gio_device_id *id)
> {
> - if (!sgi_gfxaddr)
> - return 0;
> + unsigned long newport_addr;
>
> - if (!npregs)
> - npregs = (struct newport_regs *)/* ioremap cannot fail */
> - ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
> + if (!dev->resource.start)
> + return -EINVAL;
> +
> + if (npregs)
> + return -EBUSY; /* we only support one Newport as console */
> +
> + newport_addr = dev->resource.start + 0xF0000;
> + if (!request_mem_region(newport_addr, 0x10000, "Newport"))
> + return -ENODEV;
> +
> + npregs = (struct newport_regs *)/* ioremap cannot fail */
> + ioremap(newport_addr, sizeof(struct newport_regs));
>
> return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
> }
> -module_init(newport_console_init);
>
> -static void __exit newport_console_exit(void)
> +static void newport_remove(struct gio_device *dev)
> {
> give_up_console(&newport_con);
> iounmap((void *)npregs);
> }
> +
> +static struct gio_device_id newport_ids[] = {
> + { .id = 0x7e },
> + { .id = 0xff }
> +};
> +
> +static struct gio_driver newport_driver = {
> + .name = "newport",
> + .id_table = newport_ids,
> + .probe = newport_probe,
> + .remove = newport_remove,
> +};
> +
> +int __init newport_console_init(void)
> +{
> + return gio_register_driver(&newport_driver);
> +}
> +
> +void __exit newport_console_exit(void)
> +{
> + gio_unregister_driver(&newport_driver);
> +}
> +
> +module_init(newport_console_init);
> module_exit(newport_console_exit);
> -#endif
>
> MODULE_LICENSE("GPL");
>
^ permalink raw reply
* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Joshua Kinard @ 2011-10-30 20:43 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-fbdev, ralf, FlorianSchandinat
In-Reply-To: <20111020221928.0C2191DA27@solo.franken.de>
On 10/20/2011 18:19, Thomas Bogendoerfer wrote:
> SGI IP22/IP28 machines have GIO busses for adding graphics and other
> extension cards. This patch adds support for GIO driver/device
> handling and converts the newport console driver to a GIO driver.
>
> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Does this handle any glue logic for add-on NIC cards found for Indy and I2?
I have a G130 Phobus and a rare ThunderLAN card in my Indy. The Phobus has
an Altera GIO/PCI glue chip. Not sure about the ThunderLAN. Both have
normal driver support in the kernel (Phobus is just a Tulip chip).
--
Joshua Kinard
Gentoo/MIPS
kumba@gentoo.org
4096R/D25D95E3 2011-03-28
"The past tempts us, the present confuses us, the future frightens us. And
our lives slip away, moment by moment, lost in that vast, terrible in-between."
--Emperor Turhan, Centauri Republic
^ permalink raw reply
* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Thomas Bogendoerfer @ 2011-10-30 22:34 UTC (permalink / raw)
To: Joshua Kinard; +Cc: linux-mips, linux-fbdev, ralf, FlorianSchandinat
In-Reply-To: <4EADB701.9040506@gentoo.org>
On Sun, Oct 30, 2011 at 04:43:45PM -0400, Joshua Kinard wrote:
> Does this handle any glue logic for add-on NIC cards found for Indy and I2?
no, but it will make live a lot easier, because address and interrupts don't
need to be probed by the driver. Right now interrupts are on my todo, since
there is some weirdness between guiness and fullhouse boxes...
> I have a G130 Phobus and a rare ThunderLAN card in my Indy. The Phobus has
> an Altera GIO/PCI glue chip. Not sure about the ThunderLAN. Both have
> normal driver support in the kernel (Phobus is just a Tulip chip).
it still needs something to setup the PCI bus on the card and issue
the probing. The problem with the Tulip Phobos cards is, that they
messed up the endianess, so that none of the Linux Tulip drivers will
work out of the box...
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply
* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Joshua Kinard @ 2011-10-31 8:04 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-fbdev, ralf, FlorianSchandinat
In-Reply-To: <20111030223418.GA16346@alpha.franken.de>
On 10/30/2011 18:34, Thomas Bogendoerfer wrote:
>
> no, but it will make live a lot easier, because address and interrupts don't
> need to be probed by the driver. Right now interrupts are on my todo, since
> there is some weirdness between guiness and fullhouse boxes...
It wouldn't be an SGI machine if it didn't implement something weird or just
plain backwards...
> it still needs something to setup the PCI bus on the card and issue
> the probing. The problem with the Tulip Phobos cards is, that they
> messed up the endianess, so that none of the Linux Tulip drivers will
> work out of the box...
A.k.a., Tulip (and possibly ThunderLAN) assume little-endian, when we're
talking big-endian archs here. Interesting. Simple fix, as in defining a
few driver structures with little- and big-endian versions (if they're doing
something like packing bits or using bitfields)? Or is it more complex than
that?
--
Joshua Kinard
Gentoo/MIPS
kumba@gentoo.org
4096R/D25D95E3 2011-03-28
"The past tempts us, the present confuses us, the future frightens us. And
our lives slip away, moment by moment, lost in that vast, terrible in-between."
--Emperor Turhan, Centauri Republic
^ permalink raw reply
* Re: Proposal for a low-level Linux display framework
From: Jesse Barnes @ 2011-10-31 20:24 UTC (permalink / raw)
To: Alan Cox
Cc: Dave Airlie, linux-fbdev, linaro-dev, Florian Tobias Schandinat,
linux-kernel, dri-devel, Archit Taneja, Rob Clark
In-Reply-To: <20110917212529.6b452bf2@lxorguk.ukuu.org.uk>
[-- Attachment #1: Type: text/plain, Size: 3068 bytes --]
On Sat, 17 Sep 2011 21:25:29 +0100
Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> > Just tell the X driver to not use acceleration, and it you won't get
> > any acceleration used, then you get complete stability. If a driver
> > writer wants to turn off all accel in the kernel driver, it can, its
>
> In fact one thing we actually need really is a "dumb" KMS X server to
> replace the fbdev X server that unaccel stuff depends upon and which
> can't do proper mode handling, multi-head or resizing as a result. A dumb
> fb generic request for a back to front copy might also be useful for
> shadowfb, or at least indicators so you know what the cache behaviour is
> so the X server can pick the right policy.
>
> > We've fixed this in KMS, we don't pass direct mappings to userspace
> > that we can't tear down and refault. We only provide objects via
> > handles. The only place its a problem is where we expose fbdev legacy
> > emulation, since we have to fix the pages.
>
> Which is doable. Horrible but doable. The usb framebuffer code has to
> play games like this with the virtual framebuffer in order to track
> changes by faulting.
>
> There are still some architectural screwups however. DRM continues the
> fbdev worldview that outputs, memory and accelerators are tied together
> in lumps we call video cards. That isn't really true for all cases and
> with capture/overlay it gets even less true.
Sorry for re-opening this ancient thread; I'm catching up from the past
2 months of travel & misc.
I definitely agree about the PC card centric architecture of DRM KMS
(and before it, X). But we have a path out of it now, and lots of
interest from vendors and developers, so I don't think it's an
insurmountable problem by any means.
I definitely understand Florian's worries about DRM vs fb. If nothing
else, there's certainly a perception that fb is simpler and easier to
get right. But really, as others have pointed out, it's solving a
different set of problems than the DRM layer. The latter is actually
trying to expose the features of contemporary hardware in a way that's
as portable as possible. That portability comes at a cost though: the
APIs we add need to get lots of review, and there's no doubt we'll need
to add more as newer, weirder hardware comes along.
Really, I see no reason why fb and DRM can't continue to live side by
side. If a vendor really only needs the features provided by the fb
layer, they're free to stick with a simple fb driver. However, I
expect most vendors making phones, tablets, notebooks, etc will need
and want an architecture that looks a lot like the DRM layer, with
authentication for rendering clients, an command submission ioctl for
acceleration, and memory management, so I expect most of the driver
growth to be in DRM in the near future.
And I totally agree with Dave about having a kmscon. I really wish
someone would implement it so I could have my VTs spinning on a cube.
--
Jesse Barnes, Intel Open Source Technology Center
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Thomas Bogendoerfer @ 2011-11-01 10:00 UTC (permalink / raw)
To: Joshua Kinard; +Cc: linux-mips, linux-fbdev, ralf, FlorianSchandinat
In-Reply-To: <4EAE5681.2090103@gentoo.org>
On Mon, Oct 31, 2011 at 04:04:17AM -0400, Joshua Kinard wrote:
> A.k.a., Tulip (and possibly ThunderLAN) assume little-endian, when we're
> talking big-endian archs here. Interesting. Simple fix, as in defining a
> few driver structures with little- and big-endian versions (if they're doing
> something like packing bits or using bitfields)? Or is it more complex than
> that?
iirc, the PCI bridge on the cards do 32bit swaps (address invariant) so
tulip chips need to run in big endian mode, which in turn makes descriptors
also big endian. But none of the tulip driver supports big endian descriptors.
That's fixable of course.
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply
* [PATCH 09/18] MIPS: Alchemy: move au1200fb global functions to platform data
From: Manuel Lauss @ 2011-11-01 19:03 UTC (permalink / raw)
To: Linux-MIPS, Ralf Baechle; +Cc: Manuel Lauss, linux-fbdev
In-Reply-To: <1320174224-27305-1-git-send-email-manuel.lauss@googlemail.com>
au1200fb calls 3 functions which have to be defined in board code.
Fix this ugliness with the introduction of platform_data.
Cc: linux-fbdev@vger.kernel.org
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
---
I'd like this to go in via the MIPS tree since patches depend on it.
arch/mips/alchemy/devboards/db1200.c | 51 +++---
arch/mips/alchemy/devboards/db1300.c | 52 +++---
arch/mips/alchemy/devboards/pb1200.c | 55 ++++---
arch/mips/include/asm/mach-au1x00/au1200fb.h | 14 ++
drivers/video/au1200fb.c | 241 ++++++++++++--------------
5 files changed, 213 insertions(+), 200 deletions(-)
create mode 100644 arch/mips/include/asm/mach-au1x00/au1200fb.h
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index 43f5f1b..e2cc5f9 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -37,6 +37,7 @@
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1100_mmc.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1200fb.h>
#include <asm/mach-au1x00/au1550_spi.h>
#include <asm/mach-db1x00/bcsr.h>
#include <asm/mach-db1x00/db1200.h>
@@ -422,6 +423,33 @@ static struct platform_device db1200_mmc0_dev = {
/**********************************************************************/
+static int db1200fb_panel_index(void)
+{
+ return (bcsr_read(BCSR_SWITCHES) >> 8) & 0x0f;
+}
+
+static int db1200fb_panel_init(void)
+{
+ /* Apply power */
+ bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
+ BCSR_BOARD_LCDBL);
+ return 0;
+}
+
+static int db1200fb_panel_shutdown(void)
+{
+ /* Remove power */
+ bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
+ BCSR_BOARD_LCDBL, 0);
+ return 0;
+}
+
+static struct au1200fb_platdata db1200fb_pd = {
+ .panel_index = db1200fb_panel_index,
+ .panel_init = db1200fb_panel_init,
+ .panel_shutdown = db1200fb_panel_shutdown,
+};
+
static struct resource au1200_lcd_res[] = {
[0] = {
.start = AU1200_LCD_PHYS_ADDR,
@@ -443,6 +471,7 @@ static struct platform_device au1200_lcd_dev = {
.dev = {
.dma_mask = &au1200_lcd_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &db1200fb_pd,
},
.num_resources = ARRAY_SIZE(au1200_lcd_res),
.resource = au1200_lcd_res,
@@ -681,25 +710,3 @@ static int __init db1200_dev_init(void)
return platform_add_devices(db1200_devs, ARRAY_SIZE(db1200_devs));
}
device_initcall(db1200_dev_init);
-
-/* au1200fb calls these: STERBT EINEN TRAGISCHEN TOD!!! */
-int board_au1200fb_panel(void)
-{
- return (bcsr_read(BCSR_SWITCHES) >> 8) & 0x0f;
-}
-
-int board_au1200fb_panel_init(void)
-{
- /* Apply power */
- bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
- BCSR_BOARD_LCDBL);
- return 0;
-}
-
-int board_au1200fb_panel_shutdown(void)
-{
- /* Remove power */
- bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
- BCSR_BOARD_LCDBL, 0);
- return 0;
-}
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index bf0d1c4..d1a7344 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -22,6 +22,7 @@
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/mach-au1x00/au1200fb.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
#include <asm/mach-db1x00/db1300.h>
@@ -635,6 +636,33 @@ static struct platform_device db1300_sndi2s_dev = {
/**********************************************************************/
+static int db1300fb_panel_index(void)
+{
+ return 9; /* DB1300_800x480 */
+}
+
+static int db1300fb_panel_init(void)
+{
+ /* Apply power (Vee/Vdd logic is inverted on Panel DB1300_800x480) */
+ bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD,
+ BCSR_BOARD_LCDBL);
+ return 0;
+}
+
+static int db1300fb_panel_shutdown(void)
+{
+ /* Remove power (Vee/Vdd logic is inverted on Panel DB1300_800x480) */
+ bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDBL,
+ BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD);
+ return 0;
+}
+
+static struct au1200fb_platdata db1300fb_pd = {
+ .panel_index = db1300fb_panel_index,
+ .panel_init = db1300fb_panel_init,
+ .panel_shutdown = db1300fb_panel_shutdown,
+};
+
static struct resource au1300_lcd_res[] = {
[0] = {
.start = AU1200_LCD_PHYS_ADDR,
@@ -656,6 +684,7 @@ static struct platform_device db1300_lcd_dev = {
.dev = {
.dma_mask = &au1300_lcd_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &db1300fb_pd,
},
.num_resources = ARRAY_SIZE(au1300_lcd_res),
.resource = au1300_lcd_res,
@@ -761,26 +790,3 @@ void __init board_setup(void)
alchemy_uart_enable(AU1300_UART1_PHYS_ADDR);
alchemy_uart_enable(AU1300_UART3_PHYS_ADDR);
}
-
-
-/* au1200fb calls these: STERBT EINEN TRAGISCHEN TOD!!! */
-int board_au1200fb_panel(void)
-{
- return 9; /* DB1300_800x480 */
-}
-
-int board_au1200fb_panel_init(void)
-{
- /* Apply power (Vee/Vdd logic is inverted on Panel DB1300_800x480) */
- bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD,
- BCSR_BOARD_LCDBL);
- return 0;
-}
-
-int board_au1200fb_panel_shutdown(void)
-{
- /* Remove power (Vee/Vdd logic is inverted on Panel DB1300_800x480) */
- bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDBL,
- BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD);
- return 0;
-}
diff --git a/arch/mips/alchemy/devboards/pb1200.c b/arch/mips/alchemy/devboards/pb1200.c
index a1b6497..a2676c9 100644
--- a/arch/mips/alchemy/devboards/pb1200.c
+++ b/arch/mips/alchemy/devboards/pb1200.c
@@ -26,6 +26,7 @@
#include <linux/smc91x.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1100_mmc.h>
+#include <asm/mach-au1x00/au1200fb.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-db1x00/bcsr.h>
#include <asm/mach-pb1x00/pb1200.h>
@@ -351,6 +352,33 @@ static struct platform_device pb1200_i2c_dev = {
.resource = au1200_psc0_res,
};
+static int pb1200fb_panel_index(void)
+{
+ return (bcsr_read(BCSR_SWITCHES) >> 8) & 0x0f;
+}
+
+static int pb1200fb_panel_init(void)
+{
+ /* Apply power */
+ bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
+ BCSR_BOARD_LCDBL);
+ return 0;
+}
+
+static int pb1200fb_panel_shutdown(void)
+{
+ /* Remove power */
+ bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
+ BCSR_BOARD_LCDBL, 0);
+ return 0;
+}
+
+static struct au1200fb_platdata pb1200fb_pd = {
+ .panel_index = pb1200fb_panel_index,
+ .panel_init = pb1200fb_panel_init,
+ .panel_shutdown = pb1200fb_panel_shutdown,
+};
+
static struct resource au1200_lcd_res[] = {
[0] = {
.start = AU1200_LCD_PHYS_ADDR,
@@ -366,12 +394,13 @@ static struct resource au1200_lcd_res[] = {
static u64 au1200_lcd_dmamask = DMA_BIT_MASK(32);
-static struct platform_device au1200_lcd_dev = {
+static struct platform_device pb1200_lcd_dev = {
.name = "au1200-lcd",
.id = 0,
.dev = {
.dma_mask = &au1200_lcd_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &pb1200fb_pd,
},
.num_resources = ARRAY_SIZE(au1200_lcd_res),
.resource = au1200_lcd_res,
@@ -383,7 +412,7 @@ static struct platform_device *board_platform_devices[] __initdata = {
&pb1200_i2c_dev,
&pb1200_mmc0_dev,
&pb1200_mmc1_dev,
- &au1200_lcd_dev,
+ &pb1200_lcd_dev,
};
static int __init board_register_devices(void)
@@ -440,25 +469,3 @@ static int __init board_register_devices(void)
ARRAY_SIZE(board_platform_devices));
}
device_initcall(board_register_devices);
-
-
-int board_au1200fb_panel(void)
-{
- return (bcsr_read(BCSR_SWITCHES) >> 8) & 0x0f;
-}
-
-int board_au1200fb_panel_init(void)
-{
- /* Apply power */
- bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
- BCSR_BOARD_LCDBL);
- return 0;
-}
-
-int board_au1200fb_panel_shutdown(void)
-{
- /* Remove power */
- bcsr_mod(BCSR_BOARD, BCSR_BOARD_LCDVEE | BCSR_BOARD_LCDVDD |
- BCSR_BOARD_LCDBL, 0);
- return 0;
-}
diff --git a/arch/mips/include/asm/mach-au1x00/au1200fb.h b/arch/mips/include/asm/mach-au1x00/au1200fb.h
new file mode 100644
index 0000000..b3c87cc
--- /dev/null
+++ b/arch/mips/include/asm/mach-au1x00/au1200fb.h
@@ -0,0 +1,14 @@
+/*
+ * platform data for au1200fb driver.
+ */
+
+#ifndef _AU1200FB_PLAT_H_
+#define _AU1200FB_PLAT_H_
+
+struct au1200fb_platdata {
+ int (*panel_index)(void);
+ int (*panel_init)(void);
+ int (*panel_shutdown)(void);
+};
+
+#endif
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 6c4342f..04e4479 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -44,6 +44,7 @@
#include <linux/slab.h>
#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1200fb.h> /* platform_data */
#include "au1200fb.h"
#define DRIVER_NAME "au1200fb"
@@ -143,6 +144,7 @@ struct au1200_lcd_iodata_t {
/* Private, per-framebuffer management information (independent of the panel itself) */
struct au1200fb_device {
struct fb_info *fb_info; /* FB driver info record */
+ struct au1200fb_platdata *pd;
int plane;
unsigned char* fb_mem; /* FrameBuffer memory map */
@@ -201,9 +203,6 @@ struct window_settings {
#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
#endif
-extern int board_au1200fb_panel_init (void);
-extern int board_au1200fb_panel_shutdown (void);
-
/*
* Default window configurations
*/
@@ -334,8 +333,6 @@ struct panel_settings
uint32 mode_toyclksrc;
uint32 mode_backlight;
uint32 mode_auxpll;
- int (*device_init)(void);
- int (*device_shutdown)(void);
#define Xres min_xres
#define Yres min_yres
u32 min_xres; /* Minimum horizontal resolution */
@@ -385,8 +382,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
320, 320,
240, 240,
},
@@ -415,8 +410,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
640, 480,
640, 480,
},
@@ -445,8 +438,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
800, 800,
600, 600,
},
@@ -475,8 +466,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 6, /* 72MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
1024, 1024,
768, 768,
},
@@ -505,8 +494,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 10, /* 120MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
1280, 1280,
1024, 1024,
},
@@ -535,8 +522,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
1024, 1024,
768, 768,
},
@@ -568,8 +553,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
640, 480,
640, 480,
},
@@ -601,8 +584,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
320, 320,
240, 240,
},
@@ -634,8 +615,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
856, 856,
480, 480,
},
@@ -670,8 +649,6 @@ static struct panel_settings known_lcd_panels[] .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
.mode_backlight = 0x00000000,
.mode_auxpll = (48/12) * 2,
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
800, 800,
480, 480,
},
@@ -800,7 +777,8 @@ static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
return 0;
}
-static void au1200_setpanel (struct panel_settings *newpanel)
+static void au1200_setpanel(struct panel_settings *newpanel,
+ struct au1200fb_platdata *pd)
{
/*
* Perform global setup/init of LCD controller
@@ -834,8 +812,8 @@ static void au1200_setpanel (struct panel_settings *newpanel)
the controller, the clock cannot be turned off before first
shutting down the controller.
*/
- if (panel->device_shutdown != NULL)
- panel->device_shutdown();
+ if (pd->panel_shutdown)
+ pd->panel_shutdown();
}
/* Newpanel = NULL indicates a shutdown operation only */
@@ -888,7 +866,8 @@ static void au1200_setpanel (struct panel_settings *newpanel)
au_sync();
/* Call init of panel */
- if (panel->device_init != NULL) panel->device_init();
+ if (pd->panel_init)
+ pd->panel_init();
/* FIX!!!! not appropriate on panel change!!! Global setup/init */
lcd->intenable = 0;
@@ -1221,6 +1200,8 @@ static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
*/
static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
{
+ struct au1200fb_device *fbdev = fbi->par;
+
/* Short-circuit screen blanking */
if (noblanking)
return 0;
@@ -1230,13 +1211,13 @@ static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
case FB_BLANK_UNBLANK:
case FB_BLANK_NORMAL:
/* printk("turn on panel\n"); */
- au1200_setpanel(panel);
+ au1200_setpanel(panel, fbdev->pd);
break;
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
/* printk("turn off panel\n"); */
- au1200_setpanel(NULL);
+ au1200_setpanel(NULL, fbdev->pd);
break;
default:
break;
@@ -1464,6 +1445,7 @@ static void get_window(unsigned int plane,
static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
+ struct au1200fb_device *fbdev = info->par;
int plane;
int val;
@@ -1508,7 +1490,7 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
struct panel_settings *newpanel;
panel_index = iodata.global.panel_choice;
newpanel = &known_lcd_panels[panel_index];
- au1200_setpanel(newpanel);
+ au1200_setpanel(newpanel, fbdev->pd);
}
break;
@@ -1624,22 +1606,102 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
/*-------------------------------------------------------------------------*/
-/* AU1200 LCD controller device driver */
+static int au1200fb_setup(struct au1200fb_platdata *pd)
+{
+ char *options = NULL;
+ char *this_opt, *endptr;
+ int num_panels = ARRAY_SIZE(known_lcd_panels);
+ int panel_idx = -1;
+
+ fb_get_options(DRIVER_NAME, &options);
+
+ if (!options)
+ goto out;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ /* Panel option - can be panel name,
+ * "bs" for board-switch, or number/index */
+ if (!strncmp(this_opt, "panel:", 6)) {
+ int i;
+ long int li;
+ char *endptr;
+ this_opt += 6;
+ /* First check for index, which allows
+ * to short circuit this mess */
+ li = simple_strtol(this_opt, &endptr, 0);
+ if (*endptr = '\0')
+ panel_idx = (int)li;
+ else if (strcmp(this_opt, "bs") = 0)
+ panel_idx = pd->panel_index();
+ else {
+ for (i = 0; i < num_panels; i++) {
+ if (!strcmp(this_opt,
+ known_lcd_panels[i].name)) {
+ panel_idx = i;
+ break;
+ }
+ }
+ }
+ if ((panel_idx < 0) || (panel_idx >= num_panels))
+ print_warn("Panel %s not supported!", this_opt);
+ else
+ panel_index = panel_idx;
+
+ } else if (strncmp(this_opt, "nohwcursor", 10) = 0)
+ nohwcursor = 1;
+ else if (strncmp(this_opt, "devices:", 8) = 0) {
+ this_opt += 8;
+ device_count = simple_strtol(this_opt, &endptr, 0);
+ if ((device_count < 0) ||
+ (device_count > MAX_DEVICE_COUNT))
+ device_count = MAX_DEVICE_COUNT;
+ } else if (strncmp(this_opt, "wincfg:", 7) = 0) {
+ this_opt += 7;
+ window_index = simple_strtol(this_opt, &endptr, 0);
+ if ((window_index < 0) ||
+ (window_index >= ARRAY_SIZE(windows)))
+ window_index = DEFAULT_WINDOW_INDEX;
+ } else if (strncmp(this_opt, "off", 3) = 0)
+ return 1;
+ else
+ print_warn("Unsupported option \"%s\"", this_opt);
+ }
+
+out:
+ return 0;
+}
+
+/* AU1200 LCD controller device driver */
static int __devinit au1200fb_drv_probe(struct platform_device *dev)
{
struct au1200fb_device *fbdev;
+ struct au1200fb_platdata *pd;
struct fb_info *fbi = NULL;
unsigned long page;
int bpp, plane, ret, irq;
+ print_info("" DRIVER_DESC "");
+
+ pd = dev->dev.platform_data;
+ if (!pd)
+ return -ENODEV;
+
+ /* Setup driver with options */
+ if (au1200fb_setup(pd))
+ return -ENODEV;
+
+ /* Point to the panel selected */
+ panel = &known_lcd_panels[panel_index];
+ win = &windows[window_index];
+
+ printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
+ printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
+
/* shut gcc up */
ret = 0;
fbdev = NULL;
- /* Kickstart the panel */
- au1200_setpanel(panel);
-
for (plane = 0; plane < device_count; ++plane) {
bpp = winbpp(win->w[plane].mode_winctrl1);
if (win->w[plane].xres = 0)
@@ -1655,6 +1717,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
_au1200fb_infos[plane] = fbi;
fbdev = fbi->par;
fbdev->fb_info = fbi;
+ fbdev->pd = pd;
fbdev->plane = plane;
@@ -1716,6 +1779,11 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
goto failed;
}
+ platform_set_drvdata(dev, pd);
+
+ /* Kickstart the panel */
+ au1200_setpanel(panel, pd);
+
return 0;
failed:
@@ -1735,12 +1803,13 @@ failed:
static int __devexit au1200fb_drv_remove(struct platform_device *dev)
{
+ struct au1200fb_platdata *pd = platform_get_drvdata(dev);
struct au1200fb_device *fbdev;
struct fb_info *fbi;
int plane;
/* Turn off the panel */
- au1200_setpanel(NULL);
+ au1200_setpanel(NULL, pd);
for (plane = 0; plane < device_count; ++plane) {
fbi = _au1200fb_infos[plane];
@@ -1768,7 +1837,8 @@ static int __devexit au1200fb_drv_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int au1200fb_drv_suspend(struct device *dev)
{
- au1200_setpanel(NULL);
+ struct au1200fb_platdata *pd = dev_get_drvdata(dev);
+ au1200_setpanel(NULL, pd);
lcd->outmask = 0;
au_sync();
@@ -1778,11 +1848,12 @@ static int au1200fb_drv_suspend(struct device *dev)
static int au1200fb_drv_resume(struct device *dev)
{
+ struct au1200fb_platdata *pd = dev_get_drvdata(dev);
struct fb_info *fbi;
int i;
/* Kickstart the panel */
- au1200_setpanel(panel);
+ au1200_setpanel(panel, pd);
for (i = 0; i < device_count; i++) {
fbi = _au1200fb_infos[i];
@@ -1817,100 +1888,8 @@ static struct platform_driver au1200fb_driver = {
/*-------------------------------------------------------------------------*/
-/* Kernel driver */
-
-static int au1200fb_setup(void)
-{
- char *options = NULL;
- char *this_opt, *endptr;
- int num_panels = ARRAY_SIZE(known_lcd_panels);
- int panel_idx = -1;
-
- fb_get_options(DRIVER_NAME, &options);
-
- if (options) {
- while ((this_opt = strsep(&options,",")) != NULL) {
- /* Panel option - can be panel name,
- * "bs" for board-switch, or number/index */
- if (!strncmp(this_opt, "panel:", 6)) {
- int i;
- long int li;
- char *endptr;
- this_opt += 6;
- /* First check for index, which allows
- * to short circuit this mess */
- li = simple_strtol(this_opt, &endptr, 0);
- if (*endptr = '\0') {
- panel_idx = (int)li;
- }
- else if (strcmp(this_opt, "bs") = 0) {
- extern int board_au1200fb_panel(void);
- panel_idx = board_au1200fb_panel();
- }
-
- else
- for (i = 0; i < num_panels; i++) {
- if (!strcmp(this_opt, known_lcd_panels[i].name)) {
- panel_idx = i;
- break;
- }
- }
-
- if ((panel_idx < 0) || (panel_idx >= num_panels)) {
- print_warn("Panel %s not supported!", this_opt);
- }
- else
- panel_index = panel_idx;
- }
-
- else if (strncmp(this_opt, "nohwcursor", 10) = 0) {
- nohwcursor = 1;
- }
-
- else if (strncmp(this_opt, "devices:", 8) = 0) {
- this_opt += 8;
- device_count = simple_strtol(this_opt,
- &endptr, 0);
- if ((device_count < 0) ||
- (device_count > MAX_DEVICE_COUNT))
- device_count = MAX_DEVICE_COUNT;
- }
-
- else if (strncmp(this_opt, "wincfg:", 7) = 0) {
- this_opt += 7;
- window_index = simple_strtol(this_opt,
- &endptr, 0);
- if ((window_index < 0) ||
- (window_index >= ARRAY_SIZE(windows)))
- window_index = DEFAULT_WINDOW_INDEX;
- }
-
- else if (strncmp(this_opt, "off", 3) = 0)
- return 1;
- /* Unsupported option */
- else {
- print_warn("Unsupported option \"%s\"", this_opt);
- }
- }
- }
- return 0;
-}
-
static int __init au1200fb_init(void)
{
- print_info("" DRIVER_DESC "");
-
- /* Setup driver with options */
- if (au1200fb_setup())
- return -ENODEV;
-
- /* Point to the panel selected */
- panel = &known_lcd_panels[panel_index];
- win = &windows[window_index];
-
- printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
- printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
-
return platform_driver_register(&au1200fb_driver);
}
--
1.7.7.1
^ permalink raw reply related
* [PATCH] FSL/DIU: add 1080P, 720P and 800x600 video modes
From: r66093 @ 2011-11-02 6:35 UTC (permalink / raw)
To: linux-fbdev
From: Jerry Huang <Chang-Ming.Huang@freescale.com>
Add 1920x1080, 1280x720 and 800x600 resolution support.
Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
CC: Paul Mundt <lethal@linux-sh.org>
---
drivers/video/fsl-diu-fb.c | 47 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 46 insertions(+), 1 deletions(-)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 0acc7d6..756975f 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008,2011 Freescale Semiconductor, Inc. All Rights Reserved.
*
* Freescale DIU Frame Buffer device driver
*
@@ -60,6 +60,21 @@ static struct fb_videomode __devinitdata fsl_diu_default_mode = {
static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
{
+ .name = "800x600-60",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 25000,
+ .left_margin = 88,
+ .right_margin = 40,
+ .upper_margin = 23,
+ .lower_margin = 1,
+ .hsync_len = 128,
+ .vsync_len = 4,
+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
.name = "1024x768-60",
.refresh = 60,
.xres = 1024,
@@ -105,6 +120,21 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
.vmode = FB_VMODE_NONINTERLACED
},
{
+ .name = "1280x720-60",
+ .refresh = 60,
+ .xres = 1280,
+ .yres = 720,
+ .pixclock = 13426,
+ .left_margin = 192,
+ .right_margin = 64,
+ .upper_margin = 22,
+ .lower_margin = 1,
+ .hsync_len = 136,
+ .vsync_len = 3,
+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
.name = "1280x1024-60",
.refresh = 60,
.xres = 1280,
@@ -150,6 +180,21 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
.vmode = FB_VMODE_NONINTERLACED
},
{
+ .name = "1920x1080-60",
+ .refresh = 60,
+ .xres = 1920,
+ .yres = 1080,
+ .pixclock = 5787,
+ .left_margin = 328,
+ .right_margin = 120,
+ .upper_margin = 34,
+ .lower_margin = 1,
+ .hsync_len = 208,
+ .vsync_len = 3,
+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
.name = "320x240", /* for AOI only */
.refresh = 60,
.xres = 320,
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH] FSL/DIU: add 1080P, 720P and 800x600 video modes
From: Tabi Timur-B04825 @ 2011-11-02 13:23 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1320215710-9128-1-git-send-email-r66093@freescale.com>
On Wed, Nov 2, 2011 at 1:35 AM, <r66093@freescale.com> wrote:
> From: Jerry Huang <Chang-Ming.Huang@freescale.com>
>
> Add 1920x1080, 1280x720 and 800x600 resolution support.
>
> Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> CC: Paul Mundt <lethal@linux-sh.org>
> ---
These video modes are already in the driver.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* RE: [PATCH] FSL/DIU: add 1080P, 720P and 800x600 video modes
From: Huang Changming-R66093 @ 2011-11-03 2:32 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1320215710-9128-1-git-send-email-r66093@freescale.com>
Please ignore this patch.
Thanks and Best Regards
Jerry Huang
> -----Original Message-----
> From: Huang Changming-R66093
> Sent: Wednesday, November 02, 2011 2:35 PM
> To: linux-fbdev@vger.kernel.org
> Cc: Huang Changming-R66093; Paul Mundt
> Subject: [PATCH] FSL/DIU: add 1080P, 720P and 800x600 video modes
>
> From: Jerry Huang <Chang-Ming.Huang@freescale.com>
>
> Add 1920x1080, 1280x720 and 800x600 resolution support.
>
> Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
> CC: Paul Mundt <lethal@linux-sh.org>
> ---
> drivers/video/fsl-diu-fb.c | 47
> +++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 46 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
> index 0acc7d6..756975f 100644
> --- a/drivers/video/fsl-diu-fb.c
> +++ b/drivers/video/fsl-diu-fb.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright 2008,2011 Freescale Semiconductor, Inc. All Rights
> Reserved.
> *
> * Freescale DIU Frame Buffer device driver
> *
> @@ -60,6 +60,21 @@ static struct fb_videomode __devinitdata
> fsl_diu_default_mode = {
>
> static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
> {
> + .name = "800x600-60",
> + .refresh = 60,
> + .xres = 800,
> + .yres = 600,
> + .pixclock = 25000,
> + .left_margin = 88,
> + .right_margin = 40,
> + .upper_margin = 23,
> + .lower_margin = 1,
> + .hsync_len = 128,
> + .vsync_len = 4,
> + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
> + .vmode = FB_VMODE_NONINTERLACED
> + },
> + {
> .name = "1024x768-60",
> .refresh = 60,
> .xres = 1024,
> @@ -105,6 +120,21 @@ static struct fb_videomode __devinitdata
> fsl_diu_mode_db[] = {
> .vmode = FB_VMODE_NONINTERLACED
> },
> {
> + .name = "1280x720-60",
> + .refresh = 60,
> + .xres = 1280,
> + .yres = 720,
> + .pixclock = 13426,
> + .left_margin = 192,
> + .right_margin = 64,
> + .upper_margin = 22,
> + .lower_margin = 1,
> + .hsync_len = 136,
> + .vsync_len = 3,
> + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
> + .vmode = FB_VMODE_NONINTERLACED
> + },
> + {
> .name = "1280x1024-60",
> .refresh = 60,
> .xres = 1280,
> @@ -150,6 +180,21 @@ static struct fb_videomode __devinitdata
> fsl_diu_mode_db[] = {
> .vmode = FB_VMODE_NONINTERLACED
> },
> {
> + .name = "1920x1080-60",
> + .refresh = 60,
> + .xres = 1920,
> + .yres = 1080,
> + .pixclock = 5787,
> + .left_margin = 328,
> + .right_margin = 120,
> + .upper_margin = 34,
> + .lower_margin = 1,
> + .hsync_len = 208,
> + .vsync_len = 3,
> + .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
> + .vmode = FB_VMODE_NONINTERLACED
> + },
> + {
> .name = "320x240", /* for AOI only */
> .refresh = 60,
> .xres = 320,
> --
> 1.7.4.1
^ permalink raw reply
* [RFC] Virtual CRTCs (proposal + experimental code)
From: Ilija Hadzic @ 2011-11-03 15:59 UTC (permalink / raw)
To: dri-devel, linux-fbdev
Hi everyone,
I would like to bring to the attention of dri-devel and linux-fbdev
community a set of hopefully useful and interesting patches that
I (and a few other colleagues) have been working on during the past
few months. Here, I will provide a short abstract, so that you can
decide whether this is of interest for you. At the end, I will
provide the pointers to the code and documentation.
The code is based on Dave Arilie's tree, drm-next branch and it
allows a GPU driver to have an arbitrary number of CRTCs
(configurable by user) instead of only those CRTCs that represent
real hardware.
The new CRTCs, that we call Virtual CRTCs can be attached to a
foreign device, that we call CTD device (short for Compression
Transmission and Display), and pixels can be streamed out of the GPU
to the device.
In one example, we use AMD/ATI Radeon GPU to do 3D rendering
(accelerated, of course) and we use our code to add additional
monitor heads using DisplayLink devices. In other words, we achieve
accelerated 3D rendering on a DisplayLink monitor. In another example
we funnel rendered pixels to userland by emulating a Video-for-Linux
device (and then userland can do whatever it wants with it). While
doing all this, GPU has no idea that we are doing this, the entire DRI
"thinks" that it is just dealing with a GPU that has a few "extra"
connectors and CRTCs. So everything ports without the need to modify
anything in the userland.
In general any device that can do something good with rendered pixels
can act as a CTD device, allowing a GPU to be an acceleration device
for a less capable display device or (the opposite) a frame-buffer-based
display device to be an expansion card for a GPU. Of course, for
each display device, a driver would have to be made compatible with our
new infrastructure (which is what we have done with DisplayLink driver
and also wrote one "synthetic" driver to fake out a V4L2 device as a
CTD device).
The newly introduced kernel module that we call VCRTCM (short for
Virtual CRTC Manager) handles the "traffic" between GPUs (actually
their CRTCs) and CTDs. The code makes use of DMA wherever possible
and also deals with specifics of CRTCs like modes, vblanks, page
flips, hardware cursor, etc. (just for kick, we played OpenArena
and watched Unigine Heaven demo on a DisplayLink monitor).
At this time, we would like to solicit feedback, comments, and
possibly contributions. The code is on github (pointers below)
and is based on the current state of drm-next branch from Dave's
tree. The code is very experimental, but complete and stable enough
that you can do something useful with it. We will be adding more
CTD drivers and updates to current ones in the near future and will
continue to maintain the code on github.
If the community finds this useful, we would be glad to work with
the maintainers on merging this upstream. So we would especially like
to hear what you would like to see changed to make this code acceptable
for the mainline of development.
My Github page is at https://github.com/ihadzic. To access the kernel
code type:
$ git clone git://github.com/ihadzic/linux-vcrtcm.git
$ git branch drm-next-vcrtcm origin/drm-next-vcrtcm
$ git checkout drm-next-vcrtcm
You will get all that's currently on Dave's drm-next plus our patches on
the top. We kept the development history preserved without squashing patches
(unless we had to due to merge/rebase conflicts), so you can see (and laugh
at) all our goofs and fixes to them.
To access the documentation, type:
$ git clone git://github.com/ihadzic/vcrtcm-doc.git
Then read the HOWTO.txt file. The first few sections provide some
general overview, and the sections that come later provide instructions
how to use our stuff.
Again, all comments, positive or negative, are very welcome.
-- Ilija
^ permalink raw reply
* Re: [RFC] Virtual CRTCs (proposal + experimental code)
From: Daniel Vetter @ 2011-11-03 17:21 UTC (permalink / raw)
To: Ilija Hadzic; +Cc: linux-fbdev, dri-devel
In-Reply-To: <CA+4h6Hk3gE+8ou6NSMhoGJWZJ-5aM1OgC0HFoKs55fjfQ-qN8g@mail.gmail.com>
Hi,
Quick question: How does this compare to Dave Airlies' PRIME buffer
sharing work for drm respectively the more generic dma_buf buffer sharing
work pushed by Linaro? You seem to aim for a solution for similar problems
(judging by your description) using a rather different approach.
Cheers, Daniel
On Thu, Nov 03, 2011 at 11:59:21AM -0400, Ilija Hadzic wrote:
> Hi everyone,
>
> I would like to bring to the attention of dri-devel and linux-fbdev
> community a set of hopefully useful and interesting patches that
> I (and a few other colleagues) have been working on during the past
> few months. Here, I will provide a short abstract, so that you can
> decide whether this is of interest for you. At the end, I will
> provide the pointers to the code and documentation.
>
> The code is based on Dave Arilie's tree, drm-next branch and it
> allows a GPU driver to have an arbitrary number of CRTCs
> (configurable by user) instead of only those CRTCs that represent
> real hardware.
>
> The new CRTCs, that we call Virtual CRTCs can be attached to a
> foreign device, that we call CTD device (short for Compression
> Transmission and Display), and pixels can be streamed out of the GPU
> to the device.
>
> In one example, we use AMD/ATI Radeon GPU to do 3D rendering
> (accelerated, of course) and we use our code to add additional
> monitor heads using DisplayLink devices. In other words, we achieve
> accelerated 3D rendering on a DisplayLink monitor. In another example
> we funnel rendered pixels to userland by emulating a Video-for-Linux
> device (and then userland can do whatever it wants with it). While
> doing all this, GPU has no idea that we are doing this, the entire DRI
> "thinks" that it is just dealing with a GPU that has a few "extra"
> connectors and CRTCs. So everything ports without the need to modify
> anything in the userland.
>
> In general any device that can do something good with rendered pixels
> can act as a CTD device, allowing a GPU to be an acceleration device
> for a less capable display device or (the opposite) a frame-buffer-based
> display device to be an expansion card for a GPU. Of course, for
> each display device, a driver would have to be made compatible with our
> new infrastructure (which is what we have done with DisplayLink driver
> and also wrote one "synthetic" driver to fake out a V4L2 device as a
> CTD device).
>
> The newly introduced kernel module that we call VCRTCM (short for
> Virtual CRTC Manager) handles the "traffic" between GPUs (actually
> their CRTCs) and CTDs. The code makes use of DMA wherever possible
> and also deals with specifics of CRTCs like modes, vblanks, page
> flips, hardware cursor, etc. (just for kick, we played OpenArena
> and watched Unigine Heaven demo on a DisplayLink monitor).
>
> At this time, we would like to solicit feedback, comments, and
> possibly contributions. The code is on github (pointers below)
> and is based on the current state of drm-next branch from Dave's
> tree. The code is very experimental, but complete and stable enough
> that you can do something useful with it. We will be adding more
> CTD drivers and updates to current ones in the near future and will
> continue to maintain the code on github.
>
> If the community finds this useful, we would be glad to work with
> the maintainers on merging this upstream. So we would especially like
> to hear what you would like to see changed to make this code acceptable
> for the mainline of development.
>
> My Github page is at https://github.com/ihadzic. To access the kernel
> code type:
>
> $ git clone git://github.com/ihadzic/linux-vcrtcm.git
> $ git branch drm-next-vcrtcm origin/drm-next-vcrtcm
> $ git checkout drm-next-vcrtcm
>
> You will get all that's currently on Dave's drm-next plus our patches on
> the top. We kept the development history preserved without squashing patches
> (unless we had to due to merge/rebase conflicts), so you can see (and laugh
> at) all our goofs and fixes to them.
>
> To access the documentation, type:
>
> $ git clone git://github.com/ihadzic/vcrtcm-doc.git
>
> Then read the HOWTO.txt file. The first few sections provide some
> general overview, and the sections that come later provide instructions
> how to use our stuff.
>
> Again, all comments, positive or negative, are very welcome.
>
> -- Ilija
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48
^ permalink raw reply
* Re: [RFC] Virtual CRTCs (proposal + experimental code)
From: David Airlie @ 2011-11-03 17:27 UTC (permalink / raw)
To: Ilija Hadzic; +Cc: linux-fbdev, dri-devel
In-Reply-To: <CA+4h6Hk3gE+8ou6NSMhoGJWZJ-5aM1OgC0HFoKs55fjfQ-qN8g@mail.gmail.com>
>
> Hi everyone,
>
> I would like to bring to the attention of dri-devel and linux-fbdev
> community a set of hopefully useful and interesting patches that
> I (and a few other colleagues) have been working on during the past
> few months. Here, I will provide a short abstract, so that you can
> decide whether this is of interest for you. At the end, I will
> provide the pointers to the code and documentation.
>
> The code is based on Dave Arilie's tree, drm-next branch and it
> allows a GPU driver to have an arbitrary number of CRTCs
> (configurable by user) instead of only those CRTCs that represent
> real hardware.
Well the current plan I had for this was to do it in userspace, I don't think the kernel
has any business doing it and I think for the simple USB case its fine but will fallover
when you get to the non-trivial cases where some sort of acceleration is required to move
pixels around. But in saying that its good you've done what something, and I'll try and spend
some time reviewing it.
The current plan from my POV is to add hotplug support to the X server and just hotplug USB
devices up there, and not mess up the kernel with lots of extra state that really the drivers
don't need to know about.
I'm also not sure how you deal with tiling etc, you can also start hitting rendering limits,
where a GPU can render to 4kx4k but you can plug in more USB devices, again I'm hoping to
solve this in userspace as well.
But I'll take some time if I can find it to look over it.
Dave.
^ permalink raw reply
* Re: [RFC] Virtual CRTCs (proposal + experimental code)
From: Alan Cox @ 2011-11-03 17:53 UTC (permalink / raw)
To: David Airlie; +Cc: linux-fbdev, dri-devel
In-Reply-To: <e80977e3-0992-454e-8ee2-2944560d3b3d@zmail16.collab.prod.int.phx2.redhat.com>
> Well the current plan I had for this was to do it in userspace, I don't think the kernel
> has any business doing it and I think for the simple USB case its fine but will fallover
> when you get to the non-trivial cases where some sort of acceleration is required to move
> pixels around. But in saying that its good you've done what something, and I'll try and spend
> some time reviewing it.
There are some clear advantages in the kernel doing bits of this I think.
The kernel understands device to device DMA, and has a better idea than
userspace about things like buffer alignment internals. It also means
this ultimately can work without X running which is a plus for some
applications (I want a displaylink gadget for my phone but thats another
story 8)).
> I'm also not sure how you deal with tiling etc, you can also start hitting rendering limits,
> where a GPU can render to 4kx4k but you can plug in more USB devices, again I'm hoping to
> solve this in userspace as well.
Tiling has to be handled by the recipient (at least when the fb is shared). The nastier end of
it that I don't see convered in the documentation is the handling of
fencing between cards. Eg if you wanted to do display on one card fed
into a second to do effects processing (think about TV type stuff)
Alan
^ permalink raw reply
* Re: [RFC] Virtual CRTCs (proposal + experimental code)
From: Ilija Hadzic @ 2011-11-03 18:00 UTC (permalink / raw)
To: David Airlie; +Cc: linux-fbdev, dri-devel
In-Reply-To: <e80977e3-0992-454e-8ee2-2944560d3b3d@zmail16.collab.prod.int.phx2.redhat.com>
On Thu, 3 Nov 2011, David Airlie wrote:
>
> Well the current plan I had for this was to do it in userspace, I don't think the kernel
> has any business doing it and I think for the simple USB case its fine but will fallover
> when you get to the non-trivial cases where some sort of acceleration is required to move
> pixels around. But in saying that its good you've done what something, and I'll try and spend
> some time reviewing it.
>
The reason I opted for doing this in kernel is that I wanted to confine
all the changes to a relatively small set of modules. At first this was a
pragmatic approach, because I live out of the mainstream development tree
and I didn't want to turn my life into an ethernal
merging/conflict-resolution activity.
However, a more fundamental reason for it is that I didn't want to be tied
to X. I deal with some userland applications (that unfortunately I can't
provide much detail of .... yet) that live directly on the top of libdrm.
So I set myself a goal of "full application transparency". Whatever is
thrown at me, I wanted to be able to handle without having to touch any
piece of application or library that the application relies on.
I think I have achieved this goal and really everything I tried just
worked out of the box (with an exception of two bug fixes to ATI DDX
and Xorg, that are bugs with or without my work).
-- Ilija
^ permalink raw reply
* [PATCH v3] GIO bus support for SGI IP22/28
From: Thomas Bogendoerfer @ 2011-11-04 11:09 UTC (permalink / raw)
To: linux-mips, linux-fbdev; +Cc: ralf, FlorianSchandinat
SGI IP22/IP28 machines have GIO busses for adding graphics and other
extension cards. This patch adds support for GIO driver/device
handling and converts the newport console driver to a GIO driver.
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
Changes in v3:
- reworked device tree for gio bus
- make module autoloading working
Changes in v2:
- use EXPORT_SYMBOL_GPL
- ChallengeS has only 2 slots
- use subsys_initcall for gio detection
arch/mips/include/asm/gio_device.h | 56 +++++
arch/mips/sgi-ip22/Makefile | 2 +-
arch/mips/sgi-ip22/ip22-gio.c | 428 +++++++++++++++++++++++++++++++++++
arch/mips/sgi-ip22/ip22-mc.c | 10 +-
arch/mips/sgi-ip22/ip22-setup.c | 21 --
drivers/video/console/newport_con.c | 63 ++++--
6 files changed, 534 insertions(+), 46 deletions(-)
diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h
new file mode 100644
index 0000000..5437c84
--- /dev/null
+++ b/arch/mips/include/asm/gio_device.h
@@ -0,0 +1,56 @@
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+struct gio_device_id {
+ __u8 id;
+};
+
+struct gio_device {
+ struct device dev;
+ struct resource resource;
+ unsigned int irq;
+ unsigned int slotno;
+
+ const char *name;
+ struct gio_device_id id;
+ unsigned id32:1;
+ unsigned gio64:1;
+};
+#define to_gio_device(d) container_of(d, struct gio_device, dev)
+
+struct gio_driver {
+ const char *name;
+ struct module *owner;
+ const struct gio_device_id *id_table;
+
+ int (*probe)(struct gio_device *, const struct gio_device_id *);
+ void (*remove)(struct gio_device *);
+ int (*suspend)(struct gio_device *, pm_message_t);
+ int (*resume)(struct gio_device *);
+ void (*shutdown)(struct gio_device *);
+
+ struct device_driver driver;
+};
+#define to_gio_driver(drv) container_of(drv, struct gio_driver, driver)
+
+extern const struct gio_device_id *gio_match_device(const struct gio_device_id *,
+ const struct gio_device *);
+extern struct gio_device *gio_dev_get(struct gio_device *);
+extern void gio_dev_put(struct gio_device *);
+
+extern int gio_device_register(struct gio_device *);
+extern void gio_device_unregister(struct gio_device *);
+extern void gio_release_dev(struct device *);
+
+static inline void gio_device_free(struct gio_device *dev)
+{
+ gio_release_dev(&dev->dev);
+}
+
+extern int gio_register_driver(struct gio_driver *);
+extern void gio_unregister_driver(struct gio_driver *);
+
+#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev)
+#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data))
+
+extern void gio_set_master(struct gio_device *);
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index cc53849..411cda9 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -4,7 +4,7 @@
#
obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \
- ip22-platform.o ip22-reset.o ip22-setup.o
+ ip22-platform.o ip22-reset.o ip22-setup.o ip22-gio.o
obj-$(CONFIG_SGI_IP22) += ip22-berr.o
obj-$(CONFIG_SGI_IP28) += ip28-berr.o
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
new file mode 100644
index 0000000..b6537d9
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -0,0 +1,428 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#include <asm/addrspace.h>
+#include <asm/paccess.h>
+#include <asm/gio_device.h>
+#include <asm/sgi/gio.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/ip22.h>
+
+static struct bus_type gio_bus_type;
+
+static struct {
+ const char *name;
+ __u8 id;
+} gio_name_table[] = {
+ { .name = "SGI Impact", .id = 0x10 },
+ { .name = "Phobos G160", .id = 0x35 },
+ /* fake IDs */
+ { .name = "SGI Newport", .id = 0x7e },
+ { .name = "SGI GR2/GR3", .id = 0x7f },
+};
+
+static struct device gio_bus = {
+ .init_name = "gio",
+};
+
+/**
+ * gio_match_device - Tell if an of_device structure has a matching
+ * gio_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct gio_device_id *gio_match_device(const struct gio_device_id *match,
+ const struct gio_device *dev)
+{
+ const struct gio_device_id *ids;
+
+ for (ids = match; ids->id != 0xff; ids++)
+ if (ids->id = dev->id.id)
+ return ids;
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gio_match_device);
+
+struct gio_device *gio_dev_get(struct gio_device *dev)
+{
+ struct device *tmp;
+
+ if (!dev)
+ return NULL;
+ tmp = get_device(&dev->dev);
+ if (tmp)
+ return to_gio_device(tmp);
+ else
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gio_dev_get);
+
+void gio_dev_put(struct gio_device *dev)
+{
+ if (dev)
+ put_device(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(gio_dev_put);
+
+/**
+ * gio_release_dev - free an gio device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this gio device are
+ * done.
+ */
+void gio_release_dev(struct device *dev)
+{
+ struct gio_device *giodev;
+
+ giodev = to_gio_device(dev);
+ kfree(giodev);
+}
+EXPORT_SYMBOL_GPL(gio_release_dev);
+
+int gio_device_register(struct gio_device *giodev)
+{
+ giodev->dev.bus = &gio_bus_type;
+ giodev->dev.parent = &gio_bus;
+ return device_register(&giodev->dev);
+}
+EXPORT_SYMBOL_GPL(gio_device_register);
+
+void gio_device_unregister(struct gio_device *giodev)
+{
+ device_unregister(&giodev->dev);
+}
+EXPORT_SYMBOL_GPL(gio_device_unregister);
+
+static int gio_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *gio_drv = to_gio_driver(drv);
+
+ return gio_match_device(gio_drv->id_table, gio_dev) != NULL;
+}
+
+static int gio_device_probe(struct device *dev)
+{
+ int error = -ENODEV;
+ struct gio_driver *drv;
+ struct gio_device *gio_dev;
+ const struct gio_device_id *match;
+
+ drv = to_gio_driver(dev->driver);
+ gio_dev = to_gio_device(dev);
+
+ if (!drv->probe)
+ return error;
+
+ gio_dev_get(gio_dev);
+
+ match = gio_match_device(drv->id_table, gio_dev);
+ if (match)
+ error = drv->probe(gio_dev, match);
+ if (error)
+ gio_dev_put(gio_dev);
+
+ return error;
+}
+
+static int gio_device_remove(struct device *dev)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+
+ if (dev->driver && drv->remove)
+ drv->remove(gio_dev);
+ return 0;
+}
+
+static int gio_device_suspend(struct device *dev, pm_message_t state)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->suspend)
+ error = drv->suspend(gio_dev, state);
+ return error;
+}
+
+static int gio_device_resume(struct device *dev)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->resume)
+ error = drv->resume(gio_dev);
+ return error;
+}
+
+static void gio_device_shutdown(struct device *dev)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+
+ if (dev->driver && drv->shutdown)
+ drv->shutdown(gio_dev);
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ int len = snprintf(buf, PAGE_SIZE, "gio:%x\n", gio_dev->id.id);
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gio_device *giodev;
+
+ giodev = to_gio_device(dev);
+ return sprintf(buf, "%s", giodev->name);
+}
+
+static ssize_t id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gio_device *giodev;
+
+ giodev = to_gio_device(dev);
+ return sprintf(buf, "%x", giodev->id.id);
+}
+
+static struct device_attribute gio_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_RO(name),
+ __ATTR_RO(id),
+ __ATTR_NULL,
+};
+
+static int gio_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+
+ add_uevent_var(env, "MODALIAS=gio:%x", gio_dev->id.id);
+ return 0;
+}
+
+int gio_register_driver(struct gio_driver *drv)
+{
+ /* initialize common driver fields */
+ if (!drv->driver.name)
+ drv->driver.name = drv->name;
+ if (!drv->driver.owner)
+ drv->driver.owner = drv->owner;
+ drv->driver.bus = &gio_bus_type;
+
+ /* register with core */
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(gio_register_driver);
+
+void gio_unregister_driver(struct gio_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(gio_unregister_driver);
+
+void gio_set_master(struct gio_device *dev)
+{
+ u32 tmp = sgimc->giopar;
+
+ switch (dev->slotno) {
+ case 0:
+ tmp |= SGIMC_GIOPAR_MASTERGFX;
+ break;
+ case 1:
+ tmp |= SGIMC_GIOPAR_MASTEREXP0;
+ break;
+ case 2:
+ tmp |= SGIMC_GIOPAR_MASTEREXP1;
+ break;
+ }
+ sgimc->giopar = tmp;
+}
+EXPORT_SYMBOL_GPL(gio_set_master);
+
+void ip22_gio_set_64bit(int slotno)
+{
+ u32 tmp = sgimc->giopar;
+
+ switch (slotno) {
+ case 0:
+ tmp |= SGIMC_GIOPAR_GFX64;
+ break;
+ case 1:
+ tmp |= SGIMC_GIOPAR_EXP064;
+ break;
+ case 2:
+ tmp |= SGIMC_GIOPAR_EXP164;
+ break;
+ }
+ sgimc->giopar = tmp;
+}
+
+static int ip22_gio_id(unsigned long addr, u32 *res)
+{
+ u8 tmp8;
+ u8 tmp16;
+ u32 tmp32;
+ u8 *ptr8;
+ u16 *ptr16;
+ u32 *ptr32;
+
+ ptr32 = (void *)CKSEG1ADDR(addr);
+ if (!get_dbe(tmp32, ptr32)) {
+ /*
+ * We got no DBE, but this doesn't mean anything.
+ * If GIO is pipelined (which can't be disabled
+ * for GFX slot) we don't get a DBE, but we see
+ * the transfer size as data. So we do an 8bit
+ * and a 16bit access and check whether the common
+ * data matches
+ */
+ ptr8 = (void *)CKSEG1ADDR(addr + 3);
+ get_dbe(tmp8, ptr8);
+ ptr16 = (void *)CKSEG1ADDR(addr + 2);
+ get_dbe(tmp16, ptr16);
+ if (tmp8 = (tmp16 & 0xff) &&
+ tmp8 = (tmp32 & 0xff) &&
+ tmp16 = (tmp32 & 0xffff)) {
+ *res = tmp32;
+ return 1;
+ }
+ }
+ return 0; /* nothing here */
+}
+
+#define HQ2_MYSTERY_OFFS 0x6A07C
+#define NEWPORT_USTATUS_OFFS 0xF133C
+
+static int ip22_is_gr2(unsigned long addr)
+{
+ u32 tmp;
+ u32 *ptr;
+
+ /* HQ2 only allows 32bit accesses */
+ ptr = (void *)CKSEG1ADDR(addr + HQ2_MYSTERY_OFFS);
+ if (!get_dbe(tmp, ptr)) {
+ if (tmp = 0xdeadbeef)
+ return 1;
+ }
+ return 0;
+}
+
+
+static void ip22_check_gio(int slotno, unsigned long addr)
+{
+ const char *name = "Unknown";
+ struct gio_device *gio_dev;
+ u32 tmp;
+ __u8 id;
+ int i;
+
+ /* first look for GR2/GR3 by checking mystery register */
+ if (ip22_is_gr2(addr))
+ tmp = 0x7f;
+ else {
+ if (!ip22_gio_id(addr, &tmp)) {
+ /*
+ * no GIO signature at start address of slot, but
+ * Newport doesn't have one, so let's check usea
+ * status register
+ */
+ if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp))
+ tmp = 0x7e;
+ else
+ tmp = 0;
+ }
+ }
+ if (tmp) {
+ id = GIO_ID(tmp);
+ if (tmp & GIO_32BIT_ID) {
+ if (tmp & GIO_64BIT_IFACE)
+ ip22_gio_set_64bit(slotno);
+ }
+ for (i = 0; i < ARRAY_SIZE(gio_name_table); i++) {
+ if (id = gio_name_table[i].id) {
+ name = gio_name_table[i].name;
+ break;
+ }
+ }
+ printk(KERN_INFO "GIO: slot %d : %s (id %x)\n",
+ slotno, name, id);
+ gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL);
+ gio_dev->name = name;
+ gio_dev->slotno = slotno;
+ gio_dev->id.id = id;
+ gio_dev->resource.start = addr;
+ gio_dev->resource.end = addr + 0x3fffff;
+ gio_dev->resource.flags = IORESOURCE_MEM;
+ dev_set_name(&gio_dev->dev, "%d", slotno);
+ gio_device_register(gio_dev);
+ } else
+ printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
+}
+
+static struct bus_type gio_bus_type = {
+ .name = "gio",
+ .dev_attrs = gio_dev_attrs,
+ .match = gio_bus_match,
+ .probe = gio_device_probe,
+ .remove = gio_device_remove,
+ .suspend = gio_device_suspend,
+ .resume = gio_device_resume,
+ .shutdown = gio_device_shutdown,
+ .uevent = gio_device_uevent,
+};
+
+static struct resource gio_bus_resource = {
+ .start = GIO_SLOT_GFX_BASE,
+ .end = GIO_SLOT_GFX_BASE + 0x9fffff,
+ .name = "GIO Bus",
+ .flags = IORESOURCE_MEM,
+};
+
+int __init ip22_gio_init(void)
+{
+ unsigned int pbdma __maybe_unused;
+ int ret;
+
+ ret = device_register(&gio_bus);
+ if (ret)
+ return ret;
+
+ ret = bus_register(&gio_bus_type);
+ if (!ret) {
+ request_resource(&iomem_resource, &gio_bus_resource);
+ printk(KERN_INFO "GIO: Probing bus...\n");
+
+ if (ip22_is_fullhouse() ||
+ !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) {
+ /* Indigo2 and ChallengeS */
+ ip22_check_gio(0, GIO_SLOT_GFX_BASE);
+ ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
+ } else {
+ /* Indy */
+ ip22_check_gio(0, GIO_SLOT_GFX_BASE);
+ ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
+ ip22_check_gio(2, GIO_SLOT_EXP1_BASE);
+ }
+ } else
+ device_unregister(&gio_bus);
+
+ return ret;
+}
+
+subsys_initcall(ip22_gio_init);
+
diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c
index d22262e..75ada8a 100644
--- a/arch/mips/sgi-ip22/ip22-mc.c
+++ b/arch/mips/sgi-ip22/ip22-mc.c
@@ -139,11 +139,11 @@ void __init sgimc_init(void)
* zero.
*/
/* don't touch parity settings for IP28 */
-#ifndef CONFIG_SGI_IP28
tmp = sgimc->cpuctrl0;
- tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
- SGIMC_CCTRL0_R4KNOCHKPARR);
+#ifndef CONFIG_SGI_IP28
+ tmp |= SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM;
#endif
+ tmp |= SGIMC_CCTRL0_R4KNOCHKPARR;
sgimc->cpuctrl0 = tmp;
/* Step 3: Setup the MC write buffer depth, this is controlled
@@ -178,7 +178,8 @@ void __init sgimc_init(void)
*/
/* First the basic invariants across all GIO64 implementations. */
- tmp = SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
+ tmp = sgimc->giopar & SGIMC_GIOPAR_GFX64; /* keep gfx 64bit settings */
+ tmp |= SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
tmp |= SGIMC_GIOPAR_ONEBUS; /* Only one physical GIO bus exists */
if (ip22_is_fullhouse()) {
@@ -193,7 +194,6 @@ void __init sgimc_init(void)
tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp[01] pipelined */
tmp |= SGIMC_GIOPAR_PLINEEXP1;
tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA masters */
- tmp |= SGIMC_GIOPAR_GFX64; /* GFX at 64 bits */
}
} else {
/* Guiness specific settings. */
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index 5e66213..c7bdfe4 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -26,9 +26,6 @@
#include <asm/sgi/hpc3.h>
#include <asm/sgi/ip22.h>
-unsigned long sgi_gfxaddr;
-EXPORT_SYMBOL_GPL(sgi_gfxaddr);
-
extern void ip22_be_init(void) __init;
void __init plat_mem_setup(void)
@@ -78,22 +75,4 @@ void __init plat_mem_setup(void)
prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
add_preferred_console("arc", 0, NULL);
}
-
-#if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
- {
- ULONG *gfxinfo;
- ULONG * (*__vec)(void) = (void *) (long)
- *((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20));
-
- gfxinfo = __vec();
- sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000
- && gfxinfo[1] <= 0xc0000000)
- ? gfxinfo[1] - 0xa0000000 : 0);
-
- /* newport addresses? */
- if (sgi_gfxaddr = 0x1f0f0000 || sgi_gfxaddr = 0x1f4f0000) {
- conswitchp = &newport_con;
- }
- }
-#endif
}
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 93317b5..a122d92 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -25,14 +25,13 @@
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/gio_device.h>
+
#include <video/newport.h>
#include <linux/linux_logo.h>
#include <linux/font.h>
-
-extern unsigned long sgi_gfxaddr;
-
#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
/* borrowed from fbcon.c */
@@ -304,12 +303,6 @@ static const char *newport_startup(void)
{
int i;
- if (!sgi_gfxaddr)
- return NULL;
-
- if (!npregs)
- npregs = (struct newport_regs *)/* ioremap cannot fail */
- ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
npregs->cset.config = NPORT_CFG_GD0;
if (newport_wait(npregs))
@@ -743,26 +736,58 @@ const struct consw newport_con = {
.con_save_screen = DUMMY
};
-#ifdef MODULE
-static int __init newport_console_init(void)
+static int newport_probe(struct gio_device *dev,
+ const struct gio_device_id *id)
{
- if (!sgi_gfxaddr)
- return 0;
+ unsigned long newport_addr;
- if (!npregs)
- npregs = (struct newport_regs *)/* ioremap cannot fail */
- ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
+ if (!dev->resource.start)
+ return -EINVAL;
+
+ if (npregs)
+ return -EBUSY; /* we only support one Newport as console */
+
+ newport_addr = dev->resource.start + 0xF0000;
+ if (!request_mem_region(newport_addr, 0x10000, "Newport"))
+ return -ENODEV;
+
+ npregs = (struct newport_regs *)/* ioremap cannot fail */
+ ioremap(newport_addr, sizeof(struct newport_regs));
return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
}
-module_init(newport_console_init);
-static void __exit newport_console_exit(void)
+static void newport_remove(struct gio_device *dev)
{
give_up_console(&newport_con);
iounmap((void *)npregs);
}
+
+static struct gio_device_id newport_ids[] = {
+ { .id = 0x7e },
+ { .id = 0xff }
+};
+
+MODULE_ALIAS("gio:7e");
+
+static struct gio_driver newport_driver = {
+ .name = "newport",
+ .id_table = newport_ids,
+ .probe = newport_probe,
+ .remove = newport_remove,
+};
+
+int __init newport_console_init(void)
+{
+ return gio_register_driver(&newport_driver);
+}
+
+void __exit newport_console_exit(void)
+{
+ gio_unregister_driver(&newport_driver);
+}
+
+module_init(newport_console_init);
module_exit(newport_console_exit);
-#endif
MODULE_LICENSE("GPL");
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox