Commit d14672aa authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] matroxfb: Add support for mapping CRTC<->outputs at boot time

Signed-off-by: default avatarPetr Vandrovec <vandrove@vc.cvut.cz>

Some people expressed interest in having possibility to set CRTC <->
outputs mapping at boot time, without having to use 'matroxset' later after
kernel boots.

This patch adds option 'video=matroxfb:outputs:XYZ', where X sets which
CRTC will connect to primary output, Y sets secondary output and Z sets DVI
output.

In addition to that I also added missing memset() into maven, which was
broken since i2c was kobjectified.
parent 377cb3de
......@@ -660,7 +660,7 @@ static int MGA1064_preinit(WPMINFO2) {
ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
ACCESS_FBINFO(outputs[0]).output = &m1064;
ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src;
ACCESS_FBINFO(outputs[0]).data = MINFO;
ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
......@@ -859,7 +859,7 @@ static int MGAG100_preinit(WPMINFO2) {
{
ACCESS_FBINFO(outputs[0]).output = &m1064;
}
ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1;
ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src;
ACCESS_FBINFO(outputs[0]).data = MINFO;
ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
......
......@@ -692,7 +692,7 @@ static int Ti3026_preinit(WPMINFO2) {
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]).src = ACCESS_FBINFO(outputs[0]).default_src;
ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
if (ACCESS_FBINFO(devflags.noinit))
......
......@@ -1272,6 +1272,7 @@ static unsigned int maxclk; /* "matrox:maxclk:xxxxM" */
static int dfp; /* "matrox:dfp */
static int dfp_type = -1; /* "matrox:dfp:xxx */
static int memtype = -1; /* "matrox:memtype:xxx" */
static char outputs[8]; /* "matrox:outputs:xxx" */
#ifndef MODULE
static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */
......@@ -1537,6 +1538,39 @@ static struct fb_videomode defaultmode = {
static int hotplug = 0;
static void setDefaultOutputs(WPMINFO2) {
unsigned int i;
const char* ptr;
ACCESS_FBINFO(outputs[0]).default_src = MATROXFB_SRC_CRTC1;
if (ACCESS_FBINFO(devflags.g450dac)) {
ACCESS_FBINFO(outputs[1]).default_src = MATROXFB_SRC_CRTC1;
ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1;
} else if (dfp) {
ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1;
}
ptr = outputs;
for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
char c = *ptr++;
if (c == 0) {
break;
}
if (c == '0') {
ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_NONE;
} else if (c == '1') {
ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC1;
} else if (c == '2' && ACCESS_FBINFO(devflags.crtc2)) {
ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC2;
} else {
printk(KERN_ERR "matroxfb: Unknown outputs setting\n");
break;
}
}
/* Nullify this option for subsequent adapters */
outputs[0] = 0;
}
static int initMatrox2(WPMINFO struct board* b){
unsigned long ctrlptr_phys = 0;
unsigned long video_base_phys = 0;
......@@ -1577,20 +1611,18 @@ static int initMatrox2(WPMINFO struct board* b){
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;
ACCESS_FBINFO(devflags.dfp_type) = dfp_type;
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);
setDefaultOutputs(PMINFO2);
if (b->flags & DEVF_PANELLINK_CAPABLE) {
ACCESS_FBINFO(outputs[2]).data = MINFO;
ACCESS_FBINFO(outputs[2]).output = &panellink_output;
if (dfp)
ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_CRTC1;
else
ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_NONE;
ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src;
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) != 0;
ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
if (ACCESS_FBINFO(capable.cross4MB) < 0)
ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
......@@ -1813,6 +1845,13 @@ static int initMatrox2(WPMINFO struct board* b){
to yres_virtual * xres_virtual < 2^32 */
}
matroxfb_init_fix(PMINFO2);
/* Normalize values (namely yres_virtual) */
matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
/* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
* vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
* and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
* anyway. But we at least tried... */
ACCESS_FBINFO(fbcon.var) = vesafb_defined;
err = -EINVAL;
printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
......@@ -1834,6 +1873,9 @@ static int initMatrox2(WPMINFO struct board* b){
* until someone tells me what is proper thing to do */
printk(KERN_INFO "fb%d: initializing hardware\n",
ACCESS_FBINFO(fbcon.node));
/* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
* already before, so register_framebuffer works correctly. */
vesafb_defined.activate |= FB_ACTIVATE_FORCE;
fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
}
return 0;
......@@ -2288,6 +2330,8 @@ int __init matroxfb_setup(char *options) {
mem = simple_strtoul(this_opt+4, NULL, 0);
else if (!strncmp(this_opt, "mode:", 5))
strlcpy(videomode, this_opt+5, sizeof(videomode));
else if (!strncmp(this_opt, "outputs:", 8))
strlcpy(outputs, this_opt+8, sizeof(outputs));
else if (!strncmp(this_opt, "dfp:", 4)) {
dfp_type = simple_strtoul(this_opt+4, NULL, 0);
dfp = 1;
......@@ -2463,6 +2507,8 @@ MODULE_PARM(dfp, "i");
MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)");
MODULE_PARM(dfp_type, "i");
MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)");
MODULE_PARM(outputs, "c8");
MODULE_PARM_DESC(outputs, "Specifies which CRTC is mapped to which output (string of up to three letters, consisting of 0 (disabled), 1 (CRTC1), 2 (CRTC2)) (default=111 for Gx50, 101 for G200/G400 with DFP, and 100 for all other devices)");
#ifdef CONFIG_PPC_PMAC
MODULE_PARM(vmode, "i");
MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
......
......@@ -479,6 +479,7 @@ struct matrox_fb_info {
struct matrox_altout* output;
void* data;
unsigned int mode;
unsigned int default_src;
} outputs[MATROXFB_MAX_OUTPUTS];
#define MATROXFB_MAX_FB_DRIVERS 5
......
......@@ -628,15 +628,6 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
m2info->mmio.vbase = ACCESS_FBINFO(mmio.vbase);
m2info->mmio.len = ACCESS_FBINFO(mmio.len);
/*
* If we have unused output, connect CRTC2 to it...
*/
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_init_fix(m2info);
if (register_framebuffer(&m2info->fbcon)) {
return -ENXIO;
......
......@@ -591,11 +591,11 @@ void matroxfb_g450_connect(WPMINFO2) {
if (ACCESS_FBINFO(devflags.g450dac)) {
down_write(&ACCESS_FBINFO(altout.lock));
tvo_fill_defaults(PMINFO2);
ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC1;
ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src;
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]).src = ACCESS_FBINFO(outputs[2]).default_src;
ACCESS_FBINFO(outputs[2]).data = MINFO;
ACCESS_FBINFO(outputs[2]).output = &matroxfb_g450_dvi;
ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
......
......@@ -1188,7 +1188,7 @@ static int maven_init_client(struct i2c_client* clnt) {
md->client = clnt;
down_write(&ACCESS_FBINFO(altout.lock));
ACCESS_FBINFO(outputs[1]).output = &maven_altout;
ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_NONE;
ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src;
ACCESS_FBINFO(outputs[1]).data = md;
ACCESS_FBINFO(outputs[1]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
up_write(&ACCESS_FBINFO(altout.lock));
......@@ -1249,6 +1249,7 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin
err = -ENOMEM;
goto ERROR0;
}
memset(new_client, 0, sizeof(*new_client) + sizeof(*data));
data = (struct maven_data*)(new_client + 1);
i2c_set_clientdata(new_client, data);
new_client->addr = address;
......
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