From 48800d9e5d8dcf8169c8c444ffedee5907213921 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:01:28 +0200 Subject: Support secondary head DDC on G450/G550. Simplify i2c-matroxfb code. --- drivers/video/matrox/i2c-matroxfb.c | 259 +++++++++------------------------- drivers/video/matrox/matroxfb_base.c | 20 +-- drivers/video/matrox/matroxfb_base.h | 1 + drivers/video/matrox/matroxfb_maven.c | 3 +- drivers/video/matrox/matroxfb_maven.h | 16 +-- 5 files changed, 80 insertions(+), 219 deletions(-) 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 + * (c) 1998-2002 Petr Vandrovec * - * 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 "); +MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec "); MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards"); module_init(i2c_matroxfb_init); diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 9912fa946907..1f6f779fe6c7 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 + * (c) 1998-2002 Petr Vandrovec * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.62 2001/11/29 + * Version: 1.64 2002/06/10 * * MTRR stuff: 1998 Tom Rini * @@ -1392,10 +1392,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 +1405,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; @@ -1611,12 +1611,12 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ 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.dualhead) = (b->flags & DEVF_DUALHEAD) != 0; if (b->flags & DEVF_PANELLINK_CAPABLE) { ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_DFP; if (dfp) ACCESS_FBINFO(output.ph) |= MATROXFB_OUTPUT_CONN_DFP; - } - if (b->flags & DEVF_BOTHDACS) { + } else if (b->flags & DEVF_DUALHEAD) { #ifdef CONFIG_FB_MATROX_G450 ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY; ACCESS_FBINFO(output.ph) |= MATROXFB_OUTPUT_CONN_SECONDARY; diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 5ad1962a3d00..1fd9852de7a0 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -541,6 +541,7 @@ struct matrox_fb_info { int memtype; int g450dac; int dfp_type; + int dualhead; unsigned int fbResource; } devflags; struct display_switch dispsw; diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 70e51e7e2d7e..b20043a628bf 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -924,8 +924,7 @@ static struct matrox_altout maven_altout = { 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(((struct i2c_bit_adapter*)a)->minfo); md->mode = MODE_MONITOR; md->primary_head = MINFO; 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 #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__ */ -- cgit v1.2.3 From ce31e58a95cf192b26e8d96c3d35f5caa856f219 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:04:20 +0200 Subject: Make secondary output support mandatory for Matrox G450/G550. --- drivers/video/Config.help | 49 ++++++++++------------- drivers/video/Config.in | 9 ++++- drivers/video/matrox/Makefile | 6 +-- drivers/video/matrox/matroxfb_base.c | 4 ++ drivers/video/matrox/matroxfb_g450.c | 77 ++++++++++-------------------------- drivers/video/matrox/matroxfb_g450.h | 11 +++++- 6 files changed, 65 insertions(+), 91 deletions(-) diff --git a/drivers/video/Config.help b/drivers/video/Config.help index 21c25f78749a..6e334b9e00ae 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,26 @@ 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. + + 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... +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 +484,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 ) 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/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 1f6f779fe6c7..eb12ce039ffb 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -100,6 +100,7 @@ #include "matroxfb_Ti3026.h" #include "matroxfb_maven.h" #include "matroxfb_crtc2.h" +#include "matroxfb_g450.h" #include #include @@ -212,6 +213,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)) @@ -1732,6 +1734,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 +1888,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)); diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index f07d3b26209b..314343038afb 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -71,76 +71,41 @@ static struct matrox_altout matroxfb_g450_altout = { matroxfb_g450_get_mode }; -static int matroxfb_g450_connect(struct matroxfb_g450_info* m2info) { - MINFO_FROM(m2info->primary_dev); - - 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); - return 0; -} - -static void matroxfb_g450_shutdown(struct matroxfb_g450_info* m2info) { - MINFO_FROM(m2info->primary_dev); - - 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; - } -} - -/* we do not have __setup() yet */ -static void* matroxfb_g450_probe(struct matrox_fb_info* minfo) { +void matroxfb_g450_connect(WPMINFO2) { struct matroxfb_g450_info* m2info; - + /* hardware is not G450... */ if (!ACCESS_FBINFO(devflags.g450dac)) - return NULL; + return; 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; + return; } memset(m2info, 0, sizeof(*m2info)); + down_write(&ACCESS_FBINFO(altout.lock)); m2info->primary_dev = MINFO; - if (matroxfb_g450_connect(m2info)) { - kfree(m2info); - printk(KERN_ERR "matroxfb_g450: G450 DAC failed to initialize\n"); - return NULL; - } - return m2info; -} - -static void matroxfb_g450_remove(struct matrox_fb_info* minfo, void* g450) { - matroxfb_g450_shutdown(g450); - kfree(g450); + 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); } -static struct matroxfb_driver g450 = { - .name = "Matrox G450 output #2", - .probe = matroxfb_g450_probe, - .remove = matroxfb_g450_remove }; - -static int matroxfb_g450_init(void) { - matroxfb_register_driver(&g450); - return 0; +void matroxfb_g450_shutdown(WPMINFO2) { + 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)); + kfree(ACCESS_FBINFO(altout.device)); + ACCESS_FBINFO(altout.device) = NULL; + ACCESS_FBINFO(altout.output) = NULL; + up_write(&ACCESS_FBINFO(altout.lock)); } -static void matroxfb_g450_exit(void) { - matroxfb_unregister_driver(&g450); -} +EXPORT_SYMBOL(matroxfb_g450_connect); +EXPORT_SYMBOL(matroxfb_g450_shutdown); MODULE_AUTHOR("(c) 2000-2001 Petr Vandrovec "); MODULE_DESCRIPTION("Matrox G450 secondary 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..291a132aca3b 100644 --- a/drivers/video/matrox/matroxfb_g450.h +++ b/drivers/video/matrox/matroxfb_g450.h @@ -1,7 +1,6 @@ #ifndef __MATROXFB_G450_H__ #define __MATROXFB_G450_H__ -#include #include "matroxfb_base.h" struct matroxfb_g450_info { @@ -9,4 +8,12 @@ struct matroxfb_g450_info { unsigned int timmings; }; -#endif /* __MATROXFB_MAVEN_H__ */ +#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_G450_H__ */ -- cgit v1.2.3 From 482371ff07dd321f9705a13d57832174f7e2126e Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:08:09 +0200 Subject: Remove structure holding state of secondary output in the matroxfb driver. We do not have any state stored here. --- drivers/video/matrox/matroxfb_g450.c | 20 +++----------------- drivers/video/matrox/matroxfb_g450.h | 5 ----- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index 314343038afb..093b6d81f0e5 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -20,20 +20,16 @@ #include static int matroxfb_g450_compute(void* md, struct my_timming* mt) { -#define m2info ((struct matroxfb_g450_info*)md) -#define minfo (m2info->primary_dev) +#define minfo ((struct matrox_fb_info*)md) ACCESS_FBINFO(hw).vidclk = mt->pixclock; #undef minfo -#undef m2info return 0; } static int matroxfb_g450_program(void* md) { -#define m2info ((struct matroxfb_g450_info*)md) -#define minfo (m2info->primary_dev) +#define minfo ((struct matrox_fb_info*)md) matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(hw).vidclk, M_VIDEO_PLL); #undef minfo -#undef m2info return 0; } @@ -72,20 +68,11 @@ static struct matrox_altout matroxfb_g450_altout = { }; void matroxfb_g450_connect(WPMINFO2) { - struct matroxfb_g450_info* m2info; - /* hardware is not G450... */ if (!ACCESS_FBINFO(devflags.g450dac)) return; - 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; - } - memset(m2info, 0, sizeof(*m2info)); down_write(&ACCESS_FBINFO(altout.lock)); - m2info->primary_dev = MINFO; - ACCESS_FBINFO(altout.device) = m2info; + ACCESS_FBINFO(altout.device) = MINFO; ACCESS_FBINFO(altout.output) = &matroxfb_g450_altout; up_write(&ACCESS_FBINFO(altout.lock)); ACCESS_FBINFO(output.all) |= MATROXFB_OUTPUT_CONN_SECONDARY; @@ -97,7 +84,6 @@ void matroxfb_g450_shutdown(WPMINFO2) { ACCESS_FBINFO(output.ph) &= ~MATROXFB_OUTPUT_CONN_SECONDARY; ACCESS_FBINFO(output.sh) &= ~MATROXFB_OUTPUT_CONN_SECONDARY; down_write(&ACCESS_FBINFO(altout.lock)); - kfree(ACCESS_FBINFO(altout.device)); ACCESS_FBINFO(altout.device) = NULL; ACCESS_FBINFO(altout.output) = NULL; up_write(&ACCESS_FBINFO(altout.lock)); diff --git a/drivers/video/matrox/matroxfb_g450.h b/drivers/video/matrox/matroxfb_g450.h index 291a132aca3b..98e0ce6691df 100644 --- a/drivers/video/matrox/matroxfb_g450.h +++ b/drivers/video/matrox/matroxfb_g450.h @@ -3,11 +3,6 @@ #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); -- cgit v1.2.3 From 4bbbb253bd833fab91efa84eb3d980b01522187f Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:11:17 +0200 Subject: matroxfb: Find appropriate setting for specified color depth by looking through table instead of using if-else branches in code. Source is cleaner, and generated code is smaller with this change. By Denis Zaitsev --- drivers/video/matrox/matroxfb_base.c | 151 ++++++++++++++--------------------- 1 file changed, 62 insertions(+), 89 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index eb12ce039ffb..ccab0ce611e7 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -77,6 +77,9 @@ * "Uns Lider" * G100 PLNWT fixes * + * "Denis Zaitsev" + * Fixes + * * (following author is not in any relation with this code, but his code * is included in this driver) * @@ -406,12 +409,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; @@ -440,22 +474,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; @@ -499,88 +533,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); -- cgit v1.2.3 From ca5d84400dc390e1aac3b1d1121ba544cd00f547 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:19:37 +0200 Subject: Simplify rules for writting secondary output drivers to matroxfb. Update some initializations to use C99 initializers. --- drivers/video/matrox/matroxfb_DAC1064.c | 31 +------------------- drivers/video/matrox/matroxfb_base.c | 34 ++++++++++++++------- drivers/video/matrox/matroxfb_base.h | 6 ++-- drivers/video/matrox/matroxfb_crtc2.c | 12 ++++---- drivers/video/matrox/matroxfb_g450.c | 33 ++------------------- drivers/video/matrox/matroxfb_maven.c | 52 ++++++++++----------------------- 6 files changed, 49 insertions(+), 119 deletions(-) diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 51aad5adb819..8d252f5c7698 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -504,37 +504,8 @@ 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 int m1064_setmode(void* outdev, u_int32_t mode) { - if (mode != MATROXFB_OUTPUT_MODE_MONITOR) - return -EINVAL; - return 0; -} - static struct matrox_altout m1064 = { - m1064_compute, - m1064_program, - m1064_start, - m1064_incuse, - m1064_decuse, - m1064_setmode + .compute = m1064_compute, }; #endif /* NEED_DAC1064 */ diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index ccab0ce611e7..480310b00e3f 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -825,34 +825,34 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, 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)) + if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->compute) 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)) + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->compute) 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)) + if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->program) 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)) + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->program) ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device)); up_read(&ACCESS_FBINFO(altout.lock)); } ACCESS_FBINFO(cursor.redraw) = 1; if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { - if (ACCESS_FBINFO(primout)) + if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->start) 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)) + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->start) ACCESS_FBINFO(altout.output)->start(ACCESS_FBINFO(altout.device)); up_read(&ACCESS_FBINFO(altout.lock)); } @@ -1006,11 +1006,21 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, 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)->setmode(ACCESS_FBINFO(altout.device), mom.mode); + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.device)) { + if (ACCESS_FBINFO(altout.output)->verifymode) { + val = ACCESS_FBINFO(altout.output)->verifymode(ACCESS_FBINFO(altout.device), mom.mode); + } else { + if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) { + val = 0; + } + } + } up_read(&ACCESS_FBINFO(altout.lock)); - if (val != 1) + if (val != 0) return val; + if (ACCESS_FBINFO(altout.mode) == mom.mode) + return 0; + ACCESS_FBINFO(altout.mode) = mom.mode; 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) { @@ -1051,8 +1061,10 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, 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); + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.device)) { + mom.mode = ACCESS_FBINFO(altout.mode); + val = 0; + } up_read(&ACCESS_FBINFO(altout.lock)); if (val) return val; diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 1fd9852de7a0..61f8dbc49c32 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -399,10 +399,7 @@ struct matrox_altout { 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); }; enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 }; @@ -452,6 +449,7 @@ struct matrox_fb_info { struct matrox_altout* output; void* device; struct rw_semaphore lock; + unsigned int mode; } altout; #define MATROXFB_MAX_FB_DRIVERS 5 diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 7bc8aea94f8c..dcbdb9cc5beb 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -420,34 +420,34 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, pos += m2info->video.offbase; DAC1064_global_init(PMINFO2); if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { - if (ACCESS_FBINFO(primout)) + if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->compute) ACCESS_FBINFO(primout)->compute(MINFO, &mt); } if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); - if (ACCESS_FBINFO(altout.output)) + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->compute) ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt); up_read(&ACCESS_FBINFO(altout.lock)); } matroxfb_dh_restore(m2info, &mt, p, mode, pos); DAC1064_global_restore(PMINFO2); if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { - if (ACCESS_FBINFO(primout)) + if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->program) 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)) + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->program) 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)) + if (ACCESS_FBINFO(primout) && ACCESS_FBINFO(primout)->start) ACCESS_FBINFO(primout)->start(MINFO); } if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); - if (ACCESS_FBINFO(altout.output)) + if (ACCESS_FBINFO(altout.output) && ACCESS_FBINFO(altout.output)->start) ACCESS_FBINFO(altout.output)->start(ACCESS_FBINFO(altout.device)); up_read(&ACCESS_FBINFO(altout.lock)); } diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index 093b6d81f0e5..57ea16ea8a74 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -33,38 +33,9 @@ static int matroxfb_g450_program(void* md) { return 0; } -static int matroxfb_g450_start(void* md) { - return 0; -} - -static void matroxfb_g450_incuse(void* md) { - MOD_INC_USE_COUNT; -} - -static void matroxfb_g450_decuse(void* md) { - MOD_DEC_USE_COUNT; -} - -static int matroxfb_g450_set_mode(void* md, u_int32_t arg) { - if (arg == MATROXFB_OUTPUT_MODE_MONITOR) { - return 1; - } - return -EINVAL; -} - -static int matroxfb_g450_get_mode(void* md, u_int32_t* arg) { - *arg = MATROXFB_OUTPUT_MODE_MONITOR; - return 0; -} - 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 + .compute = matroxfb_g450_compute, + .program = matroxfb_g450_program, }; void matroxfb_g450_connect(WPMINFO2) { diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index b20043a628bf..6609e710a643 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -33,7 +33,6 @@ struct maven_data { struct matrox_fb_info* primary_head; struct i2c_client* client; - int mode; int version; }; @@ -326,8 +325,9 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat 0x00, /* 3E written multiple times */ 0x00, /* never written */ }, MODE_NTSC, 525, 60 }; - - if (md->mode & MODE_PAL) + MINFO_FROM(md->primary_head); + + if (ACCESS_FBINFO(altout.mode) == MODE_PAL) *data = palregs; else *data = ntscregs; @@ -583,9 +583,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(altout.mode); + if (MODE_TV(m->mode)) { unsigned int lmargin; unsigned int umargin; unsigned int vslen; @@ -855,22 +856,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,32 +888,15 @@ 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 + .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) { @@ -926,7 +904,7 @@ static int maven_init_client(struct i2c_client* clnt) { struct maven_data* md = clnt->data; MINFO_FROM(((struct i2c_bit_adapter*)a)->minfo); - md->mode = MODE_MONITOR; + ACCESS_FBINFO(altout.mode) = MODE_MONITOR; md->primary_head = MINFO; md->client = clnt; down_write(&ACCESS_FBINFO(altout.lock)); -- cgit v1.2.3 From daf389a02ca739972aca1d66ac18d8452d35dea5 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:20:37 +0200 Subject: Use arrays for holding Matrox output drivers, it is nicer and more extensible than current solution with per-CRTC bitmaps. --- drivers/video/matrox/matroxfb_DAC1064.c | 19 ++- drivers/video/matrox/matroxfb_Ti3026.c | 14 +- drivers/video/matrox/matroxfb_base.c | 287 ++++++++++++++++++-------------- drivers/video/matrox/matroxfb_base.h | 22 ++- drivers/video/matrox/matroxfb_crtc2.c | 189 +++++++++++++-------- drivers/video/matrox/matroxfb_g450.c | 33 ++-- drivers/video/matrox/matroxfb_maven.c | 28 ++-- drivers/video/matrox/matroxfb_misc.c | 3 +- 8 files changed, 349 insertions(+), 246 deletions(-) diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 8d252f5c7698..806334dfba00 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -300,7 +300,7 @@ void DAC1064_global_init(WPMINFO2) { 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(outputs[1]).src == MATROXFB_SRC_CRTC1) { 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 */ @@ -308,15 +308,15 @@ void DAC1064_global_init(WPMINFO2) { 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) { + } else if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) { 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) + } 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) + if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE) hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; } @@ -505,6 +505,7 @@ static int m1064_compute(void* outdev, struct my_timming* m) { } static struct matrox_altout m1064 = { + .name = "Primary output", .compute = m1064_compute, }; @@ -651,7 +652,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 */ @@ -835,7 +839,10 @@ 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; + 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 diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 57b37600a3cb..fb1c494f530c 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 + * (c) 1998-2002 Petr Vandrovec * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.62 2000/11/29 + * Version: 1.64 2002/06/10 * * MTRR stuff: 1998 Tom Rini * @@ -84,6 +84,7 @@ #include "matroxfb_Ti3026.h" #include "matroxfb_misc.h" #include "matroxfb_accel.h" +#include #ifdef CONFIG_FB_MATROX_MILLENIUM #define outTi3026 matroxfb_DAC_out @@ -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_base.c b/drivers/video/matrox/matroxfb_base.c index 480310b00e3f..d298df866ebe 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -793,6 +793,7 @@ 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); /* CRTC1 delays */ @@ -809,6 +810,14 @@ 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(hw_switch->init(PMINFO &mt, display)); if (display->type == FB_TYPE_TEXT) { if (fontheight(display)) @@ -824,38 +833,22 @@ 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) - 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.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) - 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.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) - 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.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); + } } + up_read(&ACCESS_FBINFO(altout).lock); matrox_cfbX_init(PMINFO display); my_install_cmap(PMINFO2); } @@ -964,6 +957,10 @@ static int matroxfb_get_vblank(CPMINFO struct fb_vblank *vblank) 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) @@ -991,92 +988,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)) { - if (ACCESS_FBINFO(altout.output)->verifymode) { - val = ACCESS_FBINFO(altout.output)->verifymode(ACCESS_FBINFO(altout.device), mom.mode); - } else { - if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) { - val = 0; - } - } - } - up_read(&ACCESS_FBINFO(altout.lock)); - if (val != 0) - return val; - if (ACCESS_FBINFO(altout.mode) == mom.mode) - return 0; - ACCESS_FBINFO(altout.mode) = mom.mode; - 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 = (struct matroxfb_dh_fb_info*)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)) { - mom.mode = ACCESS_FBINFO(altout.mode); - val = 0; - } - 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; @@ -1084,47 +1063,104 @@ 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 (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; + } + } + } } - if (tmp == ACCESS_FBINFO(output.ph)) + 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; } @@ -1600,17 +1636,14 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ ACCESS_FBINFO(devflags.maven_capable) = b->flags & DEVF_MAVEN_CAPABLE; 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; - } else if (b->flags & DEVF_DUALHEAD) { -#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; @@ -2061,10 +2094,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 @@ -2478,8 +2507,8 @@ int __init matroxfb_init(void) /* *************************** init module code **************************** */ -MODULE_AUTHOR("(c) 1998-2001 Petr Vandrovec "); -MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450"); +MODULE_AUTHOR("(c) 1998-2002 Petr Vandrovec "); +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 61f8dbc49c32..781d5d428cc7 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -396,12 +396,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); 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 { @@ -435,22 +440,20 @@ 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; struct { struct fb_info* info; struct rw_semaphore lock; } crtc2; struct { + struct rw_semaphore lock; + } altout; +#define MATROXFB_MAX_OUTPUTS 3 + struct { + unsigned int src; struct matrox_altout* output; - void* device; - struct rw_semaphore lock; + void* data; unsigned int mode; - } altout; + } outputs[MATROXFB_MAX_OUTPUTS]; #define MATROXFB_MAX_FB_DRIVERS 5 struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]); @@ -539,6 +542,7 @@ 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; diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index dcbdb9cc5beb..2e99d553e111 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -118,25 +118,22 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, 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 */ - } - } else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { - tmp |= 0x00000004; /* source from pixclock */ - /* PIXPLL is our clock source */ + tmp |= 0x00000001; /* enable CRTC2 */ + if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) { + 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 */ } - - 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 */ @@ -172,6 +169,12 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, mga_outl(0x3C4C, 0); /* data control */ } +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 */ +} + static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info, struct display* p) { /* no acceleration for secondary head... */ @@ -411,6 +414,8 @@ 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); /* CRTC2 delay */ @@ -418,39 +423,38 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, pos = (var->yoffset * var->xres_virtual + var->xoffset) * 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) - 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.output)->compute(ACCESS_FBINFO(altout.device), &mt); - up_read(&ACCESS_FBINFO(altout.lock)); + up_read(&ACCESS_FBINFO(altout).lock); + if (cnt) { + matroxfb_dh_restore(m2info, &mt, p, 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) - 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.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) - 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.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); + } } + up_read(&ACCESS_FBINFO(altout).lock); matroxfb_dh_cfbX_init(m2info, p); my_install_cmap(m2info); } @@ -563,38 +567,84 @@ 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; @@ -730,11 +780,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); @@ -839,7 +888,7 @@ static void matroxfb_crtc2_exit(void) { matroxfb_unregister_driver(&crtc2); } -MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec "); +MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec "); MODULE_DESCRIPTION("Matrox G400 CRTC2 driver"); MODULE_LICENSE("GPL"); module_init(matroxfb_crtc2_init); diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index 57ea16ea8a74..5dafef4296b6 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -34,30 +34,31 @@ static int matroxfb_g450_program(void* md) { } static struct matrox_altout matroxfb_g450_altout = { + .name = "Secondary output", .compute = matroxfb_g450_compute, .program = matroxfb_g450_program, }; void matroxfb_g450_connect(WPMINFO2) { - /* hardware is not G450... */ - if (!ACCESS_FBINFO(devflags.g450dac)) - return; - down_write(&ACCESS_FBINFO(altout.lock)); - ACCESS_FBINFO(altout.device) = MINFO; - 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); + 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; + up_write(&ACCESS_FBINFO(altout.lock)); + } } void matroxfb_g450_shutdown(WPMINFO2) { - 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)); + 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; + up_write(&ACCESS_FBINFO(altout.lock)); + } } EXPORT_SYMBOL(matroxfb_g450_connect); diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 6609e710a643..36ce5851d8e9 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -327,7 +327,7 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat }, MODE_NTSC, 525, 60 }; MINFO_FROM(md->primary_head); - if (ACCESS_FBINFO(altout.mode) == MODE_PAL) + if (ACCESS_FBINFO(outputs[1]).mode == MODE_PAL) *data = palregs; else *data = ntscregs; @@ -585,7 +585,7 @@ static inline int maven_compute_timming(struct maven_data* md, unsigned int a, bv, c; MINFO_FROM(md->primary_head); - m->mode = ACCESS_FBINFO(altout.mode); + m->mode = ACCESS_FBINFO(outputs[1]).mode; if (MODE_TV(m->mode)) { unsigned int lmargin; unsigned int umargin; @@ -893,6 +893,7 @@ static int maven_out_verify_mode(void* md, u_int32_t arg) { } static struct matrox_altout maven_altout = { + .name = "Secondary output", .compute = maven_out_compute, .program = maven_out_program, .start = maven_out_start, @@ -904,14 +905,14 @@ static int maven_init_client(struct i2c_client* clnt) { struct maven_data* md = clnt->data; MINFO_FROM(((struct i2c_bit_adapter*)a)->minfo); - ACCESS_FBINFO(altout.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 = 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 { @@ -924,13 +925,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; diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index 49a00835203f..6bcf115eff0e 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -360,7 +360,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 */ -- cgit v1.2.3 From d5f14f252ee74dad4fdd5a7efce7fb5851df7f11 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:21:59 +0200 Subject: Store pointer to matroxfb specific fb information instead of universal fb_info* pointer for secondary head. Saves some typecasts. --- drivers/video/matrox/matroxfb_base.c | 2 +- drivers/video/matrox/matroxfb_base.h | 3 ++- drivers/video/matrox/matroxfb_crtc2.c | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index d298df866ebe..e3fdb757aa6c 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1026,7 +1026,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, 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->fbcon.currcon, &crtc2->fbcon); up_read(&ACCESS_FBINFO(crtc2.lock)); diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 781d5d428cc7..11980a00d50d 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -423,6 +423,7 @@ struct matrox_bios { struct matrox_switch; struct matroxfb_driver; +struct matroxfb_dh_fb_info; struct matrox_fb_info { /* fb_info must be first */ @@ -441,7 +442,7 @@ struct matrox_fb_info { struct pci_dev* pcidev; struct { - struct fb_info* info; + struct matroxfb_dh_fb_info* info; struct rw_semaphore lock; } crtc2; struct { diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 2e99d553e111..4fe1d1b5d4cc 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -796,7 +796,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", @@ -825,16 +825,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; } @@ -872,6 +872,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 = { -- cgit v1.2.3 From 76a21cfa0f6344a49d29a3e412595a9e86196312 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:23:10 +0200 Subject: Use container_of instead of simple typecast when we convert pointers from pointer to fb_info to pointers to matrox_fb_info. --- drivers/video/matrox/matroxfb_base.c | 28 ++++++++++++++-------------- drivers/video/matrox/matroxfb_base.h | 3 +-- drivers/video/matrox/matroxfb_crtc2.c | 31 +++++++++++++++---------------- drivers/video/matrox/matroxfb_maven.c | 2 +- 4 files changed, 31 insertions(+), 33 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index e3fdb757aa6c..d0303aa63946 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -238,7 +238,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)) { @@ -251,7 +251,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)) { @@ -263,7 +263,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") @@ -289,7 +289,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); @@ -566,7 +566,7 @@ static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green, { 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") @@ -650,7 +650,7 @@ static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct display* p; DBG("matroxfb_get_fix") -#define minfo ((struct matrox_fb_info*)info) +#define minfo (container_of(info, struct matrox_fb_info, fbcon)) if (ACCESS_FBINFO(dead)) { return -ENXIO; @@ -683,7 +683,7 @@ static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con, static int matroxfb_get_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)) DBG("matroxfb_get_var") if(con < 0) @@ -697,7 +697,7 @@ static int matroxfb_get_var(struct fb_var_screeninfo *var, int con, 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; @@ -864,7 +864,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. @@ -884,7 +884,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; @@ -910,7 +910,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") @@ -965,7 +965,7 @@ 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)) { @@ -1173,7 +1173,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 @@ -1220,7 +1220,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; diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 11980a00d50d..262c93faaf75 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -426,7 +426,6 @@ 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; @@ -622,7 +621,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), diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 4fe1d1b5d4cc..613a7e6a393a 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -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,7 +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) +#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) struct display* p; if (regno >= 16) @@ -185,8 +185,8 @@ 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; @@ -197,7 +197,6 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, } else { mga_outl(0x3C28, pos); } -#undef minfo } static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info, @@ -301,7 +300,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) { @@ -314,7 +313,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) { @@ -325,7 +324,7 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { 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) +#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) struct display* p; if (con >= 0) @@ -354,7 +353,7 @@ static int matroxfb_dh_get_fix(struct fb_fix_screeninfo* fix, int con, 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) +#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon)) if (con < 0) *var = m2info->fbcon.disp->var; else @@ -365,7 +364,7 @@ static int matroxfb_dh_get_var(struct fb_var_screeninfo* var, int con, 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; @@ -464,7 +463,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) @@ -483,7 +482,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) @@ -507,7 +506,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; @@ -540,7 +539,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") @@ -655,7 +654,7 @@ static int matroxfb_dh_ioctl(struct inode* inode, } 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: @@ -684,7 +683,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; @@ -707,7 +706,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 diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 36ce5851d8e9..0932726f1136 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -903,7 +903,7 @@ static struct matrox_altout maven_altout = { static int maven_init_client(struct i2c_client* clnt) { struct i2c_adapter* a = clnt->adapter; struct maven_data* md = clnt->data; - MINFO_FROM(((struct i2c_bit_adapter*)a)->minfo); + MINFO_FROM(container_of(a, struct i2c_bit_adapter, adapter)->minfo); md->primary_head = MINFO; md->client = clnt; -- cgit v1.2.3 From 9f8213f917d3223a2b377342af2668cc60e87fb5 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:24:08 +0200 Subject: Initialize Matrox G100 and G400 hardware with values read from BIOS instead of with failsafe settings discovered in the past. Fixes corrupted screen display on some G100. --- drivers/video/matrox/matroxfb_DAC1064.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 806334dfba00..e9deac8c1426 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -873,8 +873,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); @@ -925,17 +924,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); -- cgit v1.2.3 From 705e41f82988ce8e4eb5473f89908279fb4ca67f Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:30:01 +0200 Subject: matroxfb DVI updates: Handle DVI output on G450/G550. Powerdown unused portions of G450/G550 DAC. Split G450/G550 DAC from older DAC1064 handling. Modify PLL setting when both CRTCs use same pixel clocks. --- drivers/video/matrox/g450_pll.c | 85 ++++++----- drivers/video/matrox/g450_pll.h | 2 + drivers/video/matrox/matroxfb_DAC1064.c | 258 ++++++++++++++++++++++++-------- drivers/video/matrox/matroxfb_DAC1064.h | 4 +- drivers/video/matrox/matroxfb_base.c | 3 + drivers/video/matrox/matroxfb_base.h | 19 ++- drivers/video/matrox/matroxfb_crtc2.c | 26 +++- drivers/video/matrox/matroxfb_g450.c | 41 ++++- drivers/video/matrox/matroxfb_misc.c | 1 + 9 files changed, 323 insertions(+), 116 deletions(-) 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 + * (c) 2001-2002 Petr Vandrovec * * 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 "); +MODULE_AUTHOR("(c) 2001-2002 Petr Vandrovec "); 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/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index e9deac8c1426..2656bdca4e76 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -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(outputs[1]).src == MATROXFB_SRC_CRTC1) { - 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(outputs[1]).src == MATROXFB_SRC_CRTC2) { - 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(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; + } 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(outputs[0]).src != MATROXFB_SRC_NONE) - 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,8 +445,9 @@ 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]); } } @@ -368,13 +485,13 @@ 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; } @@ -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; @@ -505,8 +617,25 @@ static int m1064_compute(void* outdev, struct my_timming* m) { } static struct matrox_altout m1064 = { - .name = "Primary output", - .compute = m1064_compute, + .name = "Primary output", + .compute = m1064_compute, +}; + +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 g450out = { + .name = "Primary output", + .compute = g450_compute, }; #endif /* NEED_DAC1064 */ @@ -701,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); @@ -839,7 +973,11 @@ static int MGAG100_preinit(WPMINFO2) { ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 ? ACCESS_FBINFO(devflags.sgram) : 1; - ACCESS_FBINFO(outputs[0]).output = &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; 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_base.c b/drivers/video/matrox/matroxfb_base.c index d0303aa63946..f44dd4ec0463 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -796,6 +796,7 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, 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; @@ -818,6 +819,8 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, } } 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 (fontheight(display)) diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 262c93faaf75..cd456aa2b349 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.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 { @@ -441,7 +444,13 @@ struct matrox_fb_info { struct pci_dev* pcidev; struct { - struct matroxfb_dh_fb_info* info; + unsigned int pixclock; + int mnp; + } crtc1; + struct { + unsigned int pixclock; + int mnp; + struct matroxfb_dh_fb_info* info; struct rw_semaphore lock; } crtc2; struct { diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 613a7e6a393a..a4e0121fc91f 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -142,7 +142,7 @@ 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 */ + 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)); @@ -150,7 +150,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, 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) { + 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 */ @@ -160,19 +160,36 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, } mga_outl(0x3C40, linelen); } + mga_outl(0x3C4C, 0); /* 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_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, @@ -417,6 +434,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, int cnt; matroxfb_var2my(var, &mt); + mt.crtc = MATROXFB_SRC_CRTC2; /* CRTC2 delay */ mt.delay = 34; @@ -432,6 +450,8 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, } } } + 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, p, mode, pos); diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index 5dafef4296b6..1399947ee413 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -20,16 +20,28 @@ #include static int matroxfb_g450_compute(void* md, struct my_timming* mt) { -#define minfo ((struct matrox_fb_info*)md) - ACCESS_FBINFO(hw).vidclk = mt->pixclock; -#undef minfo + MINFO_FROM(md); + + 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); + } return 0; } static int matroxfb_g450_program(void* md) { -#define minfo ((struct matrox_fb_info*)md) - matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(hw).vidclk, M_VIDEO_PLL); -#undef minfo + return 0; +} + +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; } @@ -39,6 +51,11 @@ static struct matrox_altout matroxfb_g450_altout = { .program = matroxfb_g450_program, }; +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)); @@ -46,6 +63,10 @@ void matroxfb_g450_connect(WPMINFO2) { 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)); } } @@ -57,6 +78,10 @@ void matroxfb_g450_shutdown(WPMINFO2) { 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)); } } @@ -64,6 +89,6 @@ void matroxfb_g450_shutdown(WPMINFO2) { EXPORT_SYMBOL(matroxfb_g450_connect); EXPORT_SYMBOL(matroxfb_g450_shutdown); -MODULE_AUTHOR("(c) 2000-2001 Petr Vandrovec "); -MODULE_DESCRIPTION("Matrox G450 secondary output driver"); +MODULE_AUTHOR("(c) 2000-2002 Petr Vandrovec "); +MODULE_DESCRIPTION("Matrox G450/G550 output driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index 6bcf115eff0e..55a67890de9b 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -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; -- cgit v1.2.3 From b0f3e5d467f5724e403dc241d622a1e6c8d18962 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:32:33 +0200 Subject: Add TV-Out support for Matrox G450/G550. Due to the hardware only secondary CRTC can be used as a source for TV output. --- drivers/video/Config.help | 9 + drivers/video/matrox/matroxfb_crtc2.c | 22 ++- drivers/video/matrox/matroxfb_crtc2.h | 2 + drivers/video/matrox/matroxfb_g450.c | 333 +++++++++++++++++++++++++++++++++- 4 files changed, 356 insertions(+), 10 deletions(-) diff --git a/drivers/video/Config.help b/drivers/video/Config.help index 6e334b9e00ae..7a079fff6d58 100644 --- a/drivers/video/Config.help +++ b/drivers/video/Config.help @@ -425,12 +425,21 @@ CONFIG_FB_MATROX_G450 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 ) 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). + 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 diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index a4e0121fc91f..db93542f78e2 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 + * (c) 1998-2002 Petr Vandrovec * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.62 2001/11/29 + * Version: 1.64 2002/06/10 * */ @@ -103,6 +103,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, int mode, unsigned int pos) { u_int32_t tmp; + u_int32_t datactl; MINFO_FROM(m2info->primary_dev); switch (mode) { @@ -117,12 +118,15 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, tmp = 0x00800000; break; } - 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 */ + /* no vidrst when in monitor mode */ + if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + tmp |= 0xC0001000; /* Enable H/V vidrst */ + } } else { tmp |= 0x00000002; /* source from VDOCLK */ tmp |= 0xC0000000; /* enable vvidrst & hvidrst */ @@ -142,6 +146,10 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, mt->VSyncEnd >>= 1; mt->VTotal >>= 1; } + 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)); @@ -155,12 +163,14 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, 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, 0); /* data control */ + mga_outl(0x3C4C, datactl); /* data control */ if (tmp & 0x02000000) { int i; @@ -208,7 +218,7 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, linelen = var->xres_virtual * pixelsize; pos = var->yoffset * linelen + 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 { diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h index e625053bc679..a72ebe3ff508 100644 --- a/drivers/video/matrox/matroxfb_crtc2.h +++ b/drivers/video/matrox/matroxfb_crtc2.h @@ -29,6 +29,8 @@ struct matroxfb_dh_fb_info { 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 1399947ee413..17f5f9236bf4 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -2,39 +2,363 @@ * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450. * - * (c) 1998-2001 Petr Vandrovec + * (c) 1998-2002 Petr Vandrovec * * 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 #include +#include + +static void cve2_set_reg(WPMINFO int reg, int val) { + unsigned long flags; + + matroxfb_DAC_lock_irqsave(flags); + matroxfb_DAC_out(PMINFO 0x87, reg); + matroxfb_DAC_out(PMINFO 0x88, val); + matroxfb_DAC_unlock_irqrestore(flags); +} + +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 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); + + 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 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; +} + +#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 int matroxfb_g450_compute(void* md, struct my_timming* mt) { MINFO_FROM(md); - if (mt->mnp < 0) { + dprintk(KERN_DEBUG "Computing, mode=%u\n", ACCESS_FBINFO(outputs[1]).mode); + + if (mt->crtc == MATROXFB_SRC_CRTC2 && + ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + const struct output_desc* outd; + + 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 int matroxfb_g450_program(void* md) { + MINFO_FROM(md); + + if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) { + cve2_init_TV(PMINFO &ACCESS_FBINFO(hw).maven); + } return 0; } +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 -EINVAL; +} + static int g450_dvi_compute(void* md, struct my_timming* mt) { MINFO_FROM(md); @@ -49,6 +373,7 @@ static struct matrox_altout matroxfb_g450_altout = { .name = "Secondary output", .compute = matroxfb_g450_compute, .program = matroxfb_g450_program, + .verifymode = matroxfb_g450_verify_mode, }; static struct matrox_altout matroxfb_g450_dvi = { -- cgit v1.2.3 From 8d501b18994e640c0426061e6582289ae7c6f1b2 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:34:44 +0200 Subject: Make debug printouts in matroxfb G400 TV-out disabled by default. OUTPUT_MODE are values, not a bitmap, so use compare instead of bitwise AND. --- drivers/video/matrox/matroxfb_maven.c | 37 +++++++++++++++-------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 0932726f1136..9fd0c2623adc 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 + * (c) 1998-2002 Petr Vandrovec * * 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,11 +22,6 @@ #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 @@ -126,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) @@ -162,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; @@ -272,7 +267,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, @@ -324,10 +319,10 @@ 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 (ACCESS_FBINFO(outputs[1]).mode == MODE_PAL) + if (ACCESS_FBINFO(outputs[1]).mode == MATROXFB_OUTPUT_MODE_PAL) *data = palregs; else *data = ntscregs; @@ -386,7 +381,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 +419,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); @@ -524,7 +519,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 +557,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) { @@ -586,7 +581,7 @@ static inline int maven_compute_timming(struct maven_data* md, MINFO_FROM(md->primary_head); m->mode = ACCESS_FBINFO(outputs[1]).mode; - if (MODE_TV(m->mode)) { + if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) { unsigned int lmargin; unsigned int umargin; unsigned int vslen; @@ -816,7 +811,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); @@ -911,7 +906,7 @@ static int maven_init_client(struct i2c_client* clnt) { 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 = MODE_MONITOR; + ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR; up_write(&ACCESS_FBINFO(altout.lock)); if (maven_get_reg(clnt, 0xB2) < 0x14) { md->version = MGATVO_B; @@ -1045,7 +1040,7 @@ static void matroxfb_maven_exit(void) { i2c_del_driver(&maven_driver); } -MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec "); +MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec "); MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver"); MODULE_LICENSE("GPL"); module_init(matroxfb_maven_init); -- cgit v1.2.3 From dfa24d8437c2046a45afdd4a2b176576d3e700f3 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:35:29 +0200 Subject: Remove currcon field from private fb_info in matroxfb. It was moved to the generic layer long ago. --- drivers/video/matrox/matroxfb_crtc2.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h index a72ebe3ff508..be8a81f4253d 100644 --- a/drivers/video/matrox/matroxfb_crtc2.h +++ b/drivers/video/matrox/matroxfb_crtc2.h @@ -27,7 +27,6 @@ struct matroxfb_dh_fb_info { unsigned int len; } mmio; - int currcon; struct display* currcon_display; int interlaced:1; -- cgit v1.2.3 From a105a29b1998c3d25071822da9c8c1ce2bc72651 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:36:06 +0200 Subject: Use sizeof(*var) instead of sizeof(struct xxx) in matroxfb. --- drivers/video/matrox/matroxfb_base.c | 2 +- drivers/video/matrox/matroxfb_maven.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index f44dd4ec0463..9afe2da196fc 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -661,7 +661,7 @@ static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con, else p = ACCESS_FBINFO(fbcon.disp); - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + memset(fix, 0, sizeof(*fix)); strcpy(fix->id,"MATROX"); fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 9fd0c2623adc..9bbbe532221d 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -957,7 +957,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; -- cgit v1.2.3 From 102d48587c5536152c1e7e76ea3a232d3f65a48f Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:36:45 +0200 Subject: Return ENOTTY instead of EINVAL for unknown ioctl ops in matroxfb. --- drivers/video/matrox/matroxfb_base.c | 2 +- drivers/video/matrox/matroxfb_crtc2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 9afe2da196fc..6cc47170c178 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1168,7 +1168,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file, return 0; } } - return -EINVAL; + return -ENOTTY; #undef minfo } diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index db93542f78e2..f4e8a7bdf833 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -679,7 +679,7 @@ static int matroxfb_dh_ioctl(struct inode* inode, return 0; } } - return -EINVAL; + return -ENOTTY; #undef m2info } -- cgit v1.2.3 From e074c41c51f02799f9fd6935907377eb7af2caa8 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:37:23 +0200 Subject: Add support for MGA-TVO-B into matroxfb. By Mike Pieper. --- drivers/video/matrox/matroxfb_base.c | 3 +++ drivers/video/matrox/matroxfb_maven.c | 18 +++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 6cc47170c178..b13a06accba5 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -80,6 +80,9 @@ * "Denis Zaitsev" * Fixes * + * "Mike Pieper" + * TVOut enhandcements. + * * (following author is not in any relation with this code, but his code * is included in this driver) * diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 9bbbe532221d..02bc8d68378f 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -215,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 */ @@ -321,13 +328,14 @@ static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* dat 0x00, /* never written */ }, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 }; MINFO_FROM(md->primary_head); - + 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; @@ -468,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 */ @@ -493,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); @@ -800,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 */ -- cgit v1.2.3 From bda2014fe3a33f88c514af16ff99733ea6068e2f Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:38:04 +0200 Subject: matroxfb: Do not store results of bitwise AND directly in variables which are treated as a booleans. Comparsion does not work correctly on them. --- drivers/video/matrox/matroxfb_base.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index b13a06accba5..e424e26bd336 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1635,11 +1635,11 @@ 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(outputs[2]).data = MINFO; @@ -1652,7 +1652,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ 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); -- cgit v1.2.3 From 4393c27fb543ffa0f5d406d338759cf494249db6 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Wed, 14 Aug 2002 20:38:36 +0200 Subject: Set system PLL vcomax correctly in matroxfb. Discovered by Dirk Uffmann. --- drivers/video/matrox/matroxfb_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index 55a67890de9b..cbe1ddca6179 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -874,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; -- cgit v1.2.3 From 7748d302ad57e7b5e88b74e5724775b1fc0c8774 Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Thu, 15 Aug 2002 00:37:31 +0200 Subject: Update matroxfb to the current fbdev API. --- drivers/video/matrox/matroxfb_DAC1064.c | 30 ++++---- drivers/video/matrox/matroxfb_Ti3026.c | 10 +-- drivers/video/matrox/matroxfb_accel.c | 34 ++++----- drivers/video/matrox/matroxfb_accel.h | 2 +- drivers/video/matrox/matroxfb_base.c | 124 ++++++++++++-------------------- drivers/video/matrox/matroxfb_base.h | 4 +- drivers/video/matrox/matroxfb_crtc2.c | 110 +++++++++++----------------- drivers/video/matrox/matroxfb_misc.c | 8 +-- 8 files changed, 132 insertions(+), 190 deletions(-) diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index 2656bdca4e76..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 + * (c) 1998-2002 Petr Vandrovec * * 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; @@ -453,24 +453,24 @@ void DAC1064_global_restore(WPMINFO2) { } } -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; @@ -495,12 +495,12 @@ static int DAC1064_init_1(WPMINFO struct my_timming* m, struct display *p) { 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++) { @@ -508,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++) { @@ -646,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; @@ -657,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 @@ -668,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; @@ -680,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 */ diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index fb1c494f530c..92d53ad93595 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -6,7 +6,7 @@ * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.64 2002/06/10 + * Version: 1.65 2002/08/14 * * MTRR stuff: 1998 Tom Rini * @@ -402,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; @@ -434,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; @@ -502,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; @@ -569,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); 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 + * (c) 1998-2002 Petr Vandrovec * - * Version: 1.51 2001/06/18 + * Version: 1.65 2002/08/14 * * MTRR stuff: 1998 Tom Rini * @@ -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 e424e26bd336..477039b3fb8b 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -6,7 +6,7 @@ * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.64 2002/06/10 + * Version: 1.65 2002/08/14 * * MTRR stuff: 1998 Tom Rini * @@ -81,7 +81,10 @@ * Fixes * * "Mike Pieper" - * TVOut enhandcements. + * TVOut enhandcements, V4L2 control interface. + * + * "Diego Biurrun" + * DFP testing * * (following author is not in any relation with this code, but his code * is included in this driver) @@ -176,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; @@ -567,7 +572,6 @@ 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 = container_of(fb_info, struct matrox_fb_info, fbcon); #endif @@ -589,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: @@ -620,81 +623,48 @@ 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 (container_of(info, struct matrox_fb_info, fbcon)) - - if (ACCESS_FBINFO(dead)) { - return -ENXIO; - } - - if (con >= 0) - p = fb_display + con; - else - p = ACCESS_FBINFO(fbcon.disp); - - memset(fix, 0, sizeof(*fix)); 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 (container_of(info, struct matrox_fb_info, fbcon)) - 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, @@ -741,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); @@ -766,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; @@ -825,7 +797,7 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, 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 @@ -855,7 +827,7 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, } } up_read(&ACCESS_FBINFO(altout).lock); - matrox_cfbX_init(PMINFO display); + matrox_cfbX_init(PMINFO2); my_install_cmap(PMINFO2); } } @@ -956,7 +928,7 @@ 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; @@ -1213,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, diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index cd456aa2b349..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 + * (c) 1998-2002 Petr Vandrovec * */ #ifndef __MATROXFB_H__ @@ -670,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 f4e8a7bdf833..56c7c7a02583 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -6,7 +6,7 @@ * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.64 2002/06/10 + * Version: 1.65 2002/08/14 * */ @@ -42,7 +42,6 @@ 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 (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - struct display* p; 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,7 +97,6 @@ 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; @@ -157,7 +154,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info, 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); + 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 */ @@ -202,8 +199,7 @@ static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) { ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004; } -static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info, - struct display* p) { +static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info) { /* no acceleration for secondary head... */ } @@ -214,9 +210,11 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, unsigned int pixelsize; MINFO_FROM(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 (m2info->interlaced) { mga_outl(0x3C2C, pos); @@ -227,7 +225,6 @@ static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info, } 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, @@ -306,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; @@ -349,44 +346,19 @@ 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 (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - 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 (container_of(info, struct matroxfb_dh_fb_info, fbcon)) - 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, @@ -404,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; @@ -425,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); @@ -443,12 +417,12 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, 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; cnt = 0; down_read(&ACCESS_FBINFO(altout).lock); @@ -464,7 +438,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, ACCESS_FBINFO(crtc2).mnp = mt.mnp; up_read(&ACCESS_FBINFO(altout).lock); if (cnt) { - matroxfb_dh_restore(m2info, &mt, p, mode, pos); + matroxfb_dh_restore(m2info, &mt, mode, pos); } else { matroxfb_dh_disable(m2info); } @@ -484,7 +458,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, } } up_read(&ACCESS_FBINFO(altout).lock); - matroxfb_dh_cfbX_init(m2info, p); + matroxfb_dh_cfbX_init(m2info); my_install_cmap(m2info); } return 0; @@ -558,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; } @@ -701,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, diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index cbe1ddca6179..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 + * (c) 1998-2002 Petr Vandrovec * * Portions Copyright (c) 2001 Matrox Graphics Inc. * - * Version: 1.62 2001/11/29 + * Version: 1.65 2002/08/14 * * MTRR stuff: 1998 Tom Rini * @@ -227,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); @@ -1013,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 "); +MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec "); MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards"); MODULE_LICENSE("GPL"); -- cgit v1.2.3