Commit b04dcfaa authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbdev: Allow mode change even if EDID block is not found

- use symbol_get() to check for the presence of i2c

- allow mode changing even if EDID block is not found (no I2C support)

- fix crashes on chipsets that do not have i2c support

- shorten string in info->fix.id

- trivial chip name changes
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 455f8c02
...@@ -141,8 +141,10 @@ static int prosavage_gpio_getsda(void* data) ...@@ -141,8 +141,10 @@ static int prosavage_gpio_getsda(void* data)
static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
const char *name) const char *name)
{ {
int rc; int (*add_bus)(struct i2c_adapter *) = symbol_get(i2c_bit_add_bus);
int rc = 0;
if (add_bus && chan->par) {
strcpy(chan->adapter.name, name); strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE; chan->adapter.owner = THIS_MODULE;
chan->adapter.id = I2C_ALGO_SAVAGE; chan->adapter.id = I2C_ALGO_SAVAGE;
...@@ -160,13 +162,16 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, ...@@ -160,13 +162,16 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
chan->algo.setscl(chan, 1); chan->algo.setscl(chan, 1);
udelay(20); udelay(20);
rc = i2c_bit_add_bus(&chan->adapter); rc = add_bus(&chan->adapter);
if (rc == 0) if (rc == 0)
dev_dbg(&chan->par->pcidev->dev, dev_dbg(&chan->par->pcidev->dev,
"I2C bus %s registered.\n", name); "I2C bus %s registered.\n", name);
else else
dev_warn(&chan->par->pcidev->dev, dev_warn(&chan->par->pcidev->dev,
"Failed to register I2C bus %s.\n", name); "Failed to register I2C bus %s.\n", name);
} else
chan->par = NULL;
return rc; return rc;
} }
...@@ -193,6 +198,8 @@ void savagefb_create_i2c_busses(struct fb_info *info) ...@@ -193,6 +198,8 @@ void savagefb_create_i2c_busses(struct fb_info *info)
par->chan.algo.getsda = savage4_gpio_getsda; par->chan.algo.getsda = savage4_gpio_getsda;
par->chan.algo.getscl = savage4_gpio_getscl; par->chan.algo.getscl = savage4_gpio_getscl;
break; break;
default:
par->chan.par = NULL;
} }
savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2"); savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");
...@@ -202,9 +209,12 @@ EXPORT_SYMBOL(savagefb_create_i2c_busses); ...@@ -202,9 +209,12 @@ EXPORT_SYMBOL(savagefb_create_i2c_busses);
void savagefb_delete_i2c_busses(struct fb_info *info) void savagefb_delete_i2c_busses(struct fb_info *info)
{ {
struct savagefb_par *par = (struct savagefb_par *)info->par; struct savagefb_par *par = (struct savagefb_par *)info->par;
int (*del_bus)(struct i2c_adapter *) =
symbol_get(i2c_bit_del_bus);
if (del_bus && par->chan.par)
del_bus(&par->chan.adapter);
if (par->chan.par)
i2c_bit_del_bus(&par->chan.adapter);
par->chan.par = NULL; par->chan.par = NULL;
} }
EXPORT_SYMBOL(savagefb_delete_i2c_busses); EXPORT_SYMBOL(savagefb_delete_i2c_busses);
...@@ -212,6 +222,8 @@ EXPORT_SYMBOL(savagefb_delete_i2c_busses); ...@@ -212,6 +222,8 @@ EXPORT_SYMBOL(savagefb_delete_i2c_busses);
static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan) static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
{ {
u8 start = 0x0; u8 start = 0x0;
int (*transfer)(struct i2c_adapter *, struct i2c_msg *, int) =
symbol_get(i2c_transfer);
struct i2c_msg msgs[] = { struct i2c_msg msgs[] = {
{ {
.addr = SAVAGE_DDC, .addr = SAVAGE_DDC,
...@@ -223,20 +235,23 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan) ...@@ -223,20 +235,23 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
.len = EDID_LENGTH, .len = EDID_LENGTH,
}, },
}; };
u8 *buf; u8 *buf = NULL;
if (transfer && chan->par) {
buf = kmalloc(EDID_LENGTH, GFP_KERNEL); buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
if (!buf) { if (buf) {
dev_warn(&chan->par->pcidev->dev, "Out of memory!\n");
return NULL;
}
msgs[1].buf = buf; msgs[1].buf = buf;
if (i2c_transfer(&chan->adapter, msgs, 2) == 2) if (transfer(&chan->adapter, msgs, 2) != 2) {
return buf; dev_dbg(&chan->par->pcidev->dev,
dev_dbg(&chan->par->pcidev->dev, "Unable to read EDID block.\n"); "Unable to read EDID block.\n");
kfree(buf); kfree(buf);
return NULL; buf = NULL;
}
}
}
return buf;
} }
int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid) int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
......
...@@ -738,7 +738,7 @@ static int savagefb_check_var (struct fb_var_screeninfo *var, ...@@ -738,7 +738,7 @@ static int savagefb_check_var (struct fb_var_screeninfo *var,
} }
} }
if (!mode_valid && !list_empty(&info->modelist)) if (!mode_valid && info->monspecs.modedb_len)
return -EINVAL; return -EINVAL;
/* Is the mode larger than the LCD panel? */ /* Is the mode larger than the LCD panel? */
...@@ -1817,43 +1817,43 @@ static int __devinit savage_init_fb_info (struct fb_info *info, ...@@ -1817,43 +1817,43 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
break; break;
case FB_ACCEL_SAVAGE_MX_MV: case FB_ACCEL_SAVAGE_MX_MV:
par->chip = S3_SAVAGE_MX; par->chip = S3_SAVAGE_MX;
snprintf (info->fix.id, 16, "S3 Savage/MX-MV"); snprintf (info->fix.id, 16, "Savage/MX-MV");
break; break;
case FB_ACCEL_SAVAGE_MX: case FB_ACCEL_SAVAGE_MX:
par->chip = S3_SAVAGE_MX; par->chip = S3_SAVAGE_MX;
snprintf (info->fix.id, 16, "S3 Savage/MX"); snprintf (info->fix.id, 16, "Savage/MX");
break; break;
case FB_ACCEL_SAVAGE_IX_MV: case FB_ACCEL_SAVAGE_IX_MV:
par->chip = S3_SAVAGE_MX; par->chip = S3_SAVAGE_MX;
snprintf (info->fix.id, 16, "S3 Savage/IX-MV"); snprintf (info->fix.id, 16, "Savage/IX-MV");
break; break;
case FB_ACCEL_SAVAGE_IX: case FB_ACCEL_SAVAGE_IX:
par->chip = S3_SAVAGE_MX; par->chip = S3_SAVAGE_MX;
snprintf (info->fix.id, 16, "S3 Savage/IX"); snprintf (info->fix.id, 16, "Savage/IX");
break; break;
case FB_ACCEL_PROSAVAGE_PM: case FB_ACCEL_PROSAVAGE_PM:
par->chip = S3_PROSAVAGE; par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "S3 ProSavage"); snprintf (info->fix.id, 16, "ProSavagePM");
break; break;
case FB_ACCEL_PROSAVAGE_KM: case FB_ACCEL_PROSAVAGE_KM:
par->chip = S3_PROSAVAGE; par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "S3 ProSavage"); snprintf (info->fix.id, 16, "ProSavageKM");
break; break;
case FB_ACCEL_S3TWISTER_P: case FB_ACCEL_S3TWISTER_P:
par->chip = S3_PROSAVAGE; par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "S3 Twister"); snprintf (info->fix.id, 16, "TwisterP");
break; break;
case FB_ACCEL_S3TWISTER_K: case FB_ACCEL_S3TWISTER_K:
par->chip = S3_PROSAVAGE; par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "S3 TwisterK"); snprintf (info->fix.id, 16, "TwisterK");
break; break;
case FB_ACCEL_PROSAVAGE_DDR: case FB_ACCEL_PROSAVAGE_DDR:
par->chip = S3_PROSAVAGE; par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "S3 ProSavage DDR"); snprintf (info->fix.id, 16, "ProSavageDDR");
break; break;
case FB_ACCEL_PROSAVAGE_DDRK: case FB_ACCEL_PROSAVAGE_DDRK:
par->chip = S3_PROSAVAGE; par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "S3 ProSavage DDR-K"); snprintf (info->fix.id, 16, "ProSavage8");
break; break;
} }
...@@ -2029,14 +2029,13 @@ static int __devinit savagefb_probe (struct pci_dev* dev, ...@@ -2029,14 +2029,13 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
fb_destroy_modedb(info->monspecs.modedb); fb_destroy_modedb(info->monspecs.modedb);
info->monspecs.modedb_len = 0;
info->monspecs.modedb = NULL; info->monspecs.modedb = NULL;
err = register_framebuffer (info); err = register_framebuffer (info);
if (err < 0) if (err < 0)
goto failed; goto failed;
printk (KERN_INFO "fb: %s frame buffer device\n", printk (KERN_INFO "fb: S3 %s frame buffer device\n",
info->fix.id); info->fix.id);
/* /*
......
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