[PATCH 5/8] fbdev: Allow mode change even if EDID block is not found
From: Antonino A. Daplas <hidden>
Date: 2004-11-11 02:25:39
- 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 <redacted> --- savagefb-i2c.c | 93 +++++++++++++++++++++++++++++++++------------------------ savagefb.c | 25 +++++++-------- 2 files changed, 66 insertions(+), 52 deletions(-) diff -Nru a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
--- a/drivers/video/savage/savagefb-i2c.c 2004-10-27 15:25:25 +08:00
+++ b/drivers/video/savage/savagefb-i2c.c 2004-11-11 09:55:43 +08:00@@ -141,32 +141,37 @@ 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; }
@@ -174,7 +179,7 @@ { struct savagefb_par *par = (struct savagefb_par *)info->par; par->chan.par = par; - + switch(info->fix.accel) { case FB_ACCEL_PROSAVAGE_DDRK: case FB_ACCEL_PROSAVAGE_PM:
@@ -193,6 +198,8 @@ 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 @@ 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 @@ 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 @@ .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)
diff -Nru a/drivers/video/savage/savagefb.c b/drivers/video/savage/savagefb.c
--- a/drivers/video/savage/savagefb.c 2004-10-30 19:10:43 +08:00
+++ b/drivers/video/savage/savagefb.c 2004-11-11 09:55:43 +08:00@@ -738,7 +738,7 @@ } } - if (!mode_valid && !list_empty(&info->modelist)) + if (!mode_valid && info->monspecs.modedb_len) return -EINVAL; /* Is the mode larger than the LCD panel? */
@@ -1821,43 +1821,43 @@ 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; }
@@ -2033,14 +2033,13 @@ 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); /* -------------------------------------------------------
This SF.Net email is sponsored by: Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux. http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click