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