summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2002-08-16 02:56:25 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-08-16 02:56:25 -0700
commit062dffeab2d2be6de87edcd7aaf5de807be995e5 (patch)
tree0466aca36f5027a96df8ebd524d6bcf477e02889
parent273cbb5a2a76ec9ea0ec5d41fce802b3ba5c1361 (diff)
parent75273dcb8350b929b1f34abb65e18ca7b45ab946 (diff)
Merge bk://matroxfb.bkbits.net/linux-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--drivers/video/Config.help58
-rw-r--r--drivers/video/Config.in9
-rw-r--r--drivers/video/matrox/Makefile6
-rw-r--r--drivers/video/matrox/g450_pll.c85
-rw-r--r--drivers/video/matrox/g450_pll.h2
-rw-r--r--drivers/video/matrox/i2c-matroxfb.c259
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.c332
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.h4
-rw-r--r--drivers/video/matrox/matroxfb_Ti3026.c22
-rw-r--r--drivers/video/matrox/matroxfb_accel.c34
-rw-r--r--drivers/video/matrox/matroxfb_accel.h2
-rw-r--r--drivers/video/matrox/matroxfb_base.c608
-rw-r--r--drivers/video/matrox/matroxfb_base.h54
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c377
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.h3
-rw-r--r--drivers/video/matrox/matroxfb_g450.c465
-rw-r--r--drivers/video/matrox/matroxfb_g450.h14
-rw-r--r--drivers/video/matrox/matroxfb_maven.c124
-rw-r--r--drivers/video/matrox/matroxfb_maven.h16
-rw-r--r--drivers/video/matrox/matroxfb_misc.c14
20 files changed, 1405 insertions, 1083 deletions
diff --git a/drivers/video/Config.help b/drivers/video/Config.help
index 21c25f78749a..7a079fff6d58 100644
--- a/drivers/video/Config.help
+++ b/drivers/video/Config.help
@@ -387,8 +387,7 @@ CONFIG_FB_MATROX
Say Y here if you have a Matrox Millennium, Matrox Millennium II,
Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video,
- Matrox G400, G450 or G550 card in your box. At this time, support for
- the G-series digital output is almost non-existant.
+ Matrox G400, G450 or G550 card in your box.
This driver is also available as a module ( = code which can be
inserted and removed from the running kernel whenever you want).
@@ -413,7 +412,7 @@ CONFIG_FB_MATROX_MYSTIQUE
packed pixel and 32 bpp packed pixel. You can also use font widths
different from 8.
-CONFIG_FB_MATROX_G100
+CONFIG_FB_MATROX_G450
Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based
video card. If you select "Advanced lowlevel driver options", you
should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
@@ -423,11 +422,35 @@ CONFIG_FB_MATROX_G100
If you need support for G400 secondary head, you must first say Y to
"I2C support" and "I2C bit-banging support" in the character devices
section, and then to "Matrox I2C support" and "G400 second head
- support" here in the framebuffer section.
+ support" here in the framebuffer section. G450/G550 secondary head
+ and digital output are supported without additional modules.
+
+ The driver starts in monitor mode. You must use the matroxset tool
+ (available at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to
+ swap primary and secondary head outputs, or to change output mode.
+ Secondary head driver always start in 640x480 resolution and you
+ must use fbset to change it.
+
+ Do not forget that second head supports only 16 and 32 bpp
+ packed pixels, so it is a good idea to compile them into the kernel
+ too. You can use only some font widths, as the driver uses generic
+ painting procedures (the secondary head does not use acceleration
+ engine).
- If you have G550, you must also compile support for G450/G550 secondary
- head into kernel, otherwise picture will be shown only on output you
- are probably not using...
+ G450/G550 hardware can display TV picture only from secondary CRTC,
+ and it performs no scaling, so picture must have 525 or 625 lines.
+
+CONFIG_FB_MATROX_G100A
+ Say Y here if you have a Matrox G100, G200 or G400 based
+ video card. If you select "Advanced lowlevel driver options", you
+ should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed
+ pixel and 32 bpp packed pixel. You can also use font widths
+ different from 8.
+
+ If you need support for G400 secondary head, you must first say Y to
+ "I2C support" and "I2C bit-banging support" in the character devices
+ section, and then to "Matrox I2C support" and "G400 second head
+ support" here in the framebuffer section.
CONFIG_FB_MATROX_I2C
This drivers creates I2C buses which are needed for accessing the
@@ -470,27 +493,6 @@ CONFIG_FB_MATROX_MAVEN
painting procedures (the secondary head does not use acceleration
engine).
-CONFIG_FB_MATROX_G450
- Say Y or M here if you want to use a secondary head (meaning two
- monitors in parallel) on G450, or if you are using analog output
- of G550.
-
- If you compile it as module, two modules are created,
- matroxfb_crtc2.o and matroxfb_g450.o. Both modules are needed if you
- want two independent display devices.
-
- The driver starts in monitor mode and currently does not support
- output in TV modes. You must use the matroxset tool (available
- at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to swap
- primary and secondary head outputs. Secondary head driver always
- start in 640x480 resolution and you must use fbset to change it.
-
- Also do not forget that second head supports only 16 and 32 bpp
- packed pixels, so it is a good idea to compile them into the kernel
- too. You can use only some font widths, as the driver uses generic
- painting procedures (the secondary head does not use acceleration
- engine).
-
CONFIG_FB_MATROX_MULTIHEAD
Say Y here if you have more than one (supported) Matrox device in
your computer and you want to use all of them for different monitors
diff --git a/drivers/video/Config.in b/drivers/video/Config.in
index b90b2bff0615..b36afc2f81dd 100644
--- a/drivers/video/Config.in
+++ b/drivers/video/Config.in
@@ -130,14 +130,19 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_MATROX" != "n" ]; then
bool ' Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
bool ' Mystique support' CONFIG_FB_MATROX_MYSTIQUE
- bool ' G100/G200/G400/G450/G550 support' CONFIG_FB_MATROX_G100
+ bool ' G100/G200/G400/G450/G550 support' CONFIG_FB_MATROX_G450
+ if [ "$CONFIG_FB_MATROX_G450" = "n" ]; then
+ bool ' G100/G200/G400 support' CONFIG_FB_MATROX_G100A
+ fi
+ if [ "$CONFIG_FB_MATROX_G450" = "y" -o "$CONFIG_FB_MATROX_G100A" = "y" ]; then
+ define_bool CONFIG_FB_MATROX_G100 y
+ fi
if [ "$CONFIG_I2C" != "n" ]; then
dep_tristate ' Matrox I2C support' CONFIG_FB_MATROX_I2C $CONFIG_FB_MATROX $CONFIG_I2C_ALGOBIT
if [ "$CONFIG_FB_MATROX_G100" = "y" ]; then
dep_tristate ' G400 second head support' CONFIG_FB_MATROX_MAVEN $CONFIG_FB_MATROX_I2C
fi
fi
- dep_tristate ' G450/G550 second head support (mandatory for G550)' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100
bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD
fi
tristate ' ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY
diff --git a/drivers/video/matrox/Makefile b/drivers/video/matrox/Makefile
index b7891f9cb540..fabb0e915aff 100644
--- a/drivers/video/matrox/Makefile
+++ b/drivers/video/matrox/Makefile
@@ -5,16 +5,16 @@
# All of the (potential) objects that export symbols.
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
-export-objs := matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o g450_pll.o
+export-objs := matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o g450_pll.o matroxfb_g450.o
# Each configuration option enables a list of files.
-my-obj-$(CONFIG_FB_MATROX_G100) := g450_pll.o
+my-obj-$(CONFIG_FB_MATROX_G100) += g450_pll.o
+my-obj-$(CONFIG_FB_MATROX_G450) += matroxfb_g450.o matroxfb_crtc2.o
obj-$(CONFIG_FB_MATROX) += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o $(my-obj-y)
obj-$(CONFIG_FB_MATROX_I2C) += i2c-matroxfb.o
obj-$(CONFIG_FB_MATROX_MAVEN) += matroxfb_maven.o matroxfb_crtc2.o
-obj-$(CONFIG_FB_MATROX_G450) += matroxfb_g450.o matroxfb_crtc2.o
include $(TOPDIR)/Rules.make
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index 2b7e81b08931..8073a73f6f35 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox PCI cards - G450/G550 PLL control.
*
- * (c) 2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2001/11/29
+ * Version: 1.64 2002/06/10
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
@@ -33,6 +33,10 @@ static unsigned int g450_mnp2vco(CPMINFO unsigned int mnp) {
return (ACCESS_FBINFO(features).pll.ref_freq * n + (m >> 1)) / m;
}
+unsigned int g450_mnp2f(CPMINFO unsigned int mnp) {
+ return g450_vco2f(mnp, g450_mnp2vco(PMINFO mnp));
+}
+
static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) {
if (f2 < f1) {
f2 = f1 - f2;
@@ -52,40 +56,42 @@ static unsigned int g450_nextpll(CPMINFO const struct matrox_pll_limits* pi, uns
m = (mnp >> 16) & 0xFF;
p = mnp & 0xFF;
- if (m == 0 || m == 0xFF) {
- if (m == 0) {
- if (p & 0x40) {
- return NO_MORE_MNP;
+ do {
+ if (m == 0 || m == 0xFF) {
+ if (m == 0) {
+ if (p & 0x40) {
+ return NO_MORE_MNP;
+ }
+ if (p & 3) {
+ p--;
+ } else {
+ p = 0x40;
+ }
+ tvco >>= 1;
+ if (tvco < pi->vcomin) {
+ return NO_MORE_MNP;
+ }
+ *fvco = tvco;
}
- if (p & 3) {
- p--;
+
+ p &= 0x43;
+ if (tvco < 550000) {
+/* p |= 0x00; */
+ } else if (tvco < 700000) {
+ p |= 0x08;
+ } else if (tvco < 1000000) {
+ p |= 0x10;
+ } else if (tvco < 1150000) {
+ p |= 0x18;
} else {
- p = 0x40;
+ p |= 0x20;
}
- tvco >>= 1;
- if (tvco < pi->vcomin) {
- return NO_MORE_MNP;
- }
- *fvco = tvco;
- }
-
- p &= 0x43;
- if (tvco < 550000) {
-/* p |= 0x00; */
- } else if (tvco < 700000) {
- p |= 0x08;
- } else if (tvco < 1000000) {
- p |= 0x10;
- } else if (tvco < 1150000) {
- p |= 0x18;
+ m = 9;
} else {
- p |= 0x20;
+ m--;
}
- m = 9;
- } else {
- m--;
- }
- n = ((tvco * (m+1) + ACCESS_FBINFO(features).pll.ref_freq) / (ACCESS_FBINFO(features).pll.ref_freq * 2)) - 2;
+ n = ((tvco * (m+1) + ACCESS_FBINFO(features).pll.ref_freq) / (ACCESS_FBINFO(features).pll.ref_freq * 2)) - 2;
+ } while (n < 0x03 || n > 0x7A);
return (m << 16) | (n << 8) | p;
}
@@ -219,7 +225,7 @@ static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsi
}
}
-static inline void g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll) {
+void matroxfb_g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll) {
if (g450_cmppll(PMINFO mnp, pll)) {
g450_setpll(PMINFO mnp, pll);
}
@@ -385,10 +391,8 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
unsigned int vco;
unsigned int delta;
- if ((mnp & 0xFF00) < 0x0300 || (mnp & 0xFF00) > 0x7A00) {
- continue;
- }
vco = g450_mnp2vco(PMINFO mnp);
+#if 0
if (pll == M_VIDEO_PLL) {
unsigned int big, small;
@@ -406,6 +410,7 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
continue;
}
}
+#endif
delta = pll_freq_delta(fout, g450_vco2f(mnp, vco));
for (idx = mnpcount; idx > 0; idx--) {
/* == is important; due to nextpll algorithm we get
@@ -426,7 +431,7 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
}
/* VideoPLL and PixelPLL matched: do nothing... In all other cases we should get at least one frequency */
if (!mnpcount) {
- return 1;
+ return -EBUSY;
}
{
unsigned long flags;
@@ -435,15 +440,15 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
matroxfb_DAC_lock_irqsave(flags);
mnp = g450_checkcache(PMINFO ci, mnparray[0]);
if (mnp != NO_MORE_MNP) {
- g450_setpll_cond(PMINFO mnp, pll);
+ matroxfb_g450_setpll_cond(PMINFO mnp, pll);
} else {
mnp = g450_findworkingpll(PMINFO pll, mnparray, mnpcount);
g450_addcache(ci, mnparray[0], mnp);
}
updatehwstate_clk(&ACCESS_FBINFO(hw), mnp, pll);
matroxfb_DAC_unlock_irqrestore(flags);
+ return mnp;
}
- return 0;
}
/* It must be greater than number of possible PLL values.
@@ -465,8 +470,10 @@ int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll) {
}
EXPORT_SYMBOL(matroxfb_g450_setclk);
+EXPORT_SYMBOL(g450_mnp2f);
+EXPORT_SYMBOL(matroxfb_g450_setpll_cond);
-MODULE_AUTHOR("(c) 2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_AUTHOR("(c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Matrox G450/G550 PLL driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/matrox/g450_pll.h
index 58a80ef2fd76..c17ed74501e9 100644
--- a/drivers/video/matrox/g450_pll.h
+++ b/drivers/video/matrox/g450_pll.h
@@ -4,5 +4,7 @@
#include "matroxfb_base.h"
int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll);
+unsigned int g450_mnp2f(CPMINFO unsigned int mnp);
+void matroxfb_g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll);
#endif /* __G450_PLL_H__ */
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index 59fe2b984710..63d70448e783 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -2,9 +2,9 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
*
- * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
- * Version: 1.51 2001/01/19
+ * Version: 1.64 2002/06/10
*
* See matroxfb_base.c for contributors.
*
@@ -30,6 +30,12 @@
/******************************************************/
+struct matroxfb_dh_maven_info {
+ struct i2c_bit_adapter maven;
+ struct i2c_bit_adapter ddc1;
+ struct i2c_bit_adapter ddc2;
+};
+
static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
unsigned long flags;
int v;
@@ -40,7 +46,7 @@ static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
return v;
}
-static inline void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
+static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
unsigned long flags;
int v;
@@ -53,7 +59,7 @@ static inline void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int
}
/* software I2C functions */
-static void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
+static inline void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
if (state)
state = 0;
else
@@ -61,68 +67,24 @@ static void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state)
matroxfb_set_gpio(minfo, ~mask, state);
}
-static void matroxfb_maven_setsda(void* data, int state) {
- matroxfb_i2c_set(data, MAT_DATA, state);
-}
-
-static void matroxfb_maven_setscl(void* data, int state) {
- matroxfb_i2c_set(data, MAT_CLK, state);
-}
-
-static int matroxfb_maven_getsda(void* data) {
- return (matroxfb_read_gpio(data) & MAT_DATA) ? 1 : 0;
-}
-
-static int matroxfb_maven_getscl(void* data) {
- return (matroxfb_read_gpio(data) & MAT_CLK) ? 1 : 0;
-}
-
-static void matroxfb_ddc1_setsda(void* data, int state) {
- matroxfb_i2c_set(data, DDC1_DATA, state);
-}
-
-static void matroxfb_ddc1_setscl(void* data, int state) {
- matroxfb_i2c_set(data, DDC1_CLK, state);
-}
-
-static int matroxfb_ddc1_getsda(void* data) {
- return (matroxfb_read_gpio(data) & DDC1_DATA) ? 1 : 0;
-}
-
-static int matroxfb_ddc1_getscl(void* data) {
- return (matroxfb_read_gpio(data) & DDC1_CLK) ? 1 : 0;
-}
-
-static void matroxfb_ddc1b_setsda(void* data, int state) {
- matroxfb_i2c_set(data, DDC1B_DATA, state);
-}
-
-static void matroxfb_ddc1b_setscl(void* data, int state) {
- matroxfb_i2c_set(data, DDC1B_CLK, state);
-}
-
-static int matroxfb_ddc1b_getsda(void* data) {
- return (matroxfb_read_gpio(data) & DDC1B_DATA) ? 1 : 0;
-}
-
-static int matroxfb_ddc1b_getscl(void* data) {
- return (matroxfb_read_gpio(data) & DDC1B_CLK) ? 1 : 0;
+static void matroxfb_gpio_setsda(void* data, int state) {
+ struct i2c_bit_adapter* b = data;
+ matroxfb_i2c_set(b->minfo, b->mask.data, state);
}
-static void matroxfb_ddc2_setsda(void* data, int state) {
- matroxfb_i2c_set(data, DDC2_DATA, state);
+static void matroxfb_gpio_setscl(void* data, int state) {
+ struct i2c_bit_adapter* b = data;
+ matroxfb_i2c_set(b->minfo, b->mask.clock, state);
}
-static void matroxfb_ddc2_setscl(void* data, int state) {
- matroxfb_i2c_set(data, DDC2_CLK, state);
+static int matroxfb_gpio_getsda(void* data) {
+ struct i2c_bit_adapter* b = data;
+ return (matroxfb_read_gpio(b->minfo) & b->mask.data) ? 1 : 0;
}
-static int matroxfb_ddc2_getsda(void* data) {
- return (matroxfb_read_gpio(data) & DDC2_DATA) ? 1 : 0;
-}
-
-static int matroxfb_ddc2_getscl(void* data) {
- return (matroxfb_read_gpio(data) & DDC2_CLK) ? 1 : 0;
+static int matroxfb_gpio_getscl(void* data) {
+ struct i2c_bit_adapter* b = data;
+ return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
}
static void matroxfb_dh_inc_use(struct i2c_adapter* dummy) {
@@ -133,97 +95,36 @@ static void matroxfb_dh_dec_use(struct i2c_adapter* dummy) {
MOD_DEC_USE_COUNT;
}
-static struct i2c_adapter matroxmaven_i2c_adapter_template =
-{
- "",
- I2C_HW_B_G400,
-
- NULL,
- NULL,
-
- matroxfb_dh_inc_use,
- matroxfb_dh_dec_use,
- NULL,
- NULL,
- NULL,
-};
-
-static struct i2c_algo_bit_data matroxmaven_i2c_algo_template =
-{
- NULL,
- matroxfb_maven_setsda,
- matroxfb_maven_setscl,
- matroxfb_maven_getsda,
- matroxfb_maven_getscl,
- 10, 10, 100,
-};
-
-static struct i2c_adapter matrox_ddc1_adapter_template =
-{
- "",
- I2C_HW_B_G400, /* DDC */
-
- NULL,
- NULL,
-
- matroxfb_dh_inc_use,
- matroxfb_dh_dec_use,
- NULL,
- NULL,
- NULL,
-};
-
-static struct i2c_algo_bit_data matrox_ddc1_algo_template =
+static struct i2c_adapter matrox_i2c_adapter_template =
{
- NULL,
- matroxfb_ddc1_setsda,
- matroxfb_ddc1_setscl,
- matroxfb_ddc1_getsda,
- matroxfb_ddc1_getscl,
- 10, 10, 100,
-};
-
-static struct i2c_algo_bit_data matrox_ddc1b_algo_template =
-{
- NULL,
- matroxfb_ddc1b_setsda,
- matroxfb_ddc1b_setscl,
- matroxfb_ddc1b_getsda,
- matroxfb_ddc1b_getscl,
- 10, 10, 100,
-};
-
-static struct i2c_adapter matrox_ddc2_adapter_template =
-{
- "",
- I2C_HW_B_G400, /* DDC */
-
- NULL,
- NULL,
-
- matroxfb_dh_inc_use, /* should increment matroxfb_maven usage too, this DDC is coupled with maven_client */
- matroxfb_dh_dec_use, /* should decrement matroxfb_maven usage too */
- NULL,
- NULL,
- NULL,
+ .id = I2C_HW_B_G400,
+ .inc_use = matroxfb_dh_inc_use,
+ .dec_use = matroxfb_dh_dec_use,
};
-static struct i2c_algo_bit_data matrox_ddc2_algo_template =
+static struct i2c_algo_bit_data matrox_i2c_algo_template =
{
NULL,
- matroxfb_ddc2_setsda,
- matroxfb_ddc2_setscl,
- matroxfb_ddc2_getsda,
- matroxfb_ddc2_getscl,
+ matroxfb_gpio_setsda,
+ matroxfb_gpio_setscl,
+ matroxfb_gpio_getsda,
+ matroxfb_gpio_getscl,
10, 10, 100,
};
-static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo) {
+static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
+ unsigned int data, unsigned int clock, const char* name) {
int err;
- b->adapter.data = minfo;
+ b->minfo = minfo;
+ b->mask.data = data;
+ b->mask.clock = clock;
+ b->adapter = matrox_i2c_adapter_template;
+ sprintf(b->adapter.name, name, GET_FB_IDX(minfo->fbcon.node));
+ b->adapter.data = b;
b->adapter.algo_data = &b->bac;
- b->bac.data = minfo;
+ b->bac = matrox_i2c_algo_template;
+ b->bac.data = b;
err = i2c_bit_add_bus(&b->adapter);
b->initialized = !err;
return err;
@@ -236,50 +137,14 @@ static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
}
}
-static inline int i2c_maven_init(struct matroxfb_dh_maven_info* minfo2) {
- struct i2c_bit_adapter *b = &minfo2->maven;
-
- b->adapter = matroxmaven_i2c_adapter_template;
- b->bac = matroxmaven_i2c_algo_template;
- sprintf(b->adapter.name, "MAVEN:fb%u on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
- return i2c_bus_reg(b, minfo2->primary_dev);
-}
-
static inline void i2c_maven_done(struct matroxfb_dh_maven_info* minfo2) {
i2c_bit_bus_del(&minfo2->maven);
}
-static inline int i2c_ddc1_init(struct matroxfb_dh_maven_info* minfo2) {
- struct i2c_bit_adapter *b = &minfo2->ddc1;
-
- b->adapter = matrox_ddc1_adapter_template;
- b->bac = matrox_ddc1_algo_template;
- sprintf(b->adapter.name, "DDC:fb%u #0 on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
- return i2c_bus_reg(b, minfo2->primary_dev);
-}
-
-static inline int i2c_ddc1b_init(struct matroxfb_dh_maven_info* minfo2) {
- struct i2c_bit_adapter *b = &minfo2->ddc1;
-
- b->adapter = matrox_ddc1_adapter_template;
- b->bac = matrox_ddc1b_algo_template;
- sprintf(b->adapter.name, "DDC:fb%u #0 on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
- return i2c_bus_reg(b, minfo2->primary_dev);
-}
-
static inline void i2c_ddc1_done(struct matroxfb_dh_maven_info* minfo2) {
i2c_bit_bus_del(&minfo2->ddc1);
}
-static inline int i2c_ddc2_init(struct matroxfb_dh_maven_info* minfo2) {
- struct i2c_bit_adapter *b = &minfo2->ddc2;
-
- b->adapter = matrox_ddc2_adapter_template;
- b->bac = matrox_ddc2_algo_template;
- sprintf(b->adapter.name, "DDC:fb%u #1 on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
- return i2c_bus_reg(b, minfo2->primary_dev);
-}
-
static inline void i2c_ddc2_done(struct matroxfb_dh_maven_info* minfo2) {
i2c_bit_bus_del(&minfo2->ddc2);
}
@@ -299,24 +164,26 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
matroxfb_DAC_unlock_irqrestore(flags);
memset(m2info, 0, sizeof(*m2info));
- m2info->maven.minfo = m2info;
- m2info->ddc1.minfo = m2info;
- m2info->ddc2.minfo = m2info;
- m2info->primary_dev = minfo;
-
- if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGA2064W ||
- ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGA2164W ||
- ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGA2164W_AGP)
- err = i2c_ddc1b_init(m2info);
- else
- err = i2c_ddc1_init(m2info);
+
+ switch (ACCESS_FBINFO(chip)) {
+ case MGA_2064:
+ case MGA_2164:
+ err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, DDC1B_CLK, "DDC:fb%u #0 on i2c-matroxfb");
+ break;
+ default:
+ err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, DDC1_CLK, "DDC:fb%u #0 on i2c-matroxfb");
+ break;
+ }
if (err)
goto fail_ddc1;
- if (ACCESS_FBINFO(devflags.maven_capable)) {
- err = i2c_ddc2_init(m2info);
- if (err)
+ if (ACCESS_FBINFO(devflags.dualhead)) {
+ err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1 on i2c-matroxfb");
+ if (err == -ENODEV) {
+ printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
+ } else if (err)
printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
- err = i2c_maven_init(m2info);
+ /* Register maven bus even on G450/G550 */
+ err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u on i2c-matroxfb");
if (err)
printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
}
@@ -337,10 +204,10 @@ static void i2c_matroxfb_remove(struct matrox_fb_info* minfo, void* data) {
}
static struct matroxfb_driver i2c_matroxfb = {
- LIST_HEAD_INIT(i2c_matroxfb.node),
- "i2c-matroxfb",
- i2c_matroxfb_probe,
- i2c_matroxfb_remove,
+ .node = LIST_HEAD_INIT(i2c_matroxfb.node),
+ .name = "i2c-matroxfb",
+ .probe = i2c_matroxfb_probe,
+ .remove = i2c_matroxfb_remove,
};
static int __init i2c_matroxfb_init(void) {
@@ -355,7 +222,7 @@ static void __exit i2c_matroxfb_exit(void) {
matroxfb_unregister_driver(&i2c_matroxfb);
}
-MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards");
module_init(i2c_matroxfb_init);
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
index 51aad5adb819..4dbe47514057 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/matrox/matroxfb_DAC1064.c
@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
*
- * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2001/11/29
+ * Version: 1.65 2002/08/14
*
* See matroxfb_base.c for contributors.
*
@@ -150,7 +150,7 @@ static int matroxfb_DAC1064_setfont(struct display* p, int width, int height) {
return 0;
}
-static int DAC1064_selhwcursor(WPMINFO struct display* p) {
+static int DAC1064_selhwcursor(WPMINFO2) {
ACCESS_FBINFO(dispsw.cursor) = matroxfb_DAC1064_cursor;
ACCESS_FBINFO(dispsw.set_font) = matroxfb_DAC1064_setfont;
return 0;
@@ -161,37 +161,20 @@ static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsi
unsigned int p;
DBG("DAC1064_calcclock")
+
+ /* only for devices older than G450 */
fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p);
- if (ACCESS_FBINFO(devflags.g450dac)) {
- if (fvco <= 300000) /* 276-324 */
- ;
- else if (fvco <= 400000) /* 378-438 */
- p |= 0x08;
- else if (fvco <= 550000) /* 540-567 */
- p |= 0x10;
- else if (fvco <= 690000) /* 675-695 */
- p |= 0x18;
- else if (fvco <= 800000) /* 776-803 */
- p |= 0x20;
- else if (fvco <= 891000) /* 891-891 */
- p |= 0x28;
- else if (fvco <= 940000) /* 931-945 */
- p |= 0x30;
- else /* <959 */
- p |= 0x38;
- } else {
- p = (1 << p) - 1;
- if (fvco <= 100000)
- ;
- else if (fvco <= 140000)
- p |= 0x08;
- else if (fvco <= 180000)
- p |= 0x10;
- else
- p |= 0x18;
- }
+ p = (1 << p) - 1;
+ if (fvco <= 100000)
+ ;
+ else if (fvco <= 140000)
+ p |= 0x08;
+ else if (fvco <= 180000)
+ p |= 0x10;
+ else
+ p |= 0x18;
*post = p;
}
@@ -293,31 +276,164 @@ static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
hw->MXoptionReg = mx;
}
+static void g450_set_plls(WPMINFO2) {
+ u_int32_t c2_ctl;
+ unsigned int pxc;
+ struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
+ int pixelmnp;
+ int videomnp;
+
+ c2_ctl = hw->crtc2.ctl & ~0x4007; /* Clear PLL + enable for CRTC2 */
+ c2_ctl |= 0x0001; /* Enable CRTC2 */
+ hw->DACreg[POS1064_XPWRCTRL] &= ~0x02; /* Stop VIDEO PLL */
+ pixelmnp = ACCESS_FBINFO(crtc1).mnp;
+ videomnp = ACCESS_FBINFO(crtc2).mnp;
+ if (videomnp < 0) {
+ c2_ctl &= ~0x0001; /* Disable CRTC2 */
+ hw->DACreg[POS1064_XPWRCTRL] &= ~0x10; /* Powerdown CRTC2 */
+ } else if (ACCESS_FBINFO(crtc2).pixclock == ACCESS_FBINFO(features).pll.ref_freq) {
+ c2_ctl |= 0x4002; /* Use reference directly */
+ } else if (videomnp == pixelmnp) {
+ c2_ctl |= 0x0004; /* Use pixel PLL */
+ } else {
+ if (0 == ((videomnp ^ pixelmnp) & 0xFFFFFF00)) {
+ /* PIXEL and VIDEO PLL must not use same frequency. We modify N
+ of PIXEL PLL in such case because of VIDEO PLL may be source
+ of TVO clocks, and chroma subcarrier is derived from its
+ pixel clocks */
+ pixelmnp += 0x000100;
+ }
+ c2_ctl |= 0x0006; /* Use video PLL */
+ hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
+
+ outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
+ matroxfb_g450_setpll_cond(PMINFO videomnp, M_VIDEO_PLL);
+ }
+
+ hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
+ if (pixelmnp >= 0) {
+ hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
+
+ outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
+ matroxfb_g450_setpll_cond(PMINFO pixelmnp, M_PIXEL_PLL_C);
+ }
+ if (c2_ctl != hw->crtc2.ctl) {
+ hw->crtc2.ctl = c2_ctl;
+ mga_outl(0x3C10, c2_ctl);
+ }
+
+ pxc = ACCESS_FBINFO(crtc1).pixclock;
+ if (pxc == 0 || ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC2) {
+ pxc = ACCESS_FBINFO(crtc2).pixclock;
+ }
+ if (ACCESS_FBINFO(chip) == MGA_G550) {
+ if (pxc < 45000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x00; /* 0-50 */
+ } else if (pxc < 55000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x08; /* 34-62 */
+ } else if (pxc < 70000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x10; /* 42-78 */
+ } else if (pxc < 85000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x18; /* 62-92 */
+ } else if (pxc < 100000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x20; /* 74-108 */
+ } else if (pxc < 115000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x28; /* 94-122 */
+ } else if (pxc < 125000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x30; /* 108-132 */
+ } else {
+ hw->DACreg[POS1064_XPANMODE] = 0x38; /* 120-168 */
+ }
+ } else {
+ /* G450 */
+ if (pxc < 45000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x00; /* 0-54 */
+ } else if (pxc < 65000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x08; /* 38-70 */
+ } else if (pxc < 85000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x10; /* 56-96 */
+ } else if (pxc < 105000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x18; /* 80-114 */
+ } else if (pxc < 135000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x20; /* 102-144 */
+ } else if (pxc < 160000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x28; /* 132-166 */
+ } else if (pxc < 175000) {
+ hw->DACreg[POS1064_XPANMODE] = 0x30; /* 154-182 */
+ } else {
+ hw->DACreg[POS1064_XPANMODE] = 0x38; /* 170-204 */
+ }
+ }
+}
+
void DAC1064_global_init(WPMINFO2) {
struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
- hw->DACreg[POS1064_XOUTPUTCONN] = 0x01; /* output #1 enabled */
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- if (ACCESS_FBINFO(devflags.g450dac)) {
- hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL2;
- hw->DACreg[POS1064_XOUTPUTCONN] = 0x05; /* output #1 enabled; CRTC1 connected to output #2 */
- } else {
+ if (ACCESS_FBINFO(devflags.g450dac)) {
+ hw->DACreg[POS1064_XPWRCTRL] = 0x1F; /* powerup everything */
+ hw->DACreg[POS1064_XOUTPUTCONN] = 0x00; /* disable outputs */
+ hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
+ switch (ACCESS_FBINFO(outputs[0]).src) {
+ case MATROXFB_SRC_CRTC1:
+ case MATROXFB_SRC_CRTC2:
+ hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01; /* enable output; CRTC1/2 selection is in CRTC2 ctl */
+ break;
+ case MATROXFB_SRC_NONE:
+ hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN;
+ break;
+ }
+ switch (ACCESS_FBINFO(outputs[1]).src) {
+ case MATROXFB_SRC_CRTC1:
+ hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
+ break;
+ case MATROXFB_SRC_CRTC2:
+ if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_MONITOR) {
+ hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08;
+ } else {
+ hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C;
+ }
+ break;
+ case MATROXFB_SRC_NONE:
+ hw->DACreg[POS1064_XPWRCTRL] &= ~0x01; /* Poweroff DAC2 */
+ break;
+ }
+ switch (ACCESS_FBINFO(outputs[2]).src) {
+ case MATROXFB_SRC_CRTC1:
+ hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20;
+ break;
+ case MATROXFB_SRC_CRTC2:
+ hw->DACreg[POS1064_XOUTPUTCONN] |= 0x40;
+ break;
+ case MATROXFB_SRC_NONE:
+#if 0
+ /* HELP! If we boot without DFP connected to DVI, we can
+ poweroff TMDS. But if we boot with DFP connected,
+ TMDS generated clocks are used instead of ALL pixclocks
+ available... If someone knows which register
+ handles it, please reveal this secret to me... */
+ hw->DACreg[POS1064_XPWRCTRL] &= ~0x04; /* Poweroff TMDS */
+#endif
+ break;
+ }
+ /* Now set timming related variables... */
+ g450_set_plls(PMINFO2);
+ } else {
+ if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) {
hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
- }
- } else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
- hw->DACreg[POS1064_XOUTPUTCONN] = 0x09; /* output #1 enabled; CRTC2 connected to output #2 */
- } else if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP)
- hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
- else
- hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
+ } else if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) {
+ hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
+ } else if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1)
+ hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
+ else
+ hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
- if ((ACCESS_FBINFO(output.ph) | ACCESS_FBINFO(output.sh)) & MATROXFB_OUTPUT_CONN_PRIMARY)
- hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
+ if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE)
+ hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
+ }
}
void DAC1064_global_restore(WPMINFO2) {
@@ -329,31 +445,32 @@ void DAC1064_global_restore(WPMINFO2) {
outDAC1064(PMINFO 0x20, 0x04);
outDAC1064(PMINFO 0x1F, ACCESS_FBINFO(devflags.dfp_type));
if (ACCESS_FBINFO(devflags.g450dac)) {
- outDAC1064(PMINFO M1064_XSYNCCTRL, 0xCC); /* only matrox know... */
- outDAC1064(PMINFO M1064_XPWRCTRL, 0x1F); /* powerup everything */
+ outDAC1064(PMINFO M1064_XSYNCCTRL, 0xCC);
+ outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
+ outDAC1064(PMINFO M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]);
outDAC1064(PMINFO M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
}
}
}
-static int DAC1064_init_1(WPMINFO struct my_timming* m, struct display *p) {
+static int DAC1064_init_1(WPMINFO struct my_timming* m) {
struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
DBG("DAC1064_init_1")
memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
- if (p->type == FB_TYPE_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
hw->DACreg[POS1064_XMISCCTRL] = M1064_XMISCCTRL_DAC_6BIT;
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP
| M1064_XMULCTRL_GRAPHICS_PALETIZED;
} else {
- switch (p->var.bits_per_pixel) {
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
/* case 4: not supported by MGA1064 DAC */
case 8:
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
break;
case 16:
- if (p->var.green.length == 5)
+ if (ACCESS_FBINFO(fbcon).var.green.length == 5)
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
else
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
@@ -368,22 +485,22 @@ static int DAC1064_init_1(WPMINFO struct my_timming* m, struct display *p) {
return 1; /* unsupported depth */
}
}
-
- DAC1064_global_init(PMINFO2);
hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl);
hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
hw->DACreg[POS1064_XCURADDL] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 10;
hw->DACreg[POS1064_XCURADDH] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 18;
+
+ DAC1064_global_init(PMINFO2);
return 0;
}
-static int DAC1064_init_2(WPMINFO struct my_timming* m, struct display* p) {
+static int DAC1064_init_2(WPMINFO struct my_timming* m) {
struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
DBG("DAC1064_init_2")
- if (p->var.bits_per_pixel > 16) { /* 256 entries */
+ if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 16) { /* 256 entries */
int i;
for (i = 0; i < 256; i++) {
@@ -391,8 +508,8 @@ static int DAC1064_init_2(WPMINFO struct my_timming* m, struct display* p) {
hw->DACpal[i * 3 + 1] = i;
hw->DACpal[i * 3 + 2] = i;
}
- } else if (p->var.bits_per_pixel > 8) {
- if (p->var.green.length == 5) { /* 0..31, 128..159 */
+ } else if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 8) {
+ if (ACCESS_FBINFO(fbcon).var.green.length == 5) { /* 0..31, 128..159 */
int i;
for (i = 0; i < 32; i++) {
@@ -471,13 +588,8 @@ static void DAC1064_restore_2(WPMINFO struct display* p) {
#endif
}
-static int m1064_compute(void* outdev, struct my_timming* m) {
-#define minfo ((struct matrox_fb_info*)outdev)
-#ifdef CONFIG_FB_MATROX_G450
- if (ACCESS_FBINFO(devflags.g450dac)) {
- matroxfb_g450_setclk(PMINFO m->pixclock, M_PIXEL_PLL_C);
- } else
-#endif
+static int m1064_compute(void* out, struct my_timming* m) {
+#define minfo ((struct matrox_fb_info*)out)
{
int i;
int tmout;
@@ -504,37 +616,26 @@ static int m1064_compute(void* outdev, struct my_timming* m) {
return 0;
}
-static int m1064_program(void* outdev) {
- /* nothing, hardware is set in m1064_compute */
- return 0;
-}
-
-static int m1064_start(void* outdev) {
- /* nothing */
- return 0;
-}
-
-static void m1064_incuse(void* outdev) {
- /* nothing yet; MODULE_INC_USE in future... */
-}
-
-static void m1064_decuse(void* outdev) {
- /* nothing yet; MODULE_DEC_USE in future... */
-}
+static struct matrox_altout m1064 = {
+ .name = "Primary output",
+ .compute = m1064_compute,
+};
-static int m1064_setmode(void* outdev, u_int32_t mode) {
- if (mode != MATROXFB_OUTPUT_MODE_MONITOR)
- return -EINVAL;
+static int g450_compute(void* out, struct my_timming* m) {
+#define minfo ((struct matrox_fb_info*)out)
+ if (m->mnp < 0) {
+ m->mnp = matroxfb_g450_setclk(PMINFO m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
+ if (m->mnp >= 0) {
+ m->pixclock = g450_mnp2f(PMINFO m->mnp);
+ }
+ }
+#undef minfo
return 0;
}
-static struct matrox_altout m1064 = {
- m1064_compute,
- m1064_program,
- m1064_start,
- m1064_incuse,
- m1064_decuse,
- m1064_setmode
+static struct matrox_altout g450out = {
+ .name = "Primary output",
+ .compute = g450_compute,
};
#endif /* NEED_DAC1064 */
@@ -545,7 +646,7 @@ static int MGA1064_init(WPMINFO struct my_timming* m, struct display* p) {
DBG("MGA1064_init")
- if (DAC1064_init_1(PMINFO m, p)) return 1;
+ if (DAC1064_init_1(PMINFO m)) return 1;
if (matroxfb_vgaHWinit(PMINFO m, p)) return 1;
hw->MiscOutReg = 0xCB;
@@ -556,7 +657,7 @@ static int MGA1064_init(WPMINFO struct my_timming* m, struct display* p) {
if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
hw->CRTCEXT[3] |= 0x40;
- if (DAC1064_init_2(PMINFO m, p)) return 1;
+ if (DAC1064_init_2(PMINFO m)) return 1;
return 0;
}
#endif
@@ -567,7 +668,7 @@ static int MGAG100_init(WPMINFO struct my_timming* m, struct display* p) {
DBG("MGAG100_init")
- if (DAC1064_init_1(PMINFO m, p)) return 1;
+ if (DAC1064_init_1(PMINFO m)) return 1;
hw->MXoptionReg &= ~0x2000;
if (matroxfb_vgaHWinit(PMINFO m, p)) return 1;
@@ -579,7 +680,7 @@ static int MGAG100_init(WPMINFO struct my_timming* m, struct display* p) {
if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
hw->CRTCEXT[3] |= 0x40;
- if (DAC1064_init_2(PMINFO m, p)) return 1;
+ if (DAC1064_init_2(PMINFO m)) return 1;
return 0;
}
#endif /* G100 */
@@ -680,7 +781,10 @@ static int MGA1064_preinit(WPMINFO2) {
ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
- ACCESS_FBINFO(primout) = &m1064;
+ ACCESS_FBINFO(outputs[0]).output = &m1064;
+ ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
+ ACCESS_FBINFO(outputs[0]).data = MINFO;
+ ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
if (ACCESS_FBINFO(devflags.noinit))
return 0; /* do not modify settings */
@@ -726,8 +830,13 @@ static void g450_mclk_init(WPMINFO2) {
((ACCESS_FBINFO(values).reg.opt3 & 0x300000) == 0x300000)) {
matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.video), M_VIDEO_PLL);
} else {
- /* slow down video clocks... */
- matroxfb_g450_setclk(PMINFO 0, M_VIDEO_PLL);
+ unsigned long flags;
+ unsigned int pwr;
+
+ matroxfb_DAC_lock_irqsave(flags);
+ pwr = inDAC1064(PMINFO M1064_XPWRCTRL) & ~0x02;
+ outDAC1064(PMINFO M1064_XPWRCTRL, pwr);
+ matroxfb_DAC_unlock_irqrestore(flags);
}
matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL);
@@ -864,7 +973,14 @@ static int MGAG100_preinit(WPMINFO2) {
ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100
? ACCESS_FBINFO(devflags.sgram) : 1;
- ACCESS_FBINFO(primout) = &m1064;
+ if (ACCESS_FBINFO(devflags.g450dac)) {
+ ACCESS_FBINFO(outputs[0]).output = &g450out;
+ } else {
+ ACCESS_FBINFO(outputs[0]).output = &m1064;
+ }
+ ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
+ ACCESS_FBINFO(outputs[0]).data = MINFO;
+ ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
if (ACCESS_FBINFO(devflags.g450dac)) {
/* we must do this always, BIOS does not do it for us
@@ -895,8 +1011,7 @@ static int MGAG100_preinit(WPMINFO2) {
hw->MXoptionReg |= 0x1080;
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
- mga_outl(M_CTLWTST, 0x00000300);
- /* mga_outl(M_CTLWTST, 0x03258A31); */
+ mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
udelay(100);
mga_outb(0x1C05, 0x00);
mga_outb(0x1C05, 0x80);
@@ -947,17 +1062,18 @@ static int MGAG100_preinit(WPMINFO2) {
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50);
if (ACCESS_FBINFO(devflags.memtype) == -1)
- ACCESS_FBINFO(devflags.memtype) = 0;
- hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10;
+ hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00;
+ else
+ hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10;
if (ACCESS_FBINFO(devflags.sgram))
hw->MXoptionReg |= 0x4000;
- mga_outl(M_CTLWTST, 0x042450A1);
- mga_outl(M_MEMRDBK, 0x00000108);
+ mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
+ mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
udelay(200);
mga_outl(M_MACCESS, 0x00000000);
mga_outl(M_MACCESS, 0x00008000);
udelay(100);
- mga_outl(M_MEMRDBK, 0x00000108);
+ mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk);
hw->MXoptionReg |= 0x00040020;
}
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h
index 6136fd33a14b..6fb532aefb43 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.h
+++ b/drivers/video/matrox/matroxfb_DAC1064.h
@@ -146,6 +146,8 @@ void DAC1064_global_restore(WPMINFO2);
#define M1064_XPWRCTRL 0xA0
+#define M1064_XPANMODE 0xA2
+
enum POS1064 {
POS1064_XCURADDL=0, POS1064_XCURADDH, POS1064_XCURCTRL,
POS1064_XCURCOL0RED, POS1064_XCURCOL0GREEN, POS1064_XCURCOL0BLUE,
@@ -156,7 +158,7 @@ enum POS1064 {
POS1064_XGENIOCTRL, POS1064_XGENIODATA, POS1064_XZOOMCTRL, POS1064_XSENSETEST,
POS1064_XCRCBITSEL,
POS1064_XCOLKEYMASKL, POS1064_XCOLKEYMASKH, POS1064_XCOLKEYL, POS1064_XCOLKEYH,
- POS1064_XOUTPUTCONN };
+ POS1064_XOUTPUTCONN, POS1064_XPANMODE, POS1064_XPWRCTRL };
#endif /* __MATROXFB_DAC1064_H__ */
diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c
index 57b37600a3cb..92d53ad93595 100644
--- a/drivers/video/matrox/matroxfb_Ti3026.c
+++ b/drivers/video/matrox/matroxfb_Ti3026.c
@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
*
- * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2000/11/29
+ * Version: 1.65 2002/08/14
*
* MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
*
@@ -84,6 +84,7 @@
#include "matroxfb_Ti3026.h"
#include "matroxfb_misc.h"
#include "matroxfb_accel.h"
+#include <linux/matroxfb.h>
#ifdef CONFIG_FB_MATROX_MILLENIUM
#define outTi3026 matroxfb_DAC_out
@@ -401,7 +402,7 @@ static int matroxfb_ti3026_setfont(struct display* p, int width, int height) {
return 0;
}
-static int matroxfb_ti3026_selhwcursor(WPMINFO struct display* p) {
+static int matroxfb_ti3026_selhwcursor(WPMINFO2) {
ACCESS_FBINFO(dispsw.cursor) = matroxfb_ti3026_cursor;
ACCESS_FBINFO(dispsw.set_font) = matroxfb_ti3026_setfont;
return 0;
@@ -433,7 +434,7 @@ static int Ti3026_setpclk(WPMINFO int clk, struct display* p) {
hw->DACclk[1] = pixfeed;
hw->DACclk[2] = pixpost | 0xB0;
- if (p->type == FB_TYPE_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
hw->DACreg[POS3026_XMEMPLLCTRL] = TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_PIXPLL;
hw->DACclk[3] = 0xFD;
hw->DACclk[4] = 0x3D;
@@ -501,7 +502,7 @@ static int Ti3026_init(WPMINFO struct my_timming* m, struct display* p) {
DBG("Ti3026_init")
memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
- if (p->type == FB_TYPE_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1;
hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
hw->DACreg[POS3026_XMUXCTRL] = TVP3026_XMUXCTRL_VGA;
@@ -568,7 +569,7 @@ static int Ti3026_init(WPMINFO struct my_timming* m, struct display* p) {
/* set interleaving */
hw->MXoptionReg &= ~0x00001000;
- if ((p->type != FB_TYPE_TEXT) && isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
+ if ((ACCESS_FBINFO(fbcon).fix.type != FB_TYPE_TEXT) && isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
/* set DAC */
Ti3026_setpclk(PMINFO m->pixclock, p);
@@ -811,6 +812,10 @@ static void Ti3026_reset(WPMINFO2) {
ti3026_ramdac_init(PMINFO2);
}
+static struct matrox_altout ti3026_output = {
+ .name = "Primary output",
+};
+
static int Ti3026_preinit(WPMINFO2) {
static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960,
1024, 1152, 1280, 1600, 1664, 1920,
@@ -829,6 +834,11 @@ static int Ti3026_preinit(WPMINFO2) {
ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1;
ACCESS_FBINFO(cursor.timer.function) = matroxfb_ti3026_flashcursor;
+ ACCESS_FBINFO(outputs[0]).data = MINFO;
+ ACCESS_FBINFO(outputs[0]).output = &ti3026_output;
+ ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
+ ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+
if (ACCESS_FBINFO(devflags.noinit))
return 0;
/* preserve VGA I/O, BIOS and PPC */
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index 817e45cfa078..cfcb8eb3df68 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -2,9 +2,9 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
*
- * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
- * Version: 1.51 2001/06/18
+ * Version: 1.65 2002/08/14
*
* MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
*
@@ -85,21 +85,21 @@
#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
-void matrox_cfbX_init(WPMINFO struct display* p) {
+void matrox_cfbX_init(WPMINFO2) {
u_int32_t maccess;
u_int32_t mpitch;
u_int32_t mopmode;
DBG("matrox_cfbX_init")
- mpitch = p->var.xres_virtual;
+ mpitch = ACCESS_FBINFO(fbcon).var.xres_virtual;
- if (p->type == FB_TYPE_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
maccess = 0x00000000;
mpitch = (mpitch >> 4) | 0x8000; /* set something */
mopmode = M_OPMODE_8BPP;
} else {
- switch (p->var.bits_per_pixel) {
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
case 4: maccess = 0x00000000; /* accelerate as 8bpp video */
mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
mopmode = M_OPMODE_4BPP;
@@ -107,7 +107,7 @@ void matrox_cfbX_init(WPMINFO struct display* p) {
case 8: maccess = 0x00000000;
mopmode = M_OPMODE_8BPP;
break;
- case 16: if (p->var.green.length == 5)
+ case 16: if (ACCESS_FBINFO(fbcon).var.green.length == 5)
maccess = 0xC0000001;
else
maccess = 0x40000001;
@@ -816,7 +816,7 @@ static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, i
static void matrox_text_setup(struct display* p) {
MINFO_FROM_DISP(p);
- p->next_line = p->line_length ? p->line_length : ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
+ p->next_line = ACCESS_FBINFO(fbcon).fix.line_length ? ACCESS_FBINFO(fbcon).fix.line_length : ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
p->next_plane = 0;
}
@@ -1040,7 +1040,7 @@ static int matrox_text_setfont(struct display* p, int width, int height) {
MINFO_FROM_DISP(p);
matrox_text_round(PMINFO &p->var, p);
- p->next_line = p->line_length = ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
+ p->next_line = ACCESS_FBINFO(fbcon).fix.line_length = ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
if (p->conp)
matrox_text_createcursor(PMINFO p);
@@ -1144,11 +1144,11 @@ void initMatrox(WPMINFO struct display* p) {
if (p->dispsw && p->conp)
fb_con.con_cursor(p->conp, CM_ERASE);
p->dispsw_data = NULL;
- if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
- if (p->type == FB_TYPE_TEXT) {
+ if ((ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
swtmp = &matroxfb_text;
} else {
- switch (p->var.bits_per_pixel) {
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4:
swtmp = &fbcon_cfb4;
@@ -1183,10 +1183,10 @@ void initMatrox(WPMINFO struct display* p) {
}
}
dprintk(KERN_INFO "matroxfb: acceleration disabled\n");
- } else if (p->type == FB_TYPE_TEXT) {
+ } else if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
swtmp = &matroxfb_text;
} else {
- switch (p->var.bits_per_pixel) {
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4:
swtmp = &matroxfb_cfb4;
@@ -1222,8 +1222,8 @@ void initMatrox(WPMINFO struct display* p) {
}
memcpy(&ACCESS_FBINFO(dispsw), swtmp, sizeof(ACCESS_FBINFO(dispsw)));
p->dispsw = &ACCESS_FBINFO(dispsw);
- if ((p->type != FB_TYPE_TEXT) && ACCESS_FBINFO(devflags.hwcursor)) {
- ACCESS_FBINFO(hw_switch)->selhwcursor(PMINFO p);
+ if ((ACCESS_FBINFO(fbcon).fix.type != FB_TYPE_TEXT) && ACCESS_FBINFO(devflags.hwcursor)) {
+ ACCESS_FBINFO(hw_switch)->selhwcursor(PMINFO2);
}
}
@@ -1233,7 +1233,7 @@ void matrox_init_putc(WPMINFO struct display* p, void (*dac_createcursor)(WPMINF
int i;
if (p && p->conp) {
- if (p->type == FB_TYPE_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
matrox_text_createcursor(PMINFO p);
matrox_text_loadfont(PMINFO p);
i = 0;
diff --git a/drivers/video/matrox/matroxfb_accel.h b/drivers/video/matrox/matroxfb_accel.h
index ab757c8e5f57..15e5a94b1194 100644
--- a/drivers/video/matrox/matroxfb_accel.h
+++ b/drivers/video/matrox/matroxfb_accel.h
@@ -4,7 +4,7 @@
#include "matroxfb_base.h"
void matrox_init_putc(WPMINFO struct display* p, void (*)(WPMINFO struct display *p));
-void matrox_cfbX_init(WPMINFO struct display* p);
+void matrox_cfbX_init(WPMINFO2);
void matrox_text_round(CPMINFO struct fb_var_screeninfo* var, struct display* p);
void initMatrox(WPMINFO struct display* p);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 9912fa946907..477039b3fb8b 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
*
- * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2001/11/29
+ * Version: 1.65 2002/08/14
*
* MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
*
@@ -77,6 +77,15 @@
* "Uns Lider" <unslider@miranda.org>
* G100 PLNWT fixes
*
+ * "Denis Zaitsev" <zzz@cd-club.ru>
+ * Fixes
+ *
+ * "Mike Pieper" <mike@pieper-family.de>
+ * TVOut enhandcements, V4L2 control interface.
+ *
+ * "Diego Biurrun" <diego@biurrun.de>
+ * DFP testing
+ *
* (following author is not in any relation with this code, but his code
* is included in this driver)
*
@@ -100,6 +109,7 @@
#include "matroxfb_Ti3026.h"
#include "matroxfb_maven.h"
#include "matroxfb_crtc2.h"
+#include "matroxfb_g450.h"
#include <linux/matroxfb.h>
#include <asm/uaccess.h>
@@ -169,11 +179,13 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
if (ACCESS_FBINFO(dead))
return;
+ ACCESS_FBINFO(fbcon).var.xoffset = var->xoffset;
+ ACCESS_FBINFO(fbcon).var.yoffset = var->yoffset;
disp = ACCESS_FBINFO(currcon_display);
- if (disp->type == FB_TYPE_TEXT) {
- pos = var->yoffset / fontheight(disp) * disp->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(disp)?fontwidth(disp):8);
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
+ pos = ACCESS_FBINFO(fbcon).var.yoffset / fontheight(disp) * disp->next_line / ACCESS_FBINFO(devflags.textstep) + ACCESS_FBINFO(fbcon).var.xoffset / (fontwidth(disp)?fontwidth(disp):8);
} else {
- pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+ pos = (ACCESS_FBINFO(fbcon).var.yoffset * ACCESS_FBINFO(fbcon).var.xres_virtual + ACCESS_FBINFO(fbcon).var.xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
pos += ACCESS_FBINFO(curr.ydstorg.chunks);
}
p0 = ACCESS_FBINFO(hw).CRTC[0x0D] = pos & 0xFF;
@@ -212,6 +224,7 @@ static void matroxfb_remove(WPMINFO int dummy) {
}
matroxfb_unregister_device(MINFO);
unregister_framebuffer(&ACCESS_FBINFO(fbcon));
+ matroxfb_g450_shutdown(PMINFO2);
del_timer_sync(&ACCESS_FBINFO(cursor.timer));
#ifdef CONFIG_MTRR
if (ACCESS_FBINFO(mtrr.vram_valid))
@@ -233,7 +246,7 @@ static void matroxfb_remove(WPMINFO int dummy) {
static int matroxfb_open(struct fb_info *info, int user)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
DBG_LOOP("matroxfb_open")
if (ACCESS_FBINFO(dead)) {
@@ -246,7 +259,7 @@ static int matroxfb_open(struct fb_info *info, int user)
static int matroxfb_release(struct fb_info *info, int user)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
DBG_LOOP("matroxfb_release")
if (!(--ACCESS_FBINFO(usecount)) && ACCESS_FBINFO(dead)) {
@@ -258,7 +271,7 @@ static int matroxfb_release(struct fb_info *info, int user)
static int matroxfb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info* info) {
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
DBG("matroxfb_pan_display")
@@ -284,7 +297,7 @@ static int matroxfb_pan_display(struct fb_var_screeninfo *var, int con,
static int matroxfb_updatevar(int con, struct fb_info *info)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
DBG("matroxfb_updatevar");
matrox_pan_var(PMINFO &fb_display[con].var);
@@ -404,12 +417,43 @@ static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
}
static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screeninfo *var, int *visual, int *video_cmap_len, unsigned int* ydstorg) {
+ struct RGBT {
+ unsigned char bpp;
+ struct {
+ unsigned char offset,
+ length;
+ } red,
+ green,
+ blue,
+ transp;
+ signed char visual;
+ };
+ static const struct RGBT table[]= {
+#if defined FBCON_HAS_VGATEXT
+ { 0,{ 0,6},{0,6},{0,6},{ 0,0},MX_VISUAL_PSEUDOCOLOR},
+#endif
+#if defined FBCON_HAS_CFB4 || defined FBCON_HAS_CFB8
+ { 8,{ 0,8},{0,8},{0,8},{ 0,0},MX_VISUAL_PSEUDOCOLOR},
+#endif
+#if defined FBCON_HAS_CFB16
+ {15,{10,5},{5,5},{0,5},{15,1},MX_VISUAL_DIRECTCOLOR},
+ {16,{11,5},{5,6},{0,5},{ 0,0},MX_VISUAL_DIRECTCOLOR},
+#endif
+#if defined FBCON_HAS_CFB24
+ {24,{16,8},{8,8},{0,8},{ 0,0},MX_VISUAL_DIRECTCOLOR},
+#endif
+#if defined FBCON_HAS_CFB32
+ {32,{16,8},{8,8},{0,8},{24,8},MX_VISUAL_DIRECTCOLOR}
+#endif
+ };
+ struct RGBT const *rgbt;
+ unsigned int bpp = var->bits_per_pixel;
unsigned int vramlen;
unsigned int memlen;
DBG("matroxfb_decode_var")
- switch (var->bits_per_pixel) {
+ switch (bpp) {
#ifdef FBCON_HAS_VGATEXT
case 0: if (!ACCESS_FBINFO(capable.text)) return -EINVAL;
break;
@@ -438,22 +482,22 @@ static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screenin
var->yres_virtual = var->yres;
if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres;
- if (var->bits_per_pixel) {
- var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel);
- memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+ if (bpp) {
+ var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, bpp);
+ memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
if (memlen > vramlen) {
- var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel);
- memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+ var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp);
+ memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
}
/* There is hardware bug that no line can cross 4MB boundary */
/* give up for CFB24, it is impossible to easy workaround it */
/* for other try to do something */
if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000)) {
- if (var->bits_per_pixel == 24) {
+ if (bpp == 24) {
/* sorry */
} else {
unsigned int linelen;
- unsigned int m1 = linelen = var->xres_virtual * var->bits_per_pixel / 8;
+ unsigned int m1 = linelen = var->xres_virtual * bpp / 8;
unsigned int m2 = PAGE_SIZE; /* or 128 if you do not need PAGE ALIGNED address */
unsigned int max_yres;
@@ -497,88 +541,27 @@ static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screenin
if (var->yoffset + var->yres > var->yres_virtual)
var->yoffset = var->yres_virtual - var->yres;
- if (var->bits_per_pixel == 0) {
- var->red.offset = 0;
- var->red.length = 6;
- var->green.offset = 0;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 6;
- var->transp.offset = 0;
- var->transp.length = 0;
- *visual = MX_VISUAL_PSEUDOCOLOR;
- } else if (var->bits_per_pixel == 4) {
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 0;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- *visual = MX_VISUAL_PSEUDOCOLOR;
- } else if (var->bits_per_pixel <= 8) {
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 0;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- *visual = MX_VISUAL_PSEUDOCOLOR;
- } else {
- if (var->bits_per_pixel <= 16) {
- if (var->green.length == 5) {
- var->red.offset = 10;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 5;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 15;
- var->transp.length = 1;
- } else {
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- }
- } else if (var->bits_per_pixel <= 24) {
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- } else {
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- }
- dprintk("matroxfb: truecolor: "
- "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
- var->transp.length,
- var->red.length,
- var->green.length,
- var->blue.length,
- var->transp.offset,
- var->red.offset,
- var->green.offset,
- var->blue.offset);
- *visual = MX_VISUAL_DIRECTCOLOR;
+ if (bpp == 16 && var->green.length == 5) {
+ bpp--; /* an artifical value - 15 */
}
+
+ for (rgbt = table; rgbt->bpp < bpp; rgbt++);
+#define SETCLR(clr)\
+ var->clr.offset = rgbt->clr.offset;\
+ var->clr.length = rgbt->clr.length
+ SETCLR(red);
+ SETCLR(green);
+ SETCLR(blue);
+ SETCLR(transp);
+#undef SETCLR
+ *visual = rgbt->visual;
+
+ if (bpp > 8)
+ dprintk("matroxfb: truecolor: "
+ "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+ var->transp.length, var->red.length, var->green.length, var->blue.length,
+ var->transp.offset, var->red.offset, var->green.offset, var->blue.offset);
+
*video_cmap_len = matroxfb_get_cmap_len(var);
dprintk(KERN_INFO "requested %d*%d/%dbpp (%d*%d)\n", var->xres, var->yres, var->bits_per_pixel,
var->xres_virtual, var->yres_virtual);
@@ -589,9 +572,8 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *fb_info)
{
- struct display* p;
#ifdef CONFIG_FB_MATROX_MULTIHEAD
- struct matrox_fb_info* minfo = (struct matrox_fb_info*)fb_info;
+ struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon);
#endif
DBG("matroxfb_setcolreg")
@@ -611,18 +593,17 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
ACCESS_FBINFO(palette[regno].blue) = blue;
ACCESS_FBINFO(palette[regno].transp) = transp;
- p = ACCESS_FBINFO(currcon_display);
- if (p->var.grayscale) {
+ if (ACCESS_FBINFO(fbcon).var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
- red = CNVT_TOHW(red, p->var.red.length);
- green = CNVT_TOHW(green, p->var.green.length);
- blue = CNVT_TOHW(blue, p->var.blue.length);
- transp = CNVT_TOHW(transp, p->var.transp.length);
+ red = CNVT_TOHW(red, ACCESS_FBINFO(fbcon).var.red.length);
+ green = CNVT_TOHW(green, ACCESS_FBINFO(fbcon).var.green.length);
+ blue = CNVT_TOHW(blue, ACCESS_FBINFO(fbcon).var.blue.length);
+ transp = CNVT_TOHW(transp, ACCESS_FBINFO(fbcon).var.transp.length);
- switch (p->var.bits_per_pixel) {
+ switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_VGATEXT)
#ifdef FBCON_HAS_VGATEXT
case 0:
@@ -642,87 +623,54 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
#ifdef FBCON_HAS_CFB16
case 16:
ACCESS_FBINFO(cmap.cfb16[regno]) =
- (red << p->var.red.offset) |
- (green << p->var.green.offset) |
- (blue << p->var.blue.offset) |
- (transp << p->var.transp.offset); /* for 1:5:5:5 */
+ (red << ACCESS_FBINFO(fbcon).var.red.offset) |
+ (green << ACCESS_FBINFO(fbcon).var.green.offset) |
+ (blue << ACCESS_FBINFO(fbcon).var.blue.offset) |
+ (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* for 1:5:5:5 */
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
ACCESS_FBINFO(cmap.cfb24[regno]) =
- (red << p->var.red.offset) |
- (green << p->var.green.offset) |
- (blue << p->var.blue.offset);
+ (red << ACCESS_FBINFO(fbcon).var.red.offset) |
+ (green << ACCESS_FBINFO(fbcon).var.green.offset) |
+ (blue << ACCESS_FBINFO(fbcon).var.blue.offset);
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
ACCESS_FBINFO(cmap.cfb32[regno]) =
- (red << p->var.red.offset) |
- (green << p->var.green.offset) |
- (blue << p->var.blue.offset) |
- (transp << p->var.transp.offset); /* 8:8:8:8 */
+ (red << ACCESS_FBINFO(fbcon).var.red.offset) |
+ (green << ACCESS_FBINFO(fbcon).var.green.offset) |
+ (blue << ACCESS_FBINFO(fbcon).var.blue.offset) |
+ (transp << ACCESS_FBINFO(fbcon).var.transp.offset); /* 8:8:8:8 */
break;
#endif
}
return 0;
}
-static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info)
+static void matroxfb_update_fix(WPMINFO2)
{
- struct display* p;
+ struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix;
DBG("matroxfb_get_fix")
-#define minfo ((struct matrox_fb_info*)info)
-
- if (ACCESS_FBINFO(dead)) {
- return -ENXIO;
- }
-
- if (con >= 0)
- p = fb_display + con;
- else
- p = ACCESS_FBINFO(fbcon.disp);
-
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id,"MATROX");
fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes);
- fix->type = p->type;
- fix->type_aux = p->type_aux;
- fix->visual = p->visual;
- fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
+ fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
fix->ypanstep = 1;
fix->ywrapstep = 0;
- fix->line_length = p->line_length;
fix->mmio_start = ACCESS_FBINFO(mmio.base);
fix->mmio_len = ACCESS_FBINFO(mmio.len);
fix->accel = ACCESS_FBINFO(devflags.accelerator);
- return 0;
-#undef minfo
-}
-
-static int matroxfb_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
-#define minfo ((struct matrox_fb_info*)info)
- DBG("matroxfb_get_var")
-
- if(con < 0)
- *var=ACCESS_FBINFO(fbcon.disp)->var;
- else
- *var=fb_display[con].var;
- return 0;
-#undef minfo
}
static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
int err;
int visual;
int cmap_len;
@@ -763,17 +711,19 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
display->var = *var;
/* cmap */
ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)) + ydstorg;
- display->visual = visual;
- display->ypanstep = 1;
- display->ywrapstep = 0;
- if (var->bits_per_pixel) {
- display->type = FB_TYPE_PACKED_PIXELS;
- display->type_aux = 0;
- display->next_line = display->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
- } else {
- display->type = FB_TYPE_TEXT;
- display->type_aux = ACCESS_FBINFO(devflags.text_type_aux);
- display->next_line = display->line_length = (var->xres_virtual / (fontwidth(display)?fontwidth(display):8)) * ACCESS_FBINFO(devflags.textstep);
+ if (display == ACCESS_FBINFO(currcon_display)) {
+ ACCESS_FBINFO(fbcon).var = *var;
+ matroxfb_update_fix(PMINFO2);
+ ACCESS_FBINFO(fbcon).fix.visual = visual;
+ if (var->bits_per_pixel) {
+ ACCESS_FBINFO(fbcon).fix.type = FB_TYPE_PACKED_PIXELS;
+ ACCESS_FBINFO(fbcon).fix.type_aux = 0;
+ display->next_line = ACCESS_FBINFO(fbcon).fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+ } else {
+ ACCESS_FBINFO(fbcon).fix.type = FB_TYPE_TEXT;
+ ACCESS_FBINFO(fbcon).fix.type_aux = ACCESS_FBINFO(devflags.text_type_aux);
+ display->next_line = ACCESS_FBINFO(fbcon).fix.line_length = (var->xres_virtual / (fontwidth(display)?fontwidth(display):8)) * ACCESS_FBINFO(devflags.textstep);
+ }
}
display->can_soft_blank = 1;
display->inverse = ACCESS_FBINFO(devflags.inverse);
@@ -788,7 +738,7 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
unsigned int pos;
ACCESS_FBINFO(curr.cmap_len) = cmap_len;
- if (display->type == FB_TYPE_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
/* textmode must be in first megabyte, so no ydstorg allowed */
ACCESS_FBINFO(curr.ydstorg.bytes) = 0;
ACCESS_FBINFO(curr.ydstorg.chunks) = 0;
@@ -818,8 +768,10 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
{ struct my_timming mt;
struct matrox_hw_state* hw;
+ int out;
matroxfb_var2my(var, &mt);
+ mt.crtc = MATROXFB_SRC_CRTC1;
/* CRTC1 delays */
switch (var->bits_per_pixel) {
case 0: mt.delay = 31 + 0; break;
@@ -834,8 +786,18 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
del_timer_sync(&ACCESS_FBINFO(cursor.timer));
ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ down_read(&ACCESS_FBINFO(altout).lock);
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 &&
+ ACCESS_FBINFO(outputs[out]).output->compute) {
+ ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt);
+ }
+ }
+ up_read(&ACCESS_FBINFO(altout).lock);
+ ACCESS_FBINFO(crtc1).pixclock = mt.pixclock;
+ ACCESS_FBINFO(crtc1).mnp = mt.mnp;
ACCESS_FBINFO(hw_switch->init(PMINFO &mt, display));
- if (display->type == FB_TYPE_TEXT) {
+ if (ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT) {
if (fontheight(display))
pos = var->yoffset / fontheight(display) * display->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(display)?fontwidth(display):8);
else
@@ -849,39 +811,23 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
hw->CRTCEXT[8] = pos >> 21;
- if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) {
- if (ACCESS_FBINFO(primout))
- ACCESS_FBINFO(primout)->compute(MINFO, &mt);
- }
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output))
- ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt);
- up_read(&ACCESS_FBINFO(altout.lock));
- }
ACCESS_FBINFO(hw_switch->restore(PMINFO display));
- if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) {
- if (ACCESS_FBINFO(primout))
- ACCESS_FBINFO(primout)->program(MINFO);
- }
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output))
- ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device));
- up_read(&ACCESS_FBINFO(altout.lock));
+ down_read(&ACCESS_FBINFO(altout).lock);
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 &&
+ ACCESS_FBINFO(outputs[out]).output->program) {
+ ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data);
+ }
}
ACCESS_FBINFO(cursor.redraw) = 1;
- if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) {
- if (ACCESS_FBINFO(primout))
- ACCESS_FBINFO(primout)->start(MINFO);
- }
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output))
- ACCESS_FBINFO(altout.output)->start(ACCESS_FBINFO(altout.device));
- up_read(&ACCESS_FBINFO(altout.lock));
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 &&
+ ACCESS_FBINFO(outputs[out]).output->start) {
+ ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data);
+ }
}
- matrox_cfbX_init(PMINFO display);
+ up_read(&ACCESS_FBINFO(altout).lock);
+ matrox_cfbX_init(PMINFO2);
my_install_cmap(PMINFO2);
}
}
@@ -896,7 +842,7 @@ static int matrox_getcolreg(unsigned regno, unsigned *red, unsigned *green,
DBG("matrox_getcolreg")
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
/*
* Read a single color register and split it into colors/transparent.
* Return != 0 for invalid regno.
@@ -916,7 +862,7 @@ static int matrox_getcolreg(unsigned regno, unsigned *red, unsigned *green,
static int matroxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
struct display* dsp = (con < 0) ? ACCESS_FBINFO(fbcon.disp)
: fb_display + con;
@@ -942,7 +888,7 @@ static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
{
unsigned int cmap_len;
struct display* dsp = (con < 0) ? info->disp : (fb_display + con);
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
DBG("matroxfb_set_cmap")
@@ -982,18 +928,22 @@ static int matroxfb_get_vblank(CPMINFO struct fb_vblank *vblank)
vblank->flags |= FB_VBLANK_HBLANKING;
if (sts1 & 8)
vblank->flags |= FB_VBLANK_VSYNCING;
- if (vblank->vcount >= ACCESS_FBINFO(currcon_display)->var.yres)
+ if (vblank->vcount >= ACCESS_FBINFO(fbcon).var.yres)
vblank->flags |= FB_VBLANK_VBLANKING;
vblank->hcount = 0;
vblank->count = 0;
return 0;
}
+static struct matrox_altout panellink_output = {
+ .name = "Panellink output",
+};
+
static int matroxfb_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg, int con,
struct fb_info *info)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
DBG("matroxfb_ioctl")
if (ACCESS_FBINFO(dead)) {
@@ -1016,80 +966,74 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
case MATROXFB_SET_OUTPUT_MODE:
{
struct matroxioc_output_mode mom;
+ struct matrox_altout *oproc;
int val;
if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
return -EFAULT;
- if (mom.output >= sizeof(u_int32_t))
- return -EINVAL;
- switch (mom.output) {
- case MATROXFB_OUTPUT_PRIMARY:
- if (mom.mode != MATROXFB_OUTPUT_MODE_MONITOR)
- return -EINVAL;
- /* mode did not change... */
- return 0;
- case MATROXFB_OUTPUT_SECONDARY:
+ if (mom.output >= MATROXFB_MAX_OUTPUTS)
+ return -ENXIO;
+ down_read(&ACCESS_FBINFO(altout.lock));
+ oproc = ACCESS_FBINFO(outputs[mom.output]).output;
+ if (!oproc) {
+ val = -ENXIO;
+ } else if (!oproc->verifymode) {
+ if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) {
+ val = 0;
+ } else {
val = -EINVAL;
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.device))
- val = ACCESS_FBINFO(altout.output)->setmode(ACCESS_FBINFO(altout.device), mom.mode);
- up_read(&ACCESS_FBINFO(altout.lock));
- if (val != 1)
- return val;
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY)
- matroxfb_switch(ACCESS_FBINFO(fbcon.currcon), info);
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
+ }
+ } else {
+ val = oproc->verifymode(ACCESS_FBINFO(outputs[mom.output]).data, mom.mode);
+ }
+ if (!val) {
+ if (ACCESS_FBINFO(outputs[mom.output]).mode != mom.mode) {
+ ACCESS_FBINFO(outputs[mom.output]).mode = mom.mode;
+ val = 1;
+ }
+ }
+ up_read(&ACCESS_FBINFO(altout.lock));
+ if (val != 1)
+ return val;
+ switch (ACCESS_FBINFO(outputs[mom.output]).src) {
+ case MATROXFB_SRC_CRTC1:
+ matroxfb_switch(ACCESS_FBINFO(fbcon.currcon), info);
+ break;
+ case MATROXFB_SRC_CRTC2:
+ {
struct matroxfb_dh_fb_info* crtc2;
down_read(&ACCESS_FBINFO(crtc2.lock));
- crtc2 = (struct matroxfb_dh_fb_info*)(ACCESS_FBINFO(crtc2.info));
+ crtc2 = ACCESS_FBINFO(crtc2.info);
if (crtc2)
- crtc2->fbcon.switch_con(crtc2->currcon, &crtc2->fbcon);
+ crtc2->fbcon.switch_con(crtc2->fbcon.currcon, &crtc2->fbcon);
up_read(&ACCESS_FBINFO(crtc2.lock));
}
- return 0;
- case MATROXFB_OUTPUT_DFP:
- if (!(ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_DFP))
- return -ENXIO;
- if (mom.mode!= MATROXFB_OUTPUT_MODE_MONITOR)
- return -EINVAL;
- /* mode did not change... */
- return 0;
- default:
- return -EINVAL;
+ break;
}
return 0;
}
case MATROXFB_GET_OUTPUT_MODE:
{
struct matroxioc_output_mode mom;
+ struct matrox_altout *oproc;
int val;
if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
return -EFAULT;
- if (mom.output >= sizeof(u_int32_t))
- return -EINVAL;
- switch (mom.output) {
- case MATROXFB_OUTPUT_PRIMARY:
- mom.mode = MATROXFB_OUTPUT_MODE_MONITOR;
- break;
- case MATROXFB_OUTPUT_SECONDARY:
- val = -EINVAL;
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.device))
- val = ACCESS_FBINFO(altout.output)->getmode(ACCESS_FBINFO(altout.device), &mom.mode);
- up_read(&ACCESS_FBINFO(altout.lock));
- if (val)
- return val;
- break;
- case MATROXFB_OUTPUT_DFP:
- if (!(ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_DFP))
- return -ENXIO;
- mom.mode = MATROXFB_OUTPUT_MODE_MONITOR;
- break;
- default:
- return -EINVAL;
+ if (mom.output >= MATROXFB_MAX_OUTPUTS)
+ return -ENXIO;
+ down_read(&ACCESS_FBINFO(altout.lock));
+ oproc = ACCESS_FBINFO(outputs[mom.output]).output;
+ if (!oproc) {
+ val = -ENXIO;
+ } else {
+ mom.mode = ACCESS_FBINFO(outputs[mom.output]).mode;
+ val = 0;
}
+ up_read(&ACCESS_FBINFO(altout.lock));
+ if (val)
+ return val;
if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom)))
return -EFAULT;
return 0;
@@ -1097,52 +1041,109 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
case MATROXFB_SET_OUTPUT_CONNECTION:
{
u_int32_t tmp;
+ int i;
+ int changes;
if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp)))
return -EFAULT;
- if (tmp & ~ACCESS_FBINFO(output.all))
- return -EINVAL;
- if (tmp & ACCESS_FBINFO(output.sh))
- return -EINVAL;
- if (tmp & MATROXFB_OUTPUT_CONN_DFP) {
- if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY)
- return -EINVAL;
- if (ACCESS_FBINFO(output.sh))
- return -EINVAL;
+ for (i = 0; i < 32; i++) {
+ if (tmp & (1 << i)) {
+ if (i >= MATROXFB_MAX_OUTPUTS)
+ return -ENXIO;
+ if (!ACCESS_FBINFO(outputs[i]).output)
+ return -ENXIO;
+ switch (ACCESS_FBINFO(outputs[i]).src) {
+ case MATROXFB_SRC_NONE:
+ case MATROXFB_SRC_CRTC1:
+ break;
+ default:
+ return -EBUSY;
+ }
+ }
}
- if (tmp == ACCESS_FBINFO(output.ph))
+ if (ACCESS_FBINFO(devflags.panellink)) {
+ if (tmp & MATROXFB_OUTPUT_CONN_DFP) {
+ if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY)
+ return -EINVAL;
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC2) {
+ return -EBUSY;
+ }
+ }
+ }
+ }
+ changes = 0;
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (tmp & (1 << i)) {
+ if (ACCESS_FBINFO(outputs[i]).src != MATROXFB_SRC_CRTC1) {
+ changes = 1;
+ ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_CRTC1;
+ }
+ } else if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) {
+ changes = 1;
+ ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_NONE;
+ }
+ }
+ if (!changes)
return 0;
- ACCESS_FBINFO(output.ph) = tmp;
matroxfb_switch(ACCESS_FBINFO(fbcon.currcon), info);
return 0;
}
case MATROXFB_GET_OUTPUT_CONNECTION:
{
- if (put_user(ACCESS_FBINFO(output.ph), (u_int32_t*)arg))
+ u_int32_t conn = 0;
+ int i;
+
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) {
+ conn |= 1 << i;
+ }
+ }
+ if (put_user(conn, (u_int32_t*)arg))
return -EFAULT;
return 0;
}
case MATROXFB_GET_AVAILABLE_OUTPUTS:
{
- u_int32_t tmp;
-
- tmp = ACCESS_FBINFO(output.all) & ~ACCESS_FBINFO(output.sh);
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP)
- tmp &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY)
- tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
- if (put_user(tmp, (u_int32_t*)arg))
+ u_int32_t conn = 0;
+ int i;
+
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).output) {
+ switch (ACCESS_FBINFO(outputs[i]).src) {
+ case MATROXFB_SRC_NONE:
+ case MATROXFB_SRC_CRTC1:
+ conn |= 1 << i;
+ break;
+ }
+ }
+ }
+ if (ACCESS_FBINFO(devflags.panellink)) {
+ if (conn & MATROXFB_OUTPUT_CONN_DFP)
+ conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
+ if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
+ conn &= ~MATROXFB_OUTPUT_CONN_DFP;
+ }
+ if (put_user(conn, (u_int32_t*)arg))
return -EFAULT;
return 0;
}
case MATROXFB_GET_ALL_OUTPUTS:
{
- if (put_user(ACCESS_FBINFO(output.all), (u_int32_t*)arg))
+ u_int32_t conn = 0;
+ int i;
+
+ for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+ if (ACCESS_FBINFO(outputs[i]).output) {
+ conn |= 1 << i;
+ }
+ }
+ if (put_user(conn, (u_int32_t*)arg))
return -EFAULT;
return 0;
}
}
- return -EINVAL;
+ return -ENOTTY;
#undef minfo
}
@@ -1150,7 +1151,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
static int matroxfb_blank(int blank, struct fb_info *info)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
int seq;
int crtc;
CRITFLAGS
@@ -1184,8 +1185,6 @@ static struct fb_ops matroxfb_ops = {
.owner = THIS_MODULE,
.fb_open = matroxfb_open,
.fb_release = matroxfb_release,
- .fb_get_fix = matroxfb_get_fix,
- .fb_get_var = matroxfb_get_var,
.fb_set_var = matroxfb_set_var,
.fb_get_cmap = matroxfb_get_cmap,
.fb_set_cmap = matroxfb_set_cmap,
@@ -1197,7 +1196,7 @@ static struct fb_ops matroxfb_ops = {
int matroxfb_switch(int con, struct fb_info *info)
{
-#define minfo ((struct matrox_fb_info*)info)
+#define minfo (container_of(info, struct matrox_fb_info, fbcon))
struct fb_cmap* cmap;
struct display *p;
@@ -1392,10 +1391,10 @@ static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG4
#define DEVF_VIDEO64BIT 0x0001
#define DEVF_SWAPS 0x0002
#define DEVF_SRCORG 0x0004
-#define DEVF_BOTHDACS 0x0008 /* put CRTC1 on both outputs by default */
+#define DEVF_DUALHEAD 0x0008
#define DEVF_CROSS4MB 0x0010
#define DEVF_TEXT4B 0x0020
-#define DEVF_DDC_8_2 0x0040
+/* #define DEVF_recycled 0x0040 */
/* #define DEVF_recycled 0x0080 */
#define DEVF_SUPPORT32MB 0x0100
#define DEVF_ANY_VXRES 0x0200
@@ -1405,14 +1404,14 @@ static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG4
#define DEVF_PANELLINK_CAPABLE 0x2000
#define DEVF_G450DAC 0x4000
-#define DEVF_GCORE (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2)
-#define DEVF_G2CORE (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE | DEVF_SRCORG)
+#define DEVF_GCORE (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB)
+#define DEVF_G2CORE (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE | DEVF_SRCORG | DEVF_DUALHEAD)
#define DEVF_G100 (DEVF_GCORE) /* no doc, no vxres... */
#define DEVF_G200 (DEVF_G2CORE)
#define DEVF_G400 (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2)
/* if you'll find how to drive DFP... */
-#define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG)
-#define DEVF_G550 (DEVF_G450 | DEVF_BOTHDACS)
+#define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG | DEVF_DUALHEAD)
+#define DEVF_G550 (DEVF_G450)
static struct board {
unsigned short vendor, device, rev, svid, sid;
@@ -1606,27 +1605,24 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8;
}
#ifdef CONFIG_FB_MATROX_32MB
- ACCESS_FBINFO(devflags.support32MB) = b->flags & DEVF_SUPPORT32MB;
+ ACCESS_FBINFO(devflags.support32MB) = (b->flags & DEVF_SUPPORT32MB) != 0;
#endif
ACCESS_FBINFO(devflags.precise_width) = !(b->flags & DEVF_ANY_VXRES);
- ACCESS_FBINFO(devflags.crtc2) = b->flags & DEVF_CRTC2;
- ACCESS_FBINFO(devflags.maven_capable) = b->flags & DEVF_MAVEN_CAPABLE;
+ ACCESS_FBINFO(devflags.crtc2) = (b->flags & DEVF_CRTC2) != 0;
+ ACCESS_FBINFO(devflags.maven_capable) = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
+ ACCESS_FBINFO(devflags.dualhead) = (b->flags & DEVF_DUALHEAD) != 0;
if (b->flags & DEVF_PANELLINK_CAPABLE) {
- ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_DFP;
+ ACCESS_FBINFO(outputs[2]).data = MINFO;
+ ACCESS_FBINFO(outputs[2]).output = &panellink_output;
if (dfp)
- ACCESS_FBINFO(output.ph) |= MATROXFB_OUTPUT_CONN_DFP;
- }
- if (b->flags & DEVF_BOTHDACS) {
-#ifdef CONFIG_FB_MATROX_G450
- ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY;
- ACCESS_FBINFO(output.ph) |= MATROXFB_OUTPUT_CONN_SECONDARY;
-#else
- printk(KERN_INFO "Only digital output of G550 is now working (in analog mode). Enable G450 support in\n");
- printk(KERN_INFO "kernel configuration if you have analog monitor connected to G550 analog output.\n");
-#endif
+ ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_CRTC1;
+ else
+ ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_NONE;
+ ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+ ACCESS_FBINFO(devflags.panellink) = 1;
}
ACCESS_FBINFO(devflags.dfp_type) = dfp_type;
- ACCESS_FBINFO(devflags.g450dac) = b->flags & DEVF_G450DAC;
+ ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0;
ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
@@ -1732,6 +1728,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
if (!ACCESS_FBINFO(devflags.novga))
request_region(0x3C0, 32, "matrox");
+ matroxfb_g450_connect(PMINFO2);
ACCESS_FBINFO(hw_switch->reset(PMINFO2));
ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0;
@@ -1885,6 +1882,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){
}
return 0;
failVideoIO:;
+ matroxfb_g450_shutdown(PMINFO2);
mga_iounmap(ACCESS_FBINFO(video.vbase));
failCtrlIO:;
mga_iounmap(ACCESS_FBINFO(mmio.vbase));
@@ -2072,10 +2070,6 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
init_rwsem(&ACCESS_FBINFO(crtc2.lock));
init_rwsem(&ACCESS_FBINFO(altout.lock));
- ACCESS_FBINFO(output.all) = MATROXFB_OUTPUT_CONN_PRIMARY;
- ACCESS_FBINFO(output.ph) = MATROXFB_OUTPUT_CONN_PRIMARY;
- ACCESS_FBINFO(output.sh) = 0;
-
err = initMatrox2(PMINFO d, b);
if (!err) {
#ifndef CONFIG_FB_MATROX_MULTIHEAD
@@ -2489,8 +2483,8 @@ int __init matroxfb_init(void)
/* *************************** init module code **************************** */
-MODULE_AUTHOR("(c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450");
+MODULE_AUTHOR("(c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450/G550");
MODULE_LICENSE("GPL");
MODULE_PARM(mem, "i");
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 5ad1962a3d00..64980ccd5574 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -2,7 +2,7 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450
*
- * (c) 1998,1999,2000,2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
*/
#ifndef __MATROXFB_H__
@@ -288,6 +288,8 @@ static inline void mga_iounmap(vaddr_t va) {
struct my_timming {
unsigned int pixclock;
+ int mnp;
+ unsigned int crtc;
unsigned int HDisplay;
unsigned int HSyncStart;
unsigned int HSyncEnd;
@@ -364,6 +366,10 @@ struct mavenregs {
u_int16_t hcorr;
};
+struct matrox_crtc2 {
+ u_int32_t ctl;
+};
+
struct matrox_hw_state {
u_int32_t MXoptionReg;
unsigned char DACclk[6];
@@ -381,10 +387,7 @@ struct matrox_hw_state {
/* TVOut only */
struct mavenregs maven;
- /* CRTC2 only */
- /* u_int32_t TBD */
-
- unsigned int vidclk;
+ struct matrox_crtc2 crtc2;
};
struct matrox_accel_data {
@@ -396,15 +399,17 @@ struct matrox_accel_data {
};
struct matrox_altout {
+ const char *name;
int (*compute)(void* altout_dev, struct my_timming* input);
int (*program)(void* altout_dev);
int (*start)(void* altout_dev);
- void (*incuse)(void* altout_dev);
- void (*decuse)(void* altout_dev);
- int (*setmode)(void* altout_dev, u_int32_t mode);
- int (*getmode)(void* altout_dev, u_int32_t* mode);
+ int (*verifymode)(void* altout_dev, u_int32_t mode);
};
+#define MATROXFB_SRC_NONE 0
+#define MATROXFB_SRC_CRTC1 1
+#define MATROXFB_SRC_CRTC2 2
+
enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 };
struct matrox_bios {
@@ -421,9 +426,9 @@ struct matrox_bios {
struct matrox_switch;
struct matroxfb_driver;
+struct matroxfb_dh_fb_info;
struct matrox_fb_info {
- /* fb_info must be first */
struct fb_info fbcon;
struct list_head next_fb;
@@ -439,20 +444,25 @@ struct matrox_fb_info {
struct pci_dev* pcidev;
struct {
- u_int32_t all;
- u_int32_t ph;
- u_int32_t sh;
- } output;
- struct matrox_altout* primout;
+ unsigned int pixclock;
+ int mnp;
+ } crtc1;
struct {
- struct fb_info* info;
+ unsigned int pixclock;
+ int mnp;
+ struct matroxfb_dh_fb_info* info;
struct rw_semaphore lock;
} crtc2;
struct {
- struct matrox_altout* output;
- void* device;
- struct rw_semaphore lock;
+ struct rw_semaphore lock;
} altout;
+#define MATROXFB_MAX_OUTPUTS 3
+ struct {
+ unsigned int src;
+ struct matrox_altout* output;
+ void* data;
+ unsigned int mode;
+ } outputs[MATROXFB_MAX_OUTPUTS];
#define MATROXFB_MAX_FB_DRIVERS 5
struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]);
@@ -541,6 +551,8 @@ struct matrox_fb_info {
int memtype;
int g450dac;
int dfp_type;
+ int panellink; /* G400 DFP possible (not G450/G550) */
+ int dualhead;
unsigned int fbResource;
} devflags;
struct display_switch dispsw;
@@ -618,7 +630,7 @@ struct matrox_fb_info {
#define PMINFO PMINFO2 ,
static inline struct matrox_fb_info* mxinfo(const struct display* p) {
- return (struct matrox_fb_info*)p->fb_info;
+ return container_of(p->fb_info, struct matrox_fb_info, fbcon);
}
#define PMXINFO(p) mxinfo(p),
@@ -658,7 +670,7 @@ struct matrox_switch {
void (*reset)(WPMINFO2);
int (*init)(WPMINFO struct my_timming*, struct display*);
void (*restore)(WPMINFO struct display*);
- int (*selhwcursor)(WPMINFO struct display*);
+ int (*selhwcursor)(WPMINFO2);
};
struct matroxfb_driver {
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 7bc8aea94f8c..56c7c7a02583 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
*
- * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2001/11/29
+ * Version: 1.65 2002/08/14
*
*/
@@ -28,7 +28,7 @@ MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)");
static int matroxfb_dh_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp, struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
if (regno >= 16)
return 1;
*red = m2info->palette[regno].red;
@@ -41,8 +41,7 @@ static int matroxfb_dh_getcolreg(unsigned regno, unsigned *red, unsigned *green,
static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct display* p;
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
if (regno >= 16)
return 1;
@@ -50,33 +49,32 @@ static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,
m2info->palette[regno].blue = blue;
m2info->palette[regno].green = green;
m2info->palette[regno].transp = transp;
- p = m2info->currcon_display;
- if (p->var.grayscale) {
+ if (m2info->fbcon.var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
- red = CNVT_TOHW(red, p->var.red.length);
- green = CNVT_TOHW(green, p->var.green.length);
- blue = CNVT_TOHW(blue, p->var.blue.length);
- transp = CNVT_TOHW(transp, p->var.transp.length);
+ red = CNVT_TOHW(red, m2info->fbcon.var.red.length);
+ green = CNVT_TOHW(green, m2info->fbcon.var.green.length);
+ blue = CNVT_TOHW(blue, m2info->fbcon.var.blue.length);
+ transp = CNVT_TOHW(transp, m2info->fbcon.var.transp.length);
- switch (p->var.bits_per_pixel) {
+ switch (m2info->fbcon.var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB16
case 16:
m2info->cmap.cfb16[regno] =
- (red << p->var.red.offset) |
- (green << p->var.green.offset) |
- (blue << p->var.blue.offset) |
- (transp << p->var.transp.offset);
+ (red << m2info->fbcon.var.red.offset) |
+ (green << m2info->fbcon.var.green.offset) |
+ (blue << m2info->fbcon.var.blue.offset) |
+ (transp << m2info->fbcon.var.transp.offset);
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
m2info->cmap.cfb32[regno] =
- (red << p->var.red.offset) |
- (green << p->var.green.offset) |
- (blue << p->var.blue.offset) |
- (transp << p->var.transp.offset);
+ (red << m2info->fbcon.var.red.offset) |
+ (green << m2info->fbcon.var.green.offset) |
+ (blue << m2info->fbcon.var.blue.offset) |
+ (transp << m2info->fbcon.var.transp.offset);
break;
#endif
}
@@ -99,10 +97,10 @@ static inline void my_install_cmap(struct matroxfb_dh_fb_info* m2info)
static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
struct my_timming* mt,
- struct display* p,
int mode,
unsigned int pos) {
u_int32_t tmp;
+ u_int32_t datactl;
MINFO_FROM(m2info->primary_dev);
switch (mode) {
@@ -117,26 +115,26 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
tmp = 0x00800000;
break;
}
-
- if (ACCESS_FBINFO(output.sh)) {
- tmp |= 0x00000001; /* enable CRTC2 */
-
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- if (ACCESS_FBINFO(devflags.g450dac)) {
- tmp |= 0x00000006; /* source from secondary pixel PLL */
- /* no vidrst */
- } else {
- tmp |= 0x00000002; /* source from VDOCLK */
- tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
- /* MGA TVO is our clock source */
+ tmp |= 0x00000001; /* enable CRTC2 */
+ datactl = 0;
+ if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) {
+ if (ACCESS_FBINFO(devflags.g450dac)) {
+ tmp |= 0x00000006; /* source from secondary pixel PLL */
+ /* no vidrst when in monitor mode */
+ if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) {
+ tmp |= 0xC0001000; /* Enable H/V vidrst */
}
- } else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
- tmp |= 0x00000004; /* source from pixclock */
- /* PIXPLL is our clock source */
+ } else {
+ tmp |= 0x00000002; /* source from VDOCLK */
+ tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
+ /* MGA TVO is our clock source */
}
-
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY)
- tmp |= 0x00100000; /* connect CRTC2 to DAC */
+ } else if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {
+ tmp |= 0x00000004; /* source from pixclock */
+ /* PIXPLL is our clock source */
+ }
+ if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {
+ tmp |= 0x00100000; /* connect CRTC2 to DAC */
}
if (mt->interlaced) {
tmp |= 0x02000000; /* interlaced, second field is bigger, as G450 apparently ignores it */
@@ -145,35 +143,63 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
mt->VSyncEnd >>= 1;
mt->VTotal >>= 1;
}
- mga_outl(0x3C10, tmp | 0x10000000); /* depth and so on... 0x10000000 is VIDRST polarity */
+ if ((mt->HTotal & 7) == 2) {
+ datactl |= 0x00000010;
+ mt->HTotal &= ~7;
+ }
+ tmp |= 0x10000000; /* 0x10000000 is VIDRST polarity */
mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8));
mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8));
mga_outl(0x3C1C, ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1));
mga_outl(0x3C20, ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1));
mga_outl(0x3C24, ((mt->VSyncStart) << 16) | (mt->HSyncStart)); /* preload */
{
- u_int32_t linelen = p->var.xres_virtual * (p->var.bits_per_pixel >> 3);
- if (mt->interlaced) {
+ u_int32_t linelen = m2info->fbcon.var.xres_virtual * (m2info->fbcon.var.bits_per_pixel >> 3);
+ if (tmp & 0x02000000) {
/* field #0 is smaller, so... */
mga_outl(0x3C2C, pos); /* field #1 vmemory start */
mga_outl(0x3C28, pos + linelen); /* field #0 vmemory start */
linelen <<= 1;
+ m2info->interlaced = 1;
} else {
mga_outl(0x3C28, pos); /* vmemory start */
+ m2info->interlaced = 0;
}
mga_outl(0x3C40, linelen);
}
+ mga_outl(0x3C4C, datactl); /* data control */
+ if (tmp & 0x02000000) {
+ int i;
+
+ mga_outl(0x3C10, tmp & ~0x02000000);
+ for (i = 0; i < 2; i++) {
+ unsigned int nl;
+ unsigned int lastl = 0;
+
+ while ((nl = mga_inl(0x3C48) & 0xFFF) >= lastl) {
+ lastl = nl;
+ }
+ }
+ }
+ mga_outl(0x3C10, tmp);
+ ACCESS_FBINFO(hw).crtc2.ctl = tmp;
+
tmp = 0x0FFF0000; /* line compare */
if (mt->sync & FB_SYNC_HOR_HIGH_ACT)
tmp |= 0x00000100;
if (mt->sync & FB_SYNC_VERT_HIGH_ACT)
tmp |= 0x00000200;
mga_outl(0x3C44, tmp);
- mga_outl(0x3C4C, 0); /* data control */
}
-static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info,
- struct display* p) {
+static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {
+ MINFO_FROM(m2info->primary_dev);
+
+ mga_outl(0x3C10, 0x00000004); /* disable CRTC2, CRTC1->DAC1, PLL as clock source */
+ ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004;
+}
+
+static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info) {
/* no acceleration for secondary head... */
}
@@ -182,23 +208,23 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
unsigned int pos;
unsigned int linelen;
unsigned int pixelsize;
+ MINFO_FROM(m2info->primary_dev);
-#define minfo (m2info->primary_dev)
- pixelsize = var->bits_per_pixel >> 3;
- linelen = var->xres_virtual * pixelsize;
- pos = var->yoffset * linelen + var->xoffset * pixelsize;
+ m2info->fbcon.var.xoffset = var->xoffset;
+ m2info->fbcon.var.yoffset = var->yoffset;
+ pixelsize = m2info->fbcon.var.bits_per_pixel >> 3;
+ linelen = m2info->fbcon.var.xres_virtual * pixelsize;
+ pos = m2info->fbcon.var.yoffset * linelen + m2info->fbcon.var.xoffset * pixelsize;
pos += m2info->video.offbase;
- if (var->vmode & FB_VMODE_INTERLACED) {
+ if (m2info->interlaced) {
mga_outl(0x3C2C, pos);
mga_outl(0x3C28, pos + linelen);
} else {
mga_outl(0x3C28, pos);
}
-#undef minfo
}
static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info,
- struct display* p,
struct fb_var_screeninfo* var,
int *visual,
int *video_cmap_len,
@@ -277,7 +303,7 @@ static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info,
}
static void initMatroxDH(struct matroxfb_dh_fb_info* m2info, struct display* p) {
- switch (p->var.bits_per_pixel) {
+ switch (m2info->fbcon.var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB16
case 16:
p->dispsw_data = m2info->cmap.cfb16;
@@ -298,7 +324,7 @@ static void initMatroxDH(struct matroxfb_dh_fb_info* m2info, struct display* p)
}
static int matroxfb_dh_open(struct fb_info* info, int user) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
MINFO_FROM(m2info->primary_dev);
if (MINFO) {
@@ -311,7 +337,7 @@ static int matroxfb_dh_open(struct fb_info* info, int user) {
}
static int matroxfb_dh_release(struct fb_info* info, int user) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
MINFO_FROM(m2info->primary_dev);
if (MINFO) {
@@ -320,49 +346,24 @@ static int matroxfb_dh_release(struct fb_info* info, int user) {
#undef m2info
}
-static int matroxfb_dh_get_fix(struct fb_fix_screeninfo* fix, int con,
- struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
- struct display* p;
+static void matroxfb_dh_update_fix(struct matroxfb_dh_fb_info *m2info) {
+ struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;
- if (con >= 0)
- p = fb_display + con;
- else
- p = m2info->fbcon.disp;
-
- memset(fix, 0, sizeof(*fix));
strcpy(fix->id, "MATROX DH");
fix->smem_start = m2info->video.base;
fix->smem_len = m2info->video.len_usable;
- fix->type = p->type;
- fix->type_aux = p->type_aux;
- fix->visual = p->visual;
- fix->xpanstep = 8; /* TBD */
fix->ypanstep = 1;
fix->ywrapstep = 0;
- fix->line_length = p->line_length;
+ fix->xpanstep = 8; /* TBD */
fix->mmio_start = m2info->mmio.base;
fix->mmio_len = m2info->mmio.len;
fix->accel = 0; /* no accel... */
- return 0;
-#undef m2info
-}
-
-static int matroxfb_dh_get_var(struct fb_var_screeninfo* var, int con,
- struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
- if (con < 0)
- *var = m2info->fbcon.disp->var;
- else
- *var = fb_display[con].var;
- return 0;
-#undef m2info
}
static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
struct display* p;
int chgvar;
int visual;
@@ -375,7 +376,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
p = m2info->fbcon.disp;
else
p = fb_display + con;
- if ((err = matroxfb_dh_decode_var(m2info, p, var, &visual, &cmap_len, &mode)) != 0)
+ if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0)
return err;
switch (var->activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST: return 0;
@@ -396,13 +397,15 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
chgvar = 0;
p->var = *var;
/* cmap */
- m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase);
- p->visual = visual;
- p->ypanstep = 1;
- p->ywrapstep = 0;
- p->type = FB_TYPE_PACKED_PIXELS;
- p->type_aux = 0;
- p->next_line = p->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+ if (con == m2info->fbcon.currcon) {
+ m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase);
+ m2info->fbcon.var = *var;
+ m2info->fbcon.fix.visual = visual;
+ m2info->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
+ m2info->fbcon.fix.type_aux = 0;
+ p->next_line = m2info->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+ matroxfb_dh_update_fix(m2info);
+ }
p->can_soft_blank = 0;
p->inverse = 0; /* TBD */
initMatroxDH(m2info, p);
@@ -411,47 +414,51 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
if (con == m2info->fbcon.currcon) {
struct my_timming mt;
unsigned int pos;
+ int out;
+ int cnt;
- matroxfb_var2my(var, &mt);
+ matroxfb_var2my(&m2info->fbcon.var, &mt);
+ mt.crtc = MATROXFB_SRC_CRTC2;
/* CRTC2 delay */
mt.delay = 34;
- pos = (var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel >> 3;
+ pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3;
pos += m2info->video.offbase;
- DAC1064_global_init(PMINFO2);
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
- if (ACCESS_FBINFO(primout))
- ACCESS_FBINFO(primout)->compute(MINFO, &mt);
+ cnt = 0;
+ down_read(&ACCESS_FBINFO(altout).lock);
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {
+ cnt++;
+ if (ACCESS_FBINFO(outputs[out]).output->compute) {
+ ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt);
+ }
+ }
}
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output))
- ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt);
- up_read(&ACCESS_FBINFO(altout.lock));
+ ACCESS_FBINFO(crtc2).pixclock = mt.pixclock;
+ ACCESS_FBINFO(crtc2).mnp = mt.mnp;
+ up_read(&ACCESS_FBINFO(altout).lock);
+ if (cnt) {
+ matroxfb_dh_restore(m2info, &mt, mode, pos);
+ } else {
+ matroxfb_dh_disable(m2info);
}
- matroxfb_dh_restore(m2info, &mt, p, mode, pos);
+ DAC1064_global_init(PMINFO2);
DAC1064_global_restore(PMINFO2);
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
- if (ACCESS_FBINFO(primout))
- ACCESS_FBINFO(primout)->program(MINFO);
- }
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output))
- ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device));
- up_read(&ACCESS_FBINFO(altout.lock));
- }
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) {
- if (ACCESS_FBINFO(primout))
- ACCESS_FBINFO(primout)->start(MINFO);
+ down_read(&ACCESS_FBINFO(altout).lock);
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 &&
+ ACCESS_FBINFO(outputs[out]).output->program) {
+ ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data);
+ }
}
- if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) {
- down_read(&ACCESS_FBINFO(altout.lock));
- if (ACCESS_FBINFO(altout.output))
- ACCESS_FBINFO(altout.output)->start(ACCESS_FBINFO(altout.device));
- up_read(&ACCESS_FBINFO(altout.lock));
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 &&
+ ACCESS_FBINFO(outputs[out]).output->start) {
+ ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data);
+ }
}
- matroxfb_dh_cfbX_init(m2info, p);
+ up_read(&ACCESS_FBINFO(altout).lock);
+ matroxfb_dh_cfbX_init(m2info);
my_install_cmap(m2info);
}
return 0;
@@ -460,7 +467,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
static int matroxfb_dh_get_cmap(struct fb_cmap* cmap, int kspc, int con,
struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
struct display* dsp;
if (con < 0)
@@ -479,7 +486,7 @@ static int matroxfb_dh_get_cmap(struct fb_cmap* cmap, int kspc, int con,
static int matroxfb_dh_set_cmap(struct fb_cmap* cmap, int kspc, int con,
struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
struct display* dsp;
if (con < 0)
@@ -503,7 +510,7 @@ static int matroxfb_dh_set_cmap(struct fb_cmap* cmap, int kspc, int con,
static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, int con,
struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
if (var->xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
var->yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
return -EINVAL;
@@ -525,7 +532,7 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru
/* mask out reserved bits + field number (odd/even) */
vblank->vcount = mga_inl(0x3C48) & 0x000007FF;
/* compatibility stuff */
- if (vblank->vcount >= m2info->currcon_display->var.yres)
+ if (vblank->vcount >= m2info->fbcon.var.yres)
vblank->flags |= FB_VBLANK_VBLANKING;
return 0;
}
@@ -536,7 +543,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
unsigned long arg,
int con,
struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
MINFO_FROM(m2info->primary_dev);
DBG("matroxfb_crtc2_ioctl")
@@ -563,49 +570,95 @@ static int matroxfb_dh_ioctl(struct inode* inode,
case MATROXFB_SET_OUTPUT_CONNECTION:
{
u_int32_t tmp;
+ int out;
+ int changes;
if (get_user(tmp, (u_int32_t*)arg))
return -EFAULT;
- if (tmp & ~ACCESS_FBINFO(output.all))
- return -EINVAL;
- if (tmp & ACCESS_FBINFO(output.ph))
- return -EINVAL;
- if (tmp & MATROXFB_OUTPUT_CONN_DFP)
- return -EINVAL;
- if ((ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) && tmp)
- return -EINVAL;
- if (tmp == ACCESS_FBINFO(output.sh))
+ for (out = 0; out < 32; out++) {
+ if (tmp & (1 << out)) {
+ if (out >= MATROXFB_MAX_OUTPUTS)
+ return -ENXIO;
+ if (!ACCESS_FBINFO(outputs[out]).output)
+ return -ENXIO;
+ switch (ACCESS_FBINFO(outputs[out]).src) {
+ case MATROXFB_SRC_NONE:
+ case MATROXFB_SRC_CRTC2:
+ break;
+ default:
+ return -EBUSY;
+ }
+ }
+ }
+ if (ACCESS_FBINFO(devflags.panellink)) {
+ if (tmp & MATROXFB_OUTPUT_CONN_DFP)
+ return -EINVAL;
+ if ((ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) && tmp)
+ return -EBUSY;
+ }
+ changes = 0;
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (tmp & (1 << out)) {
+ if (ACCESS_FBINFO(outputs[out]).src != MATROXFB_SRC_CRTC2) {
+ changes = 1;
+ ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_CRTC2;
+ }
+ } else if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {
+ changes = 1;
+ ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_NONE;
+ }
+ }
+ if (!changes)
return 0;
- ACCESS_FBINFO(output.sh) = tmp;
matroxfb_dh_switch(m2info->fbcon.currcon, info);
return 0;
}
case MATROXFB_GET_OUTPUT_CONNECTION:
{
- if (put_user(ACCESS_FBINFO(output.sh), (u_int32_t*)arg))
+ u_int32_t conn = 0;
+ int out;
+
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {
+ conn |= 1 << out;
+ }
+ }
+ if (put_user(conn, (u_int32_t*)arg))
return -EFAULT;
return 0;
}
case MATROXFB_GET_AVAILABLE_OUTPUTS:
{
- u_int32_t tmp;
-
- /* we do not support DFP from CRTC2 */
- tmp = ACCESS_FBINFO(output.all) & ~ACCESS_FBINFO(output.ph) & ~MATROXFB_OUTPUT_CONN_DFP;
- /* CRTC1 in DFP mode disables CRTC2 at all (I know, I'm lazy) */
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP)
- tmp = 0;
+ u_int32_t tmp = 0;
+ int out;
+
+ for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
+ if (ACCESS_FBINFO(outputs[out]).output) {
+ switch (ACCESS_FBINFO(outputs[out]).src) {
+ case MATROXFB_SRC_NONE:
+ case MATROXFB_SRC_CRTC2:
+ tmp |= 1 << out;
+ break;
+ }
+ }
+ }
+ if (ACCESS_FBINFO(devflags.panellink)) {
+ tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
+ if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) {
+ tmp = 0;
+ }
+ }
if (put_user(tmp, (u_int32_t*)arg))
return -EFAULT;
return 0;
}
}
- return -EINVAL;
+ return -ENOTTY;
#undef m2info
}
static int matroxfb_dh_blank(int blank, struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
switch (blank) {
case 1:
case 2:
@@ -622,8 +675,6 @@ static struct fb_ops matroxfb_dh_ops = {
.owner = THIS_MODULE,
.fb_open = matroxfb_dh_open,
.fb_release = matroxfb_dh_release,
- .fb_get_fix = matroxfb_dh_get_fix,
- .fb_get_var = matroxfb_dh_get_var,
.fb_set_var = matroxfb_dh_set_var,
.fb_get_cmap = matroxfb_dh_get_cmap,
.fb_set_cmap = matroxfb_dh_set_cmap,
@@ -634,7 +685,7 @@ static struct fb_ops matroxfb_dh_ops = {
};
static int matroxfb_dh_switch(int con, struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
struct fb_cmap* cmap;
struct display* p;
@@ -657,7 +708,7 @@ static int matroxfb_dh_switch(int con, struct fb_info* info) {
}
static int matroxfb_dh_updatevar(int con, struct fb_info* info) {
-#define m2info ((struct matroxfb_dh_fb_info*)info)
+#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
matroxfb_dh_pan_var(m2info, &fb_display[con].var);
return 0;
#undef m2info
@@ -730,11 +781,10 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
/*
* If we have unused output, connect CRTC2 to it...
*/
- if ((ACCESS_FBINFO(output.all) & MATROXFB_OUTPUT_CONN_SECONDARY) &&
- !(ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) &&
- !(ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP)) {
- ACCESS_FBINFO(output.sh) |= MATROXFB_OUTPUT_CONN_SECONDARY;
- ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_DFP;
+ if (ACCESS_FBINFO(outputs[1]).output &&
+ ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_NONE &&
+ ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_NONE) {
+ ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC2;
}
matroxfb_dh_set_var(&matroxfb_dh_defined, -2, &m2info->fbcon);
@@ -747,7 +797,7 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
}
down_write(&ACCESS_FBINFO(crtc2.lock));
oldcrtc2 = ACCESS_FBINFO(crtc2.info);
- ACCESS_FBINFO(crtc2.info) = &m2info->fbcon;
+ ACCESS_FBINFO(crtc2.info) = m2info;
up_write(&ACCESS_FBINFO(crtc2.lock));
if (oldcrtc2) {
printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
@@ -776,16 +826,16 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
#define minfo (m2info->primary_dev)
if (m2info->fbcon_registered) {
int id;
- struct fb_info* crtc2;
+ struct matroxfb_dh_fb_info* crtc2;
down_write(&ACCESS_FBINFO(crtc2.lock));
crtc2 = ACCESS_FBINFO(crtc2.info);
- if (crtc2 == &m2info->fbcon)
+ if (crtc2 == m2info)
ACCESS_FBINFO(crtc2.info) = NULL;
up_write(&ACCESS_FBINFO(crtc2.lock));
- if (crtc2 != &m2info->fbcon) {
+ if (crtc2 != m2info) {
printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
- crtc2, &m2info->fbcon);
+ crtc2, m2info);
printk(KERN_ERR "matroxfb_crtc2: Expect kernel crash after module unload.\n");
return;
}
@@ -823,6 +873,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
static void matroxfb_crtc2_remove(struct matrox_fb_info* minfo, void* crtc2) {
matroxfb_dh_deregisterfb(crtc2);
+ kfree(crtc2);
}
static struct matroxfb_driver crtc2 = {
@@ -839,7 +890,7 @@ static void matroxfb_crtc2_exit(void) {
matroxfb_unregister_driver(&crtc2);
}
-MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Matrox G400 CRTC2 driver");
MODULE_LICENSE("GPL");
module_init(matroxfb_crtc2_init);
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
index e625053bc679..be8a81f4253d 100644
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ b/drivers/video/matrox/matroxfb_crtc2.h
@@ -27,8 +27,9 @@ struct matroxfb_dh_fb_info {
unsigned int len;
} mmio;
- int currcon;
struct display* currcon_display;
+
+ int interlaced:1;
union {
#ifdef FBCON_HAS_CFB16
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index f07d3b26209b..17f5f9236bf4 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -2,145 +2,418 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
*
- * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2001/11/29
+ * Version: 1.64 2002/06/02
*
* See matroxfb_base.c for contributors.
*
*/
-#include "matroxfb_g450.h"
+#include "matroxfb_base.h"
#include "matroxfb_misc.h"
#include "matroxfb_DAC1064.h"
#include "g450_pll.h"
#include <linux/matroxfb.h>
#include <asm/uaccess.h>
+#include <asm/div64.h>
-static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
-#define m2info ((struct matroxfb_g450_info*)md)
-#define minfo (m2info->primary_dev)
- ACCESS_FBINFO(hw).vidclk = mt->pixclock;
-#undef minfo
-#undef m2info
- return 0;
-}
+static void cve2_set_reg(WPMINFO int reg, int val) {
+ unsigned long flags;
-static int matroxfb_g450_program(void* md) {
-#define m2info ((struct matroxfb_g450_info*)md)
-#define minfo (m2info->primary_dev)
- matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(hw).vidclk, M_VIDEO_PLL);
-#undef minfo
-#undef m2info
- return 0;
+ matroxfb_DAC_lock_irqsave(flags);
+ matroxfb_DAC_out(PMINFO 0x87, reg);
+ matroxfb_DAC_out(PMINFO 0x88, val);
+ matroxfb_DAC_unlock_irqrestore(flags);
}
-static int matroxfb_g450_start(void* md) {
- return 0;
-}
+struct output_desc {
+ unsigned int h_vis;
+ unsigned int h_f_porch;
+ unsigned int h_sync;
+ unsigned int h_b_porch;
+ unsigned long long int chromasc;
+ unsigned int burst;
+ unsigned int v_total;
+};
-static void matroxfb_g450_incuse(void* md) {
- MOD_INC_USE_COUNT;
-}
+static void computeRegs(WPMINFO struct mavenregs* r, struct my_timming* mt, const struct output_desc* outd) {
+ u_int32_t chromasc;
+ u_int32_t hlen;
+ u_int32_t hsl;
+ u_int32_t hbp;
+ u_int32_t hfp;
+ u_int32_t hvis;
+ unsigned int pixclock;
+ unsigned long long piic;
+ int mnp;
+ int over;
+
+ r->regs[0x80] = 0x03; /* | 0x40 for SCART */
+
+ hvis = ((mt->HDisplay << 1) + 3) & ~3;
+
+ if (hvis >= 2048) {
+ hvis = 2044;
+ }
+
+ piic = 1000000000ULL * hvis;
+ do_div(piic, outd->h_vis);
+
+ dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic);
+
+ mnp = matroxfb_g450_setclk(PMINFO piic, M_VIDEO_PLL);
+
+ mt->mnp = mnp;
+ mt->pixclock = g450_mnp2f(PMINFO mnp);
-static void matroxfb_g450_decuse(void* md) {
- MOD_DEC_USE_COUNT;
+ dprintk(KERN_DEBUG "MNP=%08X\n", mnp);
+
+ pixclock = 1000000000U / mt->pixclock;
+
+ dprintk(KERN_DEBUG "Got %u ps pixclock\n", pixclock);
+
+ piic = outd->chromasc;
+ do_div(piic, mt->pixclock);
+ chromasc = piic;
+
+ dprintk(KERN_DEBUG "Chroma is %08X\n", chromasc);
+
+ r->regs[0] = piic >> 24;
+ r->regs[1] = piic >> 16;
+ r->regs[2] = piic >> 8;
+ r->regs[3] = piic >> 0;
+ hbp = (((outd->h_b_porch + pixclock) / pixclock)) & ~1;
+ hfp = (((outd->h_f_porch + pixclock) / pixclock)) & ~1;
+ hsl = (((outd->h_sync + pixclock) / pixclock)) & ~1;
+ hlen = hvis + hfp + hsl + hbp;
+ over = hlen & 0x0F;
+
+ dprintk(KERN_DEBUG "WL: vis=%u, hf=%u, hs=%u, hb=%u, total=%u\n", hvis, hfp, hsl, hbp, hlen);
+
+ if (over) {
+ hfp -= over;
+ hlen -= over;
+ if (over <= 2) {
+ } else if (over < 10) {
+ hfp += 4;
+ hlen += 4;
+ } else {
+ hfp += 16;
+ hlen += 16;
+ }
+ }
+
+ /* maybe cve2 has requirement 800 < hlen < 1184 */
+ r->regs[0x08] = hsl;
+ r->regs[0x09] = (outd->burst + pixclock - 1) / pixclock; /* burst length */
+ r->regs[0x0A] = hbp;
+ r->regs[0x2C] = hfp;
+ r->regs[0x31] = hvis / 8;
+ r->regs[0x32] = hvis & 7;
+
+ dprintk(KERN_DEBUG "PG: vis=%04X, hf=%02X, hs=%02X, hb=%02X, total=%04X\n", hvis, hfp, hsl, hbp, hlen);
+
+ r->regs[0x84] = 1; /* x sync point */
+ r->regs[0x85] = 0;
+ hvis = hvis >> 1;
+ hlen = hlen >> 1;
+
+ dprintk(KERN_DEBUG "hlen=%u hvis=%u\n", hlen, hvis);
+
+ mt->interlaced = 1;
+
+ mt->HDisplay = hvis & ~7;
+ mt->HSyncStart = mt->HDisplay + 8;
+ mt->HSyncEnd = (hlen & ~7) - 8;
+ mt->HTotal = hlen;
+
+ {
+ int upper;
+ unsigned int vtotal;
+ unsigned int vsyncend;
+ unsigned int vdisplay;
+
+ vtotal = mt->VTotal;
+ vsyncend = mt->VSyncEnd;
+ vdisplay = mt->VDisplay;
+ if (vtotal < outd->v_total) {
+ unsigned int yovr = outd->v_total - vtotal;
+
+ vsyncend += yovr >> 1;
+ } else if (vtotal > outd->v_total) {
+ vdisplay = outd->v_total - 4;
+ vsyncend = outd->v_total;
+ }
+ upper = (outd->v_total - vsyncend) >> 1; /* in field lines */
+ r->regs[0x17] = outd->v_total / 4;
+ r->regs[0x18] = outd->v_total & 3;
+ r->regs[0x33] = upper - 1; /* upper blanking */
+ r->regs[0x82] = upper; /* y sync point */
+ r->regs[0x83] = upper >> 8;
+
+ mt->VDisplay = vdisplay;
+ mt->VSyncStart = outd->v_total - 2;
+ mt->VSyncEnd = outd->v_total;
+ mt->VTotal = outd->v_total;
+ }
}
-static int matroxfb_g450_set_mode(void* md, u_int32_t arg) {
- if (arg == MATROXFB_OUTPUT_MODE_MONITOR) {
- return 1;
+static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct output_desc** outd) {
+ static const struct output_desc paloutd = {
+ .h_vis = 52148148, // ps
+ .h_f_porch = 1407407, // ps
+ .h_sync = 4666667, // ps
+ .h_b_porch = 5777778, // ps
+ .chromasc = 19042247534182ULL, // 4433618.750 Hz
+ .burst = 2518518, // ps
+ .v_total = 625,
+ };
+ static const struct output_desc ntscoutd = {
+ .h_vis = 52888889, // ps
+ .h_f_porch = 1333333, // ps
+ .h_sync = 4666667, // ps
+ .h_b_porch = 4666667, // ps
+ .chromasc = 15374030659475ULL, // 3579545.454 Hz
+ .burst = 2418418, // ps
+ .v_total = 525, // lines
+ };
+
+ static const struct mavenregs palregs = { {
+ 0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */
+ 0x00,
+ 0x00, /* test */
+ 0xF9, /* modified by code (F9 written...) */
+ 0x00, /* ? not written */
+ 0x7E, /* 08 */
+ 0x44, /* 09 */
+ 0x9C, /* 0A */
+ 0x2E, /* 0B */
+ 0x21, /* 0C */
+ 0x00, /* ? not written */
+// 0x3F, 0x03, /* 0E-0F */
+ 0x3C, 0x03,
+ 0x3C, 0x03, /* 10-11 */
+ 0x1A, /* 12 */
+ 0x2A, /* 13 */
+ 0x1C, 0x3D, 0x14, /* 14-16 */
+ 0x9C, 0x01, /* 17-18 */
+ 0x00, /* 19 */
+ 0xFE, /* 1A */
+ 0x7E, /* 1B */
+ 0x60, /* 1C */
+ 0x05, /* 1D */
+// 0x89, 0x03, /* 1E-1F */
+ 0xAD, 0x03,
+// 0x72, /* 20 */
+ 0xA5,
+ 0x07, /* 21 */
+// 0x72, /* 22 */
+ 0xA5,
+ 0x00, /* 23 */
+ 0x00, /* 24 */
+ 0x00, /* 25 */
+ 0x08, /* 26 */
+ 0x04, /* 27 */
+ 0x00, /* 28 */
+ 0x1A, /* 29 */
+ 0x55, 0x01, /* 2A-2B */
+ 0x26, /* 2C */
+ 0x07, 0x7E, /* 2D-2E */
+ 0x02, 0x54, /* 2F-30 */
+ 0xB0, 0x00, /* 31-32 */
+ 0x14, /* 33 */
+ 0x49, /* 34 */
+ 0x00, /* 35 written multiple times */
+ 0x00, /* 36 not written */
+ 0xA3, /* 37 */
+ 0xC8, /* 38 */
+ 0x22, /* 39 */
+ 0x02, /* 3A */
+ 0x22, /* 3B */
+ 0x3F, 0x03, /* 3C-3D */
+ 0x00, /* 3E written multiple times */
+ 0x00, /* 3F not written */
+ } };
+ static struct mavenregs ntscregs = { {
+ 0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
+ 0x00,
+ 0x00, /* test */
+ 0xF9, /* modified by code (F9 written...) */
+ 0x00, /* ? not written */
+ 0x7E, /* 08 */
+ 0x43, /* 09 */
+ 0x7E, /* 0A */
+ 0x3D, /* 0B */
+ 0x00, /* 0C */
+ 0x00, /* ? not written */
+ 0x41, 0x00, /* 0E-0F */
+ 0x3C, 0x00, /* 10-11 */
+ 0x17, /* 12 */
+ 0x21, /* 13 */
+ 0x1B, 0x1B, 0x24, /* 14-16 */
+ 0x83, 0x01, /* 17-18 */
+ 0x00, /* 19 */
+ 0x0F, /* 1A */
+ 0x0F, /* 1B */
+ 0x60, /* 1C */
+ 0x05, /* 1D */
+ //0x89, 0x02, /* 1E-1F */
+ 0xC0, 0x02, /* 1E-1F */
+ //0x5F, /* 20 */
+ 0x9C, /* 20 */
+ 0x04, /* 21 */
+ //0x5F, /* 22 */
+ 0x9C, /* 22 */
+ 0x01, /* 23 */
+ 0x02, /* 24 */
+ 0x00, /* 25 */
+ 0x0A, /* 26 */
+ 0x05, /* 27 */
+ 0x00, /* 28 */
+ 0x10, /* 29 */
+ 0xFF, 0x03, /* 2A-2B */
+ 0x24, /* 2C */
+ 0x0F, 0x78, /* 2D-2E */
+ 0x00, 0x00, /* 2F-30 */
+ 0xB2, 0x04, /* 31-32 */
+ 0x14, /* 33 */
+ 0x02, /* 34 */
+ 0x00, /* 35 written multiple times */
+ 0x00, /* 36 not written */
+ 0xA3, /* 37 */
+ 0xC8, /* 38 */
+ 0x15, /* 39 */
+ 0x05, /* 3A */
+ 0x3B, /* 3B */
+ 0x3C, 0x00, /* 3C-3D */
+ 0x00, /* 3E written multiple times */
+ 0x00, /* never written */
+ } };
+
+ if (norm == MATROXFB_OUTPUT_MODE_PAL) {
+ *data = palregs;
+ *outd = &paloutd;
+ } else {
+ *data = ntscregs;
+ *outd = &ntscoutd;
}
- return -EINVAL;
+ return;
}
-static int matroxfb_g450_get_mode(void* md, u_int32_t* arg) {
- *arg = MATROXFB_OUTPUT_MODE_MONITOR;
- return 0;
+#define LR(x) cve2_set_reg(PMINFO (x), m->regs[(x)])
+static void cve2_init_TV(WPMINFO const struct mavenregs* m) {
+ int i;
+
+ LR(0x80);
+ LR(0x82); LR(0x83);
+ LR(0x84); LR(0x85);
+
+ cve2_set_reg(PMINFO 0x3E, 0x01);
+
+ for (i = 0; i < 0x3E; i++) {
+ LR(i);
+ }
+ cve2_set_reg(PMINFO 0x3E, 0x00);
}
-static struct matrox_altout matroxfb_g450_altout = {
- matroxfb_g450_compute,
- matroxfb_g450_program,
- matroxfb_g450_start,
- matroxfb_g450_incuse,
- matroxfb_g450_decuse,
- matroxfb_g450_set_mode,
- matroxfb_g450_get_mode
-};
+static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
+ MINFO_FROM(md);
+
+ dprintk(KERN_DEBUG "Computing, mode=%u\n", ACCESS_FBINFO(outputs[1]).mode);
-static int matroxfb_g450_connect(struct matroxfb_g450_info* m2info) {
- MINFO_FROM(m2info->primary_dev);
+ if (mt->crtc == MATROXFB_SRC_CRTC2 &&
+ ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) {
+ const struct output_desc* outd;
- down_write(&ACCESS_FBINFO(altout.lock));
- ACCESS_FBINFO(altout.device) = m2info;
- ACCESS_FBINFO(altout.output) = &matroxfb_g450_altout;
- up_write(&ACCESS_FBINFO(altout.lock));
- ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY;
- matroxfb_switch(ACCESS_FBINFO(fbcon.currcon), (struct fb_info*)MINFO);
+ cve2_init_TVdata(ACCESS_FBINFO(outputs[1]).mode, &ACCESS_FBINFO(hw).maven, &outd);
+ computeRegs(PMINFO &ACCESS_FBINFO(hw).maven, mt, outd);
+ } else if (mt->mnp < 0) {
+ /* We must program clocks before CRTC2, otherwise interlaced mode
+ startup may fail */
+ mt->mnp = matroxfb_g450_setclk(PMINFO mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
+ mt->pixclock = g450_mnp2f(PMINFO mt->mnp);
+ }
+ dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock);
return 0;
}
-static void matroxfb_g450_shutdown(struct matroxfb_g450_info* m2info) {
- MINFO_FROM(m2info->primary_dev);
+static int matroxfb_g450_program(void* md) {
+ MINFO_FROM(md);
- if (MINFO) {
- ACCESS_FBINFO(output.all) &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- ACCESS_FBINFO(output.ph) &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- down_write(&ACCESS_FBINFO(altout.lock));
- ACCESS_FBINFO(altout.device) = NULL;
- ACCESS_FBINFO(altout.output) = NULL;
- up_write(&ACCESS_FBINFO(altout.lock));
- m2info->primary_dev = NULL;
+ if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) {
+ cve2_init_TV(PMINFO &ACCESS_FBINFO(hw).maven);
}
+ return 0;
}
-/* we do not have __setup() yet */
-static void* matroxfb_g450_probe(struct matrox_fb_info* minfo) {
- struct matroxfb_g450_info* m2info;
-
- /* hardware is not G450... */
- if (!ACCESS_FBINFO(devflags.g450dac))
- return NULL;
- m2info = (struct matroxfb_g450_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
- if (!m2info) {
- printk(KERN_ERR "matroxfb_g450: Not enough memory for G450 DAC control structs\n");
- return NULL;
- }
- memset(m2info, 0, sizeof(*m2info));
- m2info->primary_dev = MINFO;
- if (matroxfb_g450_connect(m2info)) {
- kfree(m2info);
- printk(KERN_ERR "matroxfb_g450: G450 DAC failed to initialize\n");
- return NULL;
+static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) {
+ switch (arg) {
+ case MATROXFB_OUTPUT_MODE_PAL:
+ case MATROXFB_OUTPUT_MODE_NTSC:
+ case MATROXFB_OUTPUT_MODE_MONITOR:
+ return 0;
}
- return m2info;
+ return -EINVAL;
}
-static void matroxfb_g450_remove(struct matrox_fb_info* minfo, void* g450) {
- matroxfb_g450_shutdown(g450);
- kfree(g450);
+static int g450_dvi_compute(void* md, struct my_timming* mt) {
+ MINFO_FROM(md);
+
+ if (mt->mnp < 0) {
+ mt->mnp = matroxfb_g450_setclk(PMINFO mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
+ mt->pixclock = g450_mnp2f(PMINFO mt->mnp);
+ }
+ return 0;
}
-static struct matroxfb_driver g450 = {
- .name = "Matrox G450 output #2",
- .probe = matroxfb_g450_probe,
- .remove = matroxfb_g450_remove };
+static struct matrox_altout matroxfb_g450_altout = {
+ .name = "Secondary output",
+ .compute = matroxfb_g450_compute,
+ .program = matroxfb_g450_program,
+ .verifymode = matroxfb_g450_verify_mode,
+};
-static int matroxfb_g450_init(void) {
- matroxfb_register_driver(&g450);
- return 0;
+static struct matrox_altout matroxfb_g450_dvi = {
+ .name = "DVI output",
+ .compute = g450_dvi_compute,
+};
+
+void matroxfb_g450_connect(WPMINFO2) {
+ if (ACCESS_FBINFO(devflags.g450dac)) {
+ down_write(&ACCESS_FBINFO(altout.lock));
+ ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC1;
+ ACCESS_FBINFO(outputs[1]).data = MINFO;
+ ACCESS_FBINFO(outputs[1]).output = &matroxfb_g450_altout;
+ ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+ ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_CRTC1;
+ ACCESS_FBINFO(outputs[2]).data = MINFO;
+ ACCESS_FBINFO(outputs[2]).output = &matroxfb_g450_dvi;
+ ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+ up_write(&ACCESS_FBINFO(altout.lock));
+ }
}
-static void matroxfb_g450_exit(void) {
- matroxfb_unregister_driver(&g450);
+void matroxfb_g450_shutdown(WPMINFO2) {
+ if (ACCESS_FBINFO(devflags.g450dac)) {
+ down_write(&ACCESS_FBINFO(altout.lock));
+ ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE;
+ ACCESS_FBINFO(outputs[1]).output = NULL;
+ ACCESS_FBINFO(outputs[1]).data = NULL;
+ ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+ ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_NONE;
+ ACCESS_FBINFO(outputs[2]).output = NULL;
+ ACCESS_FBINFO(outputs[2]).data = NULL;
+ ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+ up_write(&ACCESS_FBINFO(altout.lock));
+ }
}
-MODULE_AUTHOR("(c) 2000-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Matrox G450 secondary output driver");
+EXPORT_SYMBOL(matroxfb_g450_connect);
+EXPORT_SYMBOL(matroxfb_g450_shutdown);
+
+MODULE_AUTHOR("(c) 2000-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Matrox G450/G550 output driver");
MODULE_LICENSE("GPL");
-module_init(matroxfb_g450_init);
-module_exit(matroxfb_g450_exit);
diff --git a/drivers/video/matrox/matroxfb_g450.h b/drivers/video/matrox/matroxfb_g450.h
index e9e4acc1ef30..98e0ce6691df 100644
--- a/drivers/video/matrox/matroxfb_g450.h
+++ b/drivers/video/matrox/matroxfb_g450.h
@@ -1,12 +1,14 @@
#ifndef __MATROXFB_G450_H__
#define __MATROXFB_G450_H__
-#include <linux/ioctl.h>
#include "matroxfb_base.h"
-struct matroxfb_g450_info {
- struct matrox_fb_info* primary_dev;
- unsigned int timmings;
-};
+#ifdef CONFIG_FB_MATROX_G450
+void matroxfb_g450_connect(WPMINFO2);
+void matroxfb_g450_shutdown(WPMINFO2);
+#else
+static inline void matroxfb_g450_connect(WPMINFO2) { };
+static inline void matroxfb_g450_shutdown(WPMINFO2) { };
+#endif
-#endif /* __MATROXFB_MAVEN_H__ */
+#endif /* __MATROXFB_G450_H__ */
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 70e51e7e2d7e..02bc8d68378f 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
*
- * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2001/11/29
+ * Version: 1.64 2002/06/10
*
* See matroxfb_base.c for contributors.
*
@@ -22,18 +22,12 @@
#define MAVEN_I2CID (0x1B)
-#define MODE_PAL MATROXFB_OUTPUT_MODE_PAL
-#define MODE_NTSC MATROXFB_OUTPUT_MODE_NTSC
-#define MODE_TV(x) (((x) == MODE_PAL) || ((x) == MODE_NTSC))
-#define MODE_MONITOR MATROXFB_OUTPUT_MODE_MONITOR
-
#define MGATVO_B 1
#define MGATVO_C 2
struct maven_data {
struct matrox_fb_info* primary_head;
struct i2c_client* client;
- int mode;
int version;
};
@@ -127,7 +121,7 @@ static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
fwant = htotal * vtotal;
fmax = pll->vco_freq_max / ctl->den;
- printk(KERN_DEBUG "want: %u, xtal: %u, h: %u, v: %u, fmax: %u\n",
+ dprintk(KERN_DEBUG "want: %u, xtal: %u, h: %u, v: %u, fmax: %u\n",
fwant, fxtal, htotal, vtotal, fmax);
for (p = 1; p <= pll->post_shift_max; p++) {
if (fwant * 2 > fmax)
@@ -163,9 +157,9 @@ static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
ln = ln - scrlen;
if (ln > htotal)
continue;
- printk(KERN_DEBUG "Match: %u / %u / %u / %u\n", n, m, p, ln);
+ dprintk(KERN_DEBUG "Match: %u / %u / %u / %u\n", n, m, p, ln);
if (ln > besth2) {
- printk(KERN_DEBUG "Better...\n");
+ dprintk(KERN_DEBUG "Better...\n");
*h2 = besth2 = ln;
*post = p;
*in = m;
@@ -221,6 +215,13 @@ static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
return;
}
+static unsigned char maven_compute_deflicker (const struct maven_data* md) {
+ unsigned char df;
+
+ df = (md->version == MGATVO_B?0x40:0x00);
+ return df;
+}
+
static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* data) {
static struct mavenregs palregs = { {
0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */
@@ -273,7 +274,7 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat
0x3F, 0x03, /* 3C-3D */
0x00, /* 3E written multiple times */
0x00, /* 3F not written */
- }, MODE_PAL, 625, 50 };
+ }, MATROXFB_OUTPUT_MODE_PAL, 625, 50 };
static struct mavenregs ntscregs = { {
0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
0x00,
@@ -325,14 +326,16 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat
0x3C, 0x00, /* 3C-3D */
0x00, /* 3E written multiple times */
0x00, /* never written */
- }, MODE_NTSC, 525, 60 };
+ }, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 };
+ MINFO_FROM(md->primary_head);
- if (md->mode & MODE_PAL)
+ if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_PAL)
*data = palregs;
else
*data = ntscregs;
- data->regs[0x93] = 0xA2;
+ /* Set deflicker */
+ data->regs[0x93] = maven_compute_deflicker(md);
/* gamma correction registers */
data->regs[0x83] = 0x00;
@@ -386,7 +389,7 @@ static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
LRP(0x17);
LR(0x0B);
LR(0x0C);
- if (m->mode & MODE_PAL) {
+ if (m->mode == MATROXFB_OUTPUT_MODE_PAL) {
maven_set_reg(c, 0x35, 0x10); /* ... */
} else {
maven_set_reg(c, 0x35, 0x0F); /* ... */
@@ -424,7 +427,7 @@ static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
LR(0x27);
LR(0x21);
LRP(0x2A);
- if (m->mode & MODE_PAL)
+ if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
maven_set_reg(c, 0x35, 0x1D); /* ... */
else
maven_set_reg(c, 0x35, 0x1C);
@@ -473,7 +476,7 @@ static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
LR(0xC2);
maven_get_reg(c, 0x8D);
- maven_set_reg(c, 0x8D, 0x00);
+ maven_set_reg(c, 0x8D, 0x04);
LR(0x20); /* saturation #1 */
LR(0x22); /* saturation #2 */
@@ -498,7 +501,7 @@ static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
LR(0x8B);
val = maven_get_reg(c, 0x8D);
- val &= 0x10; /* 0x10 or anything ored with it */
+ val &= 0x14; /* 0x10 or anything ored with it */
maven_set_reg(c, 0x8D, val);
LR(0x33);
@@ -524,7 +527,7 @@ static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
LR(0x27);
LR(0x21);
LRP(0x2A);
- if (m->mode & MODE_PAL)
+ if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
maven_set_reg(c, 0x35, 0x1D);
else
maven_set_reg(c, 0x35, 0x1C);
@@ -562,7 +565,7 @@ static int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
unsigned int a, b, c, h2;
unsigned int h = ht + 2 + x;
- if (!matroxfb_mavenclock((m->mode & MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
+ if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
unsigned int diff = h - h2;
if (diff < err) {
@@ -583,9 +586,10 @@ static inline int maven_compute_timming(struct maven_data* md,
struct mavenregs* m) {
unsigned int tmpi;
unsigned int a, bv, c;
+ MINFO_FROM(md->primary_head);
- m->mode = md->mode;
- if (MODE_TV(md->mode)) {
+ m->mode = ACCESS_FBINFO(outputs[1]).mode;
+ if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) {
unsigned int lmargin;
unsigned int umargin;
unsigned int vslen;
@@ -804,7 +808,7 @@ static inline int maven_compute_timming(struct maven_data* md,
m->regs[0xB0] = 0x03; /* output: monitor */
m->regs[0xB1] = 0xA0; /* ??? */
m->regs[0x8C] = 0x20; /* must be set... */
- m->regs[0x8D] = 0x00; /* defaults to 0x10: test signal */
+ m->regs[0x8D] = 0x04; /* defaults to 0x10: test signal */
m->regs[0xB9] = 0x1A; /* defaults to 0x2C: too bright */
m->regs[0xBF] = 0x22; /* makes picture stable */
@@ -815,7 +819,7 @@ static inline int maven_program_timming(struct maven_data* md,
const struct mavenregs* m) {
struct i2c_client* c = md->client;
- if (m->mode & MODE_MONITOR) {
+ if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
LR(0x80);
LR(0x81);
LR(0x82);
@@ -855,22 +859,16 @@ static inline int maven_resync(struct maven_data* md) {
return 0;
}
-static int maven_set_output_mode(struct maven_data* md, u_int32_t arg) {
+static int maven_verify_output_mode(struct maven_data* md, u_int32_t arg) {
switch (arg) {
case MATROXFB_OUTPUT_MODE_PAL:
case MATROXFB_OUTPUT_MODE_NTSC:
case MATROXFB_OUTPUT_MODE_MONITOR:
- md->mode = arg;
- return 1;
+ return 0;
}
return -EINVAL;
}
-static int maven_get_output_mode(struct maven_data* md, u_int32_t *arg) {
- *arg = md->mode;
- return 0;
-}
-
/******************************************************/
static int maven_out_compute(void* md, struct my_timming* mt) {
@@ -893,48 +891,31 @@ static int maven_out_start(void* md) {
return maven_resync(md);
}
-static void maven_out_incuse(void* md) {
- if (md)
- i2c_inc_use_client(((struct maven_data*)md)->client);
-}
-
-static void maven_out_decuse(void* md) {
- if (md)
- i2c_dec_use_client(((struct maven_data*)md)->client);
-}
-
-static int maven_out_set_mode(void* md, u_int32_t arg) {
- return maven_set_output_mode(md, arg);
-}
-
-static int maven_out_get_mode(void* md, u_int32_t* arg) {
- return maven_get_output_mode(md, arg);
+static int maven_out_verify_mode(void* md, u_int32_t arg) {
+ return maven_verify_output_mode(md, arg);
}
static struct matrox_altout maven_altout = {
- maven_out_compute,
- maven_out_program,
- maven_out_start,
- maven_out_incuse,
- maven_out_decuse,
- maven_out_set_mode,
- maven_out_get_mode
+ .name = "Secondary output",
+ .compute = maven_out_compute,
+ .program = maven_out_program,
+ .start = maven_out_start,
+ .verifymode = maven_out_verify_mode,
};
static int maven_init_client(struct i2c_client* clnt) {
struct i2c_adapter* a = clnt->adapter;
struct maven_data* md = clnt->data;
- struct matroxfb_dh_maven_info* m2info __attribute__((unused)) = ((struct i2c_bit_adapter*)a)->minfo;
- MINFO_FROM(m2info->primary_dev);
+ MINFO_FROM(container_of(a, struct i2c_bit_adapter, adapter)->minfo);
- md->mode = MODE_MONITOR;
md->primary_head = MINFO;
md->client = clnt;
down_write(&ACCESS_FBINFO(altout.lock));
- ACCESS_FBINFO(altout.device) = md;
- ACCESS_FBINFO(altout.output) = &maven_altout;
+ ACCESS_FBINFO(outputs[1]).output = &maven_altout;
+ ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE;
+ ACCESS_FBINFO(outputs[1]).data = md;
+ ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
up_write(&ACCESS_FBINFO(altout.lock));
- ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY;
if (maven_get_reg(clnt, 0xB2) < 0x14) {
md->version = MGATVO_B;
} else {
@@ -947,13 +928,14 @@ static int maven_shutdown_client(struct i2c_client* clnt) {
struct maven_data* md = clnt->data;
if (md->primary_head) {
- md->primary_head->output.all &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- md->primary_head->output.ph &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- md->primary_head->output.sh &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
- down_write(&md->primary_head->altout.lock);
- md->primary_head->altout.device = NULL;
- md->primary_head->altout.output = NULL;
- up_write(&md->primary_head->altout.lock);
+ MINFO_FROM(md->primary_head);
+
+ down_write(&ACCESS_FBINFO(altout.lock));
+ ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE;
+ ACCESS_FBINFO(outputs[1]).output = NULL;
+ ACCESS_FBINFO(outputs[1]).data = NULL;
+ ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
+ up_write(&ACCESS_FBINFO(altout.lock));
md->primary_head = NULL;
}
return 0;
@@ -983,7 +965,7 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, unsigne
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_PROTOCOL_MANGLING))
goto ERROR0;
- if (!(new_client = (struct i2c_client*)kmalloc(sizeof(struct i2c_client) + sizeof(struct maven_data),
+ if (!(new_client = (struct i2c_client*)kmalloc(sizeof(*new_client) + sizeof(*data),
GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
@@ -1066,7 +1048,7 @@ static void matroxfb_maven_exit(void) {
i2c_del_driver(&maven_driver);
}
-MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
MODULE_LICENSE("GPL");
module_init(matroxfb_maven_init);
diff --git a/drivers/video/matrox/matroxfb_maven.h b/drivers/video/matrox/matroxfb_maven.h
index 060aa0b81864..99eddec9f30c 100644
--- a/drivers/video/matrox/matroxfb_maven.h
+++ b/drivers/video/matrox/matroxfb_maven.h
@@ -6,21 +6,15 @@
#include <linux/i2c-algo-bit.h>
#include "matroxfb_base.h"
-struct matroxfb_dh_maven_info;
-
struct i2c_bit_adapter {
struct i2c_adapter adapter;
int initialized;
struct i2c_algo_bit_data bac;
- struct matroxfb_dh_maven_info *minfo;
-};
-
-struct matroxfb_dh_maven_info {
- struct matrox_fb_info* primary_dev;
-
- struct i2c_bit_adapter maven;
- struct i2c_bit_adapter ddc1;
- struct i2c_bit_adapter ddc2;
+ struct matrox_fb_info* minfo;
+ struct {
+ unsigned int data;
+ unsigned int clock;
+ } mask;
};
#endif /* __MATROXFB_MAVEN_H__ */
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index 49a00835203f..18518d53d099 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
*
- * (c) 1998,1999,2000,2001 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
- * Version: 1.62 2001/11/29
+ * Version: 1.65 2002/08/14
*
* MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
*
@@ -146,6 +146,7 @@ void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
mt->pixclock = 1000000000 / pixclock;
if (mt->pixclock < 1) mt->pixclock = 1;
+ mt->mnp = -1;
mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
mt->HDisplay = var->xres;
@@ -226,7 +227,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) {
unsigned int wd;
unsigned int divider;
int i;
- int text = p->type == FB_TYPE_TEXT;
+ int text = ACCESS_FBINFO(fbcon).fix.type == FB_TYPE_TEXT;
int fwidth;
struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
@@ -360,7 +361,8 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) {
((hd & 0x100) >> 7) | /* blanking */
((hs & 0x100) >> 6) | /* sync start */
(hbe & 0x040); /* end hor. blanking */
- if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY)
+ /* FIXME: Enable vidrst only on G400, and only if TV-out is used */
+ if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1)
hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */
hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) |
((vd & 0x400) >> 8) | /* disp end */
@@ -872,7 +874,7 @@ static int parse_pins5(WPMINFO const struct matrox_bios* bd) {
mult = bd->pins[4]?8000:6000;
MINFO->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult;
- MINFO->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 39] * mult;
+ MINFO->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 36] * mult;
MINFO->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? MINFO->limits.system.vcomax : bd->pins[ 37] * mult;
MINFO->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult;
MINFO->limits.system.vcomin = (bd->pins[121] == 0xFF) ? MINFO->limits.pixel.vcomin : bd->pins[121] * mult;
@@ -1011,6 +1013,6 @@ EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */
EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */
EXPORT_SYMBOL(matroxfb_read_pins);
-MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
MODULE_LICENSE("GPL");