i810-i2c.c (5076B)
1 /*-*- linux-c -*- 2 * linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support 3 * 4 * Copyright (C) 2004 Antonino Daplas<adaplas@pol.net> 5 * All Rights Reserved 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file COPYING in the main directory of this archive for 9 * more details. 10 */ 11#include <linux/module.h> 12#include <linux/kernel.h> 13#include <linux/delay.h> 14#include <linux/gfp.h> 15#include <linux/pci.h> 16#include <linux/fb.h> 17#include "i810.h" 18#include "i810_regs.h" 19#include "i810_main.h" 20#include "../edid.h" 21 22/* bit locations in the registers */ 23#define SCL_DIR_MASK 0x0001 24#define SCL_DIR 0x0002 25#define SCL_VAL_MASK 0x0004 26#define SCL_VAL_OUT 0x0008 27#define SCL_VAL_IN 0x0010 28#define SDA_DIR_MASK 0x0100 29#define SDA_DIR 0x0200 30#define SDA_VAL_MASK 0x0400 31#define SDA_VAL_OUT 0x0800 32#define SDA_VAL_IN 0x1000 33 34#define DEBUG /* define this for verbose EDID parsing output */ 35 36#ifdef DEBUG 37#define DPRINTK(fmt, args...) printk(fmt,## args) 38#else 39#define DPRINTK(fmt, args...) 40#endif 41 42static void i810i2c_setscl(void *data, int state) 43{ 44 struct i810fb_i2c_chan *chan = data; 45 struct i810fb_par *par = chan->par; 46 u8 __iomem *mmio = par->mmio_start_virtual; 47 48 if (state) 49 i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK); 50 else 51 i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); 52 i810_readl(mmio, chan->ddc_base); /* flush posted write */ 53} 54 55static void i810i2c_setsda(void *data, int state) 56{ 57 struct i810fb_i2c_chan *chan = data; 58 struct i810fb_par *par = chan->par; 59 u8 __iomem *mmio = par->mmio_start_virtual; 60 61 if (state) 62 i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK); 63 else 64 i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); 65 i810_readl(mmio, chan->ddc_base); /* flush posted write */ 66} 67 68static int i810i2c_getscl(void *data) 69{ 70 struct i810fb_i2c_chan *chan = data; 71 struct i810fb_par *par = chan->par; 72 u8 __iomem *mmio = par->mmio_start_virtual; 73 74 i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK); 75 i810_writel(mmio, chan->ddc_base, 0); 76 return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0); 77} 78 79static int i810i2c_getsda(void *data) 80{ 81 struct i810fb_i2c_chan *chan = data; 82 struct i810fb_par *par = chan->par; 83 u8 __iomem *mmio = par->mmio_start_virtual; 84 85 i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK); 86 i810_writel(mmio, chan->ddc_base, 0); 87 return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); 88} 89 90static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) 91{ 92 int rc; 93 94 strcpy(chan->adapter.name, name); 95 chan->adapter.owner = THIS_MODULE; 96 chan->adapter.algo_data = &chan->algo; 97 chan->adapter.dev.parent = &chan->par->dev->dev; 98 chan->algo.setsda = i810i2c_setsda; 99 chan->algo.setscl = i810i2c_setscl; 100 chan->algo.getsda = i810i2c_getsda; 101 chan->algo.getscl = i810i2c_getscl; 102 chan->algo.udelay = 10; 103 chan->algo.timeout = (HZ/2); 104 chan->algo.data = chan; 105 106 i2c_set_adapdata(&chan->adapter, chan); 107 108 /* Raise SCL and SDA */ 109 chan->algo.setsda(chan, 1); 110 chan->algo.setscl(chan, 1); 111 udelay(20); 112 113 rc = i2c_bit_add_bus(&chan->adapter); 114 115 if (rc == 0) 116 dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); 117 else { 118 dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " 119 "%s.\n", name); 120 chan->par = NULL; 121 } 122 123 return rc; 124} 125 126void i810_create_i2c_busses(struct i810fb_par *par) 127{ 128 par->chan[0].par = par; 129 par->chan[1].par = par; 130 par->chan[2].par = par; 131 132 par->chan[0].ddc_base = GPIOA; 133 i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); 134 par->chan[1].ddc_base = GPIOB; 135 i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); 136 par->chan[2].ddc_base = GPIOC; 137 i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); 138} 139 140void i810_delete_i2c_busses(struct i810fb_par *par) 141{ 142 if (par->chan[0].par) 143 i2c_del_adapter(&par->chan[0].adapter); 144 par->chan[0].par = NULL; 145 146 if (par->chan[1].par) 147 i2c_del_adapter(&par->chan[1].adapter); 148 par->chan[1].par = NULL; 149 150 if (par->chan[2].par) 151 i2c_del_adapter(&par->chan[2].adapter); 152 par->chan[2].par = NULL; 153} 154 155int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) 156{ 157 struct i810fb_par *par = info->par; 158 u8 *edid = NULL; 159 160 DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1); 161 if (conn < par->ddc_num) { 162 edid = fb_ddc_read(&par->chan[conn].adapter); 163 } else { 164 const u8 *e = fb_firmware_edid(info->device); 165 166 if (e != NULL) { 167 DPRINTK("i810-i2c: Getting EDID from BIOS\n"); 168 edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); 169 } 170 } 171 172 *out_edid = edid; 173 174 return (edid) ? 0 : 1; 175}