From: "Antonino A. Daplas" - 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: Antonino Daplas Signed-off-by: Andrew Morton --- 25-akpm/drivers/video/savage/savagefb-i2c.c | 91 ++++++++++++++++------------ 25-akpm/drivers/video/savage/savagefb.c | 25 +++---- 2 files changed, 65 insertions(+), 51 deletions(-) diff -puN drivers/video/savage/savagefb.c~fbdev-allow-mode-change-even-if-edid-block-is-not-found drivers/video/savage/savagefb.c --- 25/drivers/video/savage/savagefb.c~fbdev-allow-mode-change-even-if-edid-block-is-not-found 2004-11-10 18:36:18.087648608 -0800 +++ 25-akpm/drivers/video/savage/savagefb.c 2004-11-10 18:36:18.094647544 -0800 @@ -738,7 +738,7 @@ static int savagefb_check_var (struct fb } } - if (!mode_valid && !list_empty(&info->modelist)) + if (!mode_valid && info->monspecs.modedb_len) return -EINVAL; /* Is the mode larger than the LCD panel? */ @@ -1817,43 +1817,43 @@ static int __devinit savage_init_fb_info break; case FB_ACCEL_SAVAGE_MX_MV: par->chip = S3_SAVAGE_MX; - snprintf (info->fix.id, 16, "S3 Savage/MX-MV"); + snprintf (info->fix.id, 16, "Savage/MX-MV"); break; case FB_ACCEL_SAVAGE_MX: par->chip = S3_SAVAGE_MX; - snprintf (info->fix.id, 16, "S3 Savage/MX"); + snprintf (info->fix.id, 16, "Savage/MX"); break; case FB_ACCEL_SAVAGE_IX_MV: par->chip = S3_SAVAGE_MX; - snprintf (info->fix.id, 16, "S3 Savage/IX-MV"); + snprintf (info->fix.id, 16, "Savage/IX-MV"); break; case FB_ACCEL_SAVAGE_IX: par->chip = S3_SAVAGE_MX; - snprintf (info->fix.id, 16, "S3 Savage/IX"); + snprintf (info->fix.id, 16, "Savage/IX"); break; case FB_ACCEL_PROSAVAGE_PM: par->chip = S3_PROSAVAGE; - snprintf (info->fix.id, 16, "S3 ProSavage"); + snprintf (info->fix.id, 16, "ProSavagePM"); break; case FB_ACCEL_PROSAVAGE_KM: par->chip = S3_PROSAVAGE; - snprintf (info->fix.id, 16, "S3 ProSavage"); + snprintf (info->fix.id, 16, "ProSavageKM"); break; case FB_ACCEL_S3TWISTER_P: par->chip = S3_PROSAVAGE; - snprintf (info->fix.id, 16, "S3 Twister"); + snprintf (info->fix.id, 16, "TwisterP"); break; case FB_ACCEL_S3TWISTER_K: par->chip = S3_PROSAVAGE; - snprintf (info->fix.id, 16, "S3 TwisterK"); + snprintf (info->fix.id, 16, "TwisterK"); break; case FB_ACCEL_PROSAVAGE_DDR: par->chip = S3_PROSAVAGE; - snprintf (info->fix.id, 16, "S3 ProSavage DDR"); + snprintf (info->fix.id, 16, "ProSavageDDR"); break; case FB_ACCEL_PROSAVAGE_DDRK: par->chip = S3_PROSAVAGE; - snprintf (info->fix.id, 16, "S3 ProSavage DDR-K"); + snprintf (info->fix.id, 16, "ProSavage8"); break; } @@ -2029,14 +2029,13 @@ static int __devinit savagefb_probe (str fb_destroy_modedb(info->monspecs.modedb); - info->monspecs.modedb_len = 0; info->monspecs.modedb = NULL; err = register_framebuffer (info); if (err < 0) goto failed; - printk (KERN_INFO "fb: %s frame buffer device\n", + printk (KERN_INFO "fb: S3 %s frame buffer device\n", info->fix.id); /* diff -puN drivers/video/savage/savagefb-i2c.c~fbdev-allow-mode-change-even-if-edid-block-is-not-found drivers/video/savage/savagefb-i2c.c --- 25/drivers/video/savage/savagefb-i2c.c~fbdev-allow-mode-change-even-if-edid-block-is-not-found 2004-11-10 18:36:18.088648456 -0800 +++ 25-akpm/drivers/video/savage/savagefb-i2c.c 2004-11-10 18:36:18.092647848 -0800 @@ -141,32 +141,37 @@ static int prosavage_gpio_getsda(void* d static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, 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); + chan->adapter.owner = THIS_MODULE; + chan->adapter.id = I2C_ALGO_SAVAGE; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->par->pcidev->dev; + chan->algo.udelay = 40; + chan->algo.mdelay = 5; + chan->algo.timeout = 20; + chan->algo.data = chan; + + i2c_set_adapdata(&chan->adapter, chan); + + /* Raise SCL and SDA */ + chan->algo.setsda(chan, 1); + chan->algo.setscl(chan, 1); + udelay(20); + + rc = add_bus(&chan->adapter); + if (rc == 0) + dev_dbg(&chan->par->pcidev->dev, + "I2C bus %s registered.\n", name); + else + dev_warn(&chan->par->pcidev->dev, + "Failed to register I2C bus %s.\n", name); + } else + chan->par = NULL; - strcpy(chan->adapter.name, name); - chan->adapter.owner = THIS_MODULE; - chan->adapter.id = I2C_ALGO_SAVAGE; - chan->adapter.algo_data = &chan->algo; - chan->adapter.dev.parent = &chan->par->pcidev->dev; - chan->algo.udelay = 40; - chan->algo.mdelay = 5; - chan->algo.timeout = 20; - chan->algo.data = chan; - - i2c_set_adapdata(&chan->adapter, chan); - - /* Raise SCL and SDA */ - chan->algo.setsda(chan, 1); - chan->algo.setscl(chan, 1); - udelay(20); - - rc = i2c_bit_add_bus(&chan->adapter); - if (rc == 0) - dev_dbg(&chan->par->pcidev->dev, - "I2C bus %s registered.\n", name); - else - dev_warn(&chan->par->pcidev->dev, - "Failed to register I2C bus %s.\n", name); return rc; } @@ -193,6 +198,8 @@ void savagefb_create_i2c_busses(struct f par->chan.algo.getsda = savage4_gpio_getsda; par->chan.algo.getscl = savage4_gpio_getscl; break; + default: + par->chan.par = NULL; } savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2"); @@ -202,9 +209,12 @@ EXPORT_SYMBOL(savagefb_create_i2c_busses void savagefb_delete_i2c_busses(struct fb_info *info) { 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; } 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) { u8 start = 0x0; + int (*transfer)(struct i2c_adapter *, struct i2c_msg *, int) = + symbol_get(i2c_transfer); struct i2c_msg msgs[] = { { .addr = SAVAGE_DDC, @@ -223,20 +235,23 @@ static u8 *savage_do_probe_i2c_edid(stru .len = EDID_LENGTH, }, }; - u8 *buf; + u8 *buf = NULL; - buf = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (!buf) { - dev_warn(&chan->par->pcidev->dev, "Out of memory!\n"); - return NULL; + if (transfer && chan->par) { + buf = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (buf) { + msgs[1].buf = buf; + + if (transfer(&chan->adapter, msgs, 2) != 2) { + dev_dbg(&chan->par->pcidev->dev, + "Unable to read EDID block.\n"); + kfree(buf); + buf = NULL; + } + } } - msgs[1].buf = buf; - if (i2c_transfer(&chan->adapter, msgs, 2) == 2) - return buf; - dev_dbg(&chan->par->pcidev->dev, "Unable to read EDID block.\n"); - kfree(buf); - return NULL; + return buf; } int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid) _