Commit 48800d9e authored by Petr Vandrovec's avatar Petr Vandrovec

Support secondary head DDC on G450/G550.

Simplify i2c-matroxfb code.
parent 456f17cd
......@@ -2,9 +2,9 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
*
* (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
* (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Version: 1.51 2001/01/19
* Version: 1.64 2002/06/10
*
* See matroxfb_base.c for contributors.
*
......@@ -30,6 +30,12 @@
/******************************************************/
struct matroxfb_dh_maven_info {
struct i2c_bit_adapter maven;
struct i2c_bit_adapter ddc1;
struct i2c_bit_adapter ddc2;
};
static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
unsigned long flags;
int v;
......@@ -40,7 +46,7 @@ static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
return v;
}
static inline void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
unsigned long flags;
int v;
......@@ -53,7 +59,7 @@ static inline void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int
}
/* software I2C functions */
static void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
static inline void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
if (state)
state = 0;
else
......@@ -61,68 +67,24 @@ static void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state)
matroxfb_set_gpio(minfo, ~mask, state);
}
static void matroxfb_maven_setsda(void* data, int state) {
matroxfb_i2c_set(data, MAT_DATA, state);
}
static void matroxfb_maven_setscl(void* data, int state) {
matroxfb_i2c_set(data, MAT_CLK, state);
}
static int matroxfb_maven_getsda(void* data) {
return (matroxfb_read_gpio(data) & MAT_DATA) ? 1 : 0;
}
static int matroxfb_maven_getscl(void* data) {
return (matroxfb_read_gpio(data) & MAT_CLK) ? 1 : 0;
}
static void matroxfb_ddc1_setsda(void* data, int state) {
matroxfb_i2c_set(data, DDC1_DATA, state);
}
static void matroxfb_ddc1_setscl(void* data, int state) {
matroxfb_i2c_set(data, DDC1_CLK, state);
}
static int matroxfb_ddc1_getsda(void* data) {
return (matroxfb_read_gpio(data) & DDC1_DATA) ? 1 : 0;
}
static int matroxfb_ddc1_getscl(void* data) {
return (matroxfb_read_gpio(data) & DDC1_CLK) ? 1 : 0;
}
static void matroxfb_ddc1b_setsda(void* data, int state) {
matroxfb_i2c_set(data, DDC1B_DATA, state);
}
static void matroxfb_ddc1b_setscl(void* data, int state) {
matroxfb_i2c_set(data, DDC1B_CLK, state);
}
static int matroxfb_ddc1b_getsda(void* data) {
return (matroxfb_read_gpio(data) & DDC1B_DATA) ? 1 : 0;
}
static int matroxfb_ddc1b_getscl(void* data) {
return (matroxfb_read_gpio(data) & DDC1B_CLK) ? 1 : 0;
static void matroxfb_gpio_setsda(void* data, int state) {
struct i2c_bit_adapter* b = data;
matroxfb_i2c_set(b->minfo, b->mask.data, state);
}
static void matroxfb_ddc2_setsda(void* data, int state) {
matroxfb_i2c_set(data, DDC2_DATA, state);
static void matroxfb_gpio_setscl(void* data, int state) {
struct i2c_bit_adapter* b = data;
matroxfb_i2c_set(b->minfo, b->mask.clock, state);
}
static void matroxfb_ddc2_setscl(void* data, int state) {
matroxfb_i2c_set(data, DDC2_CLK, state);
static int matroxfb_gpio_getsda(void* data) {
struct i2c_bit_adapter* b = data;
return (matroxfb_read_gpio(b->minfo) & b->mask.data) ? 1 : 0;
}
static int matroxfb_ddc2_getsda(void* data) {
return (matroxfb_read_gpio(data) & DDC2_DATA) ? 1 : 0;
}
static int matroxfb_ddc2_getscl(void* data) {
return (matroxfb_read_gpio(data) & DDC2_CLK) ? 1 : 0;
static int matroxfb_gpio_getscl(void* data) {
struct i2c_bit_adapter* b = data;
return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
}
static void matroxfb_dh_inc_use(struct i2c_adapter* dummy) {
......@@ -133,97 +95,36 @@ static void matroxfb_dh_dec_use(struct i2c_adapter* dummy) {
MOD_DEC_USE_COUNT;
}
static struct i2c_adapter matroxmaven_i2c_adapter_template =
{
"",
I2C_HW_B_G400,
NULL,
NULL,
matroxfb_dh_inc_use,
matroxfb_dh_dec_use,
NULL,
NULL,
NULL,
};
static struct i2c_algo_bit_data matroxmaven_i2c_algo_template =
{
NULL,
matroxfb_maven_setsda,
matroxfb_maven_setscl,
matroxfb_maven_getsda,
matroxfb_maven_getscl,
10, 10, 100,
};
static struct i2c_adapter matrox_ddc1_adapter_template =
{
"",
I2C_HW_B_G400, /* DDC */
NULL,
NULL,
matroxfb_dh_inc_use,
matroxfb_dh_dec_use,
NULL,
NULL,
NULL,
};
static struct i2c_algo_bit_data matrox_ddc1_algo_template =
static struct i2c_adapter matrox_i2c_adapter_template =
{
NULL,
matroxfb_ddc1_setsda,
matroxfb_ddc1_setscl,
matroxfb_ddc1_getsda,
matroxfb_ddc1_getscl,
10, 10, 100,
};
static struct i2c_algo_bit_data matrox_ddc1b_algo_template =
{
NULL,
matroxfb_ddc1b_setsda,
matroxfb_ddc1b_setscl,
matroxfb_ddc1b_getsda,
matroxfb_ddc1b_getscl,
10, 10, 100,
};
static struct i2c_adapter matrox_ddc2_adapter_template =
{
"",
I2C_HW_B_G400, /* DDC */
NULL,
NULL,
matroxfb_dh_inc_use, /* should increment matroxfb_maven usage too, this DDC is coupled with maven_client */
matroxfb_dh_dec_use, /* should decrement matroxfb_maven usage too */
NULL,
NULL,
NULL,
.id = I2C_HW_B_G400,
.inc_use = matroxfb_dh_inc_use,
.dec_use = matroxfb_dh_dec_use,
};
static struct i2c_algo_bit_data matrox_ddc2_algo_template =
static struct i2c_algo_bit_data matrox_i2c_algo_template =
{
NULL,
matroxfb_ddc2_setsda,
matroxfb_ddc2_setscl,
matroxfb_ddc2_getsda,
matroxfb_ddc2_getscl,
matroxfb_gpio_setsda,
matroxfb_gpio_setscl,
matroxfb_gpio_getsda,
matroxfb_gpio_getscl,
10, 10, 100,
};
static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo) {
static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
unsigned int data, unsigned int clock, const char* name) {
int err;
b->adapter.data = minfo;
b->minfo = minfo;
b->mask.data = data;
b->mask.clock = clock;
b->adapter = matrox_i2c_adapter_template;
sprintf(b->adapter.name, name, GET_FB_IDX(minfo->fbcon.node));
b->adapter.data = b;
b->adapter.algo_data = &b->bac;
b->bac.data = minfo;
b->bac = matrox_i2c_algo_template;
b->bac.data = b;
err = i2c_bit_add_bus(&b->adapter);
b->initialized = !err;
return err;
......@@ -236,50 +137,14 @@ static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
}
}
static inline int i2c_maven_init(struct matroxfb_dh_maven_info* minfo2) {
struct i2c_bit_adapter *b = &minfo2->maven;
b->adapter = matroxmaven_i2c_adapter_template;
b->bac = matroxmaven_i2c_algo_template;
sprintf(b->adapter.name, "MAVEN:fb%u on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
return i2c_bus_reg(b, minfo2->primary_dev);
}
static inline void i2c_maven_done(struct matroxfb_dh_maven_info* minfo2) {
i2c_bit_bus_del(&minfo2->maven);
}
static inline int i2c_ddc1_init(struct matroxfb_dh_maven_info* minfo2) {
struct i2c_bit_adapter *b = &minfo2->ddc1;
b->adapter = matrox_ddc1_adapter_template;
b->bac = matrox_ddc1_algo_template;
sprintf(b->adapter.name, "DDC:fb%u #0 on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
return i2c_bus_reg(b, minfo2->primary_dev);
}
static inline int i2c_ddc1b_init(struct matroxfb_dh_maven_info* minfo2) {
struct i2c_bit_adapter *b = &minfo2->ddc1;
b->adapter = matrox_ddc1_adapter_template;
b->bac = matrox_ddc1b_algo_template;
sprintf(b->adapter.name, "DDC:fb%u #0 on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
return i2c_bus_reg(b, minfo2->primary_dev);
}
static inline void i2c_ddc1_done(struct matroxfb_dh_maven_info* minfo2) {
i2c_bit_bus_del(&minfo2->ddc1);
}
static inline int i2c_ddc2_init(struct matroxfb_dh_maven_info* minfo2) {
struct i2c_bit_adapter *b = &minfo2->ddc2;
b->adapter = matrox_ddc2_adapter_template;
b->bac = matrox_ddc2_algo_template;
sprintf(b->adapter.name, "DDC:fb%u #1 on i2c-matroxfb", GET_FB_IDX(minfo2->primary_dev->fbcon.node));
return i2c_bus_reg(b, minfo2->primary_dev);
}
static inline void i2c_ddc2_done(struct matroxfb_dh_maven_info* minfo2) {
i2c_bit_bus_del(&minfo2->ddc2);
}
......@@ -299,24 +164,26 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
matroxfb_DAC_unlock_irqrestore(flags);
memset(m2info, 0, sizeof(*m2info));
m2info->maven.minfo = m2info;
m2info->ddc1.minfo = m2info;
m2info->ddc2.minfo = m2info;
m2info->primary_dev = minfo;
if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGA2064W ||
ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGA2164W ||
ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGA2164W_AGP)
err = i2c_ddc1b_init(m2info);
else
err = i2c_ddc1_init(m2info);
switch (ACCESS_FBINFO(chip)) {
case MGA_2064:
case MGA_2164:
err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, DDC1B_CLK, "DDC:fb%u #0 on i2c-matroxfb");
break;
default:
err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, DDC1_CLK, "DDC:fb%u #0 on i2c-matroxfb");
break;
}
if (err)
goto fail_ddc1;
if (ACCESS_FBINFO(devflags.maven_capable)) {
err = i2c_ddc2_init(m2info);
if (err)
if (ACCESS_FBINFO(devflags.dualhead)) {
err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1 on i2c-matroxfb");
if (err == -ENODEV) {
printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
} else if (err)
printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
err = i2c_maven_init(m2info);
/* Register maven bus even on G450/G550 */
err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u on i2c-matroxfb");
if (err)
printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
}
......@@ -337,10 +204,10 @@ static void i2c_matroxfb_remove(struct matrox_fb_info* minfo, void* data) {
}
static struct matroxfb_driver i2c_matroxfb = {
LIST_HEAD_INIT(i2c_matroxfb.node),
"i2c-matroxfb",
i2c_matroxfb_probe,
i2c_matroxfb_remove,
.node = LIST_HEAD_INIT(i2c_matroxfb.node),
.name = "i2c-matroxfb",
.probe = i2c_matroxfb_probe,
.remove = i2c_matroxfb_remove,
};
static int __init i2c_matroxfb_init(void) {
......@@ -355,7 +222,7 @@ static void __exit i2c_matroxfb_exit(void) {
matroxfb_unregister_driver(&i2c_matroxfb);
}
MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards");
module_init(i2c_matroxfb_init);
......
......@@ -2,11 +2,11 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
*
* (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
* (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
*
* Portions Copyright (c) 2001 Matrox Graphics Inc.
*
* Version: 1.62 2001/11/29
* Version: 1.64 2002/06/10
*
* MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
*
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -6,21 +6,15 @@
#include <linux/i2c-algo-bit.h>
#include "matroxfb_base.h"
struct matroxfb_dh_maven_info;
struct i2c_bit_adapter {
struct i2c_adapter adapter;
int initialized;
struct i2c_algo_bit_data bac;
struct matroxfb_dh_maven_info *minfo;
};
struct matroxfb_dh_maven_info {
struct matrox_fb_info* primary_dev;
struct i2c_bit_adapter maven;
struct i2c_bit_adapter ddc1;
struct i2c_bit_adapter ddc2;
struct matrox_fb_info* minfo;
struct {
unsigned int data;
unsigned int clock;
} mask;
};
#endif /* __MATROXFB_MAVEN_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment