summaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/i810/i810-i2c.c
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-02-13 15:31:38 +0200
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-17 08:10:19 +0300
commitf7018c21350204c4cf628462f229d44d03545254 (patch)
tree408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/fbdev/i810/i810-i2c.c
parentc26ef3eb3c11274bad1b64498d0a134f85755250 (diff)
downloadlinux-stable-f7018c21350204c4cf628462f229d44d03545254.tar.gz
linux-stable-f7018c21350204c4cf628462f229d44d03545254.tar.bz2
linux-stable-f7018c21350204c4cf628462f229d44d03545254.zip
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related files, directories for backlight, console, linux logo, lots of fbdev device drivers, fbdev framework files. Make some order into the chaos by creating drivers/video/fbdev directory, and move all fbdev related files there. No functionality is changed, although I guess it is possible that some subtle Makefile build order related issue could be created by this patch. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Rob Clark <robdclark@gmail.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/fbdev/i810/i810-i2c.c')
-rw-r--r--drivers/video/fbdev/i810/i810-i2c.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/drivers/video/fbdev/i810/i810-i2c.c b/drivers/video/fbdev/i810/i810-i2c.c
new file mode 100644
index 000000000000..7db17d0d8a8c
--- /dev/null
+++ b/drivers/video/fbdev/i810/i810-i2c.c
@@ -0,0 +1,175 @@
+ /*-*- linux-c -*-
+ * linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support
+ *
+ * Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
+ * All Rights Reserved
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+#include "i810.h"
+#include "i810_regs.h"
+#include "i810_main.h"
+#include "../edid.h"
+
+/* bit locations in the registers */
+#define SCL_DIR_MASK 0x0001
+#define SCL_DIR 0x0002
+#define SCL_VAL_MASK 0x0004
+#define SCL_VAL_OUT 0x0008
+#define SCL_VAL_IN 0x0010
+#define SDA_DIR_MASK 0x0100
+#define SDA_DIR 0x0200
+#define SDA_VAL_MASK 0x0400
+#define SDA_VAL_OUT 0x0800
+#define SDA_VAL_IN 0x1000
+
+#define DEBUG /* define this for verbose EDID parsing output */
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(fmt,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static void i810i2c_setscl(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ if (state)
+ i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK);
+ else
+ i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
+ i810_readl(mmio, chan->ddc_base); /* flush posted write */
+}
+
+static void i810i2c_setsda(void *data, int state)
+{
+ struct i810fb_i2c_chan *chan = data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ if (state)
+ i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK);
+ else
+ i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
+ i810_readl(mmio, chan->ddc_base); /* flush posted write */
+}
+
+static int i810i2c_getscl(void *data)
+{
+ struct i810fb_i2c_chan *chan = data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK);
+ i810_writel(mmio, chan->ddc_base, 0);
+ return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0);
+}
+
+static int i810i2c_getsda(void *data)
+{
+ struct i810fb_i2c_chan *chan = data;
+ struct i810fb_par *par = chan->par;
+ u8 __iomem *mmio = par->mmio_start_virtual;
+
+ i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK);
+ i810_writel(mmio, chan->ddc_base, 0);
+ return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0);
+}
+
+static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
+{
+ int rc;
+
+ strcpy(chan->adapter.name, name);
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = &chan->par->dev->dev;
+ chan->algo.setsda = i810i2c_setsda;
+ chan->algo.setscl = i810i2c_setscl;
+ chan->algo.getsda = i810i2c_getsda;
+ chan->algo.getscl = i810i2c_getscl;
+ chan->algo.udelay = 10;
+ chan->algo.timeout = (HZ/2);
+ 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->dev->dev, "I2C bus %s registered.\n",name);
+ else {
+ dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
+ "%s.\n", name);
+ chan->par = NULL;
+ }
+
+ return rc;
+}
+
+void i810_create_i2c_busses(struct i810fb_par *par)
+{
+ par->chan[0].par = par;
+ par->chan[1].par = par;
+ par->chan[2].par = par;
+
+ par->chan[0].ddc_base = GPIOA;
+ i810_setup_i2c_bus(&par->chan[0], "I810-DDC");
+ par->chan[1].ddc_base = GPIOB;
+ i810_setup_i2c_bus(&par->chan[1], "I810-I2C");
+ par->chan[2].ddc_base = GPIOC;
+ i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC");
+}
+
+void i810_delete_i2c_busses(struct i810fb_par *par)
+{
+ if (par->chan[0].par)
+ i2c_del_adapter(&par->chan[0].adapter);
+ par->chan[0].par = NULL;
+
+ if (par->chan[1].par)
+ i2c_del_adapter(&par->chan[1].adapter);
+ par->chan[1].par = NULL;
+
+ if (par->chan[2].par)
+ i2c_del_adapter(&par->chan[2].adapter);
+ par->chan[2].par = NULL;
+}
+
+int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
+{
+ struct i810fb_par *par = info->par;
+ u8 *edid = NULL;
+
+ DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1);
+ if (conn < par->ddc_num) {
+ edid = fb_ddc_read(&par->chan[conn].adapter);
+ } else {
+ const u8 *e = fb_firmware_edid(info->device);
+
+ if (e != NULL) {
+ DPRINTK("i810-i2c: Getting EDID from BIOS\n");
+ edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
+ }
+ }
+
+ *out_edid = edid;
+
+ return (edid) ? 0 : 1;
+}