#include <linux/pci.h>
#include <linux/init.h>
#include <linux/io.h>
-
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
struct i2c_adapter ddc_adapter;
struct i2c_algo_bit_data ddc_algo;
#endif
+
+#ifdef CONFIG_FB_CYBER2000_I2C
+ struct i2c_adapter i2c_adapter;
+ struct i2c_algo_bit_data i2c_algo;
+#endif
};
static char *default_font = "Acorn8x8";
{
if (int_cfb_info != NULL) {
info->dev = int_cfb_info->dev;
+#ifdef CONFIG_FB_CYBER2000_I2C
+ info->i2c = &int_cfb_info->i2c_adapter;
+#else
+ info->i2c = NULL;
+#endif
info->regs = int_cfb_info->regs;
info->fb = int_cfb_info->fb.screen_base;
info->fb_size = int_cfb_info->fb.fix.smem_len;
}
#endif /* CONFIG_FB_CYBER2000_DDC */
+#ifdef CONFIG_FB_CYBER2000_I2C
+static void cyber2000fb_i2c_setsda(void *data, int state)
+{
+ struct cfb_info *cfb = data;
+ unsigned int latch2;
+
+ spin_lock(&cfb->reg_b0_lock);
+ latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
+ latch2 &= EXT_LATCH2_I2C_CLKEN;
+ if (state)
+ latch2 |= EXT_LATCH2_I2C_DATEN;
+ cyber2000_grphw(EXT_LATCH2, latch2, cfb);
+ spin_unlock(&cfb->reg_b0_lock);
+}
+
+static void cyber2000fb_i2c_setscl(void *data, int state)
+{
+ struct cfb_info *cfb = data;
+ unsigned int latch2;
+
+ spin_lock(&cfb->reg_b0_lock);
+ latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
+ latch2 &= EXT_LATCH2_I2C_DATEN;
+ if (state)
+ latch2 |= EXT_LATCH2_I2C_CLKEN;
+ cyber2000_grphw(EXT_LATCH2, latch2, cfb);
+ spin_unlock(&cfb->reg_b0_lock);
+}
+
+static int cyber2000fb_i2c_getsda(void *data)
+{
+ struct cfb_info *cfb = data;
+ int ret;
+
+ spin_lock(&cfb->reg_b0_lock);
+ ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
+ spin_unlock(&cfb->reg_b0_lock);
+
+ return ret;
+}
+
+static int cyber2000fb_i2c_getscl(void *data)
+{
+ struct cfb_info *cfb = data;
+ int ret;
+
+ spin_lock(&cfb->reg_b0_lock);
+ ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
+ spin_unlock(&cfb->reg_b0_lock);
+
+ return ret;
+}
+
+static int __devinit cyber2000fb_i2c_register(struct cfb_info *cfb)
+{
+ strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
+ sizeof(cfb->i2c_adapter.name));
+ cfb->i2c_adapter.owner = THIS_MODULE;
+ cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
+ cfb->i2c_adapter.dev.parent = &cfb->dev->dev;
+ cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
+ cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
+ cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
+ cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
+ cfb->i2c_algo.udelay = 5;
+ cfb->i2c_algo.timeout = msecs_to_jiffies(100);
+ cfb->i2c_algo.data = cfb;
+
+ return i2c_bit_add_bus(&cfb->i2c_adapter);
+}
+
+static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
+{
+ i2c_del_adapter(&cfb->i2c_adapter);
+}
+#else
+#define cyber2000fb_i2c_register(cfb) (0)
+#define cyber2000fb_i2c_unregister(cfb) do { } while (0)
+#endif
+
/*
* These parameters give
* 640x480, hsync 31.5kHz, vsync 60Hz
if (cfb->dev)
cfb->fb.device = &cfb->dev->dev;
+
+ err = cyber2000fb_i2c_register(cfb);
+ if (err)
+ goto failed;
+
err = register_framebuffer(&cfb->fb);
+ if (err)
+ cyber2000fb_i2c_unregister(cfb);
failed:
#ifdef CONFIG_FB_CYBER2000_DDC
return err;
}
+static void __devexit cyberpro_common_remove(struct cfb_info *cfb)
+{
+ unregister_framebuffer(&cfb->fb);
+#ifdef CONFIG_FB_CYBER2000_DDC
+ if (cfb->ddc_registered)
+ i2c_del_adapter(&cfb->ddc_adapter);
+#endif
+ cyber2000fb_i2c_unregister(cfb);
+}
+
static void cyberpro_common_resume(struct cfb_info *cfb)
{
cyberpro_init_hw(cfb);
struct cfb_info *cfb = pci_get_drvdata(dev);
if (cfb) {
- /*
- * If unregister_framebuffer fails, then
- * we will be leaving hooks that could cause
- * oopsen laying around.
- */
- if (unregister_framebuffer(&cfb->fb))
- printk(KERN_WARNING "%s: danger Will Robinson, "
- "danger danger! Oopsen imminent!\n",
- cfb->fb.fix.id);
-#ifdef CONFIG_FB_CYBER2000_DDC
- if (cfb->ddc_registered)
- i2c_del_adapter(&cfb->ddc_adapter);
-#endif
+ cyberpro_common_remove(cfb);
iounmap(cfb->region);
cyberpro_free_fb_info(cfb);