i810-i2c.c revision 5a0e3ad6af8660be21ca98a971cd00f331318c05
174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas /*-*- linux-c -*- 274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support 374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * 474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * Copyright (C) 2004 Antonino Daplas<adaplas@pol.net> 574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * All Rights Reserved 674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * 774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * This file is subject to the terms and conditions of the GNU General Public 874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * License. See the file COPYING in the main directory of this archive for 974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas * more details. 1074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas */ 1174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include <linux/module.h> 1274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include <linux/kernel.h> 1374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include <linux/delay.h> 145a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 1574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include <linux/pci.h> 1674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include <linux/fb.h> 1774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include "i810.h" 1874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include "i810_regs.h" 19a0aa7d0639277f375989071fb52a7ce78beeef97Adrian Bunk#include "i810_main.h" 2074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#include "../edid.h" 2174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 2274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas/* bit locations in the registers */ 2374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SCL_DIR_MASK 0x0001 2474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SCL_DIR 0x0002 2574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SCL_VAL_MASK 0x0004 2674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SCL_VAL_OUT 0x0008 2774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SCL_VAL_IN 0x0010 2874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SDA_DIR_MASK 0x0100 2974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SDA_DIR 0x0200 3074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SDA_VAL_MASK 0x0400 3174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SDA_VAL_OUT 0x0800 3274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define SDA_VAL_IN 0x1000 3374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 3474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define DEBUG /* define this for verbose EDID parsing output */ 3574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 3674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#ifdef DEBUG 3774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define DPRINTK(fmt, args...) printk(fmt,## args) 3874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#else 3974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#define DPRINTK(fmt, args...) 4074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas#endif 4174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 4274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplasstatic void i810i2c_setscl(void *data, int state) 4374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 44c019c0ec97548d545c42961e960cbe2e8a6aabe9Antonino A. Daplas struct i810fb_i2c_chan *chan = data; 4574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas struct i810fb_par *par = chan->par; 46be88ec74cb48d1f60d0c0f059843f846f4481d87Al Viro u8 __iomem *mmio = par->mmio_start_virtual; 4774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 485fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_writel(mmio, chan->ddc_base, (state ? SCL_VAL_OUT : 0) | SCL_DIR | 4974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas SCL_DIR_MASK | SCL_VAL_MASK); 505fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_readl(mmio, chan->ddc_base); /* flush posted write */ 5174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 5274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 5374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplasstatic void i810i2c_setsda(void *data, int state) 5474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 555fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas struct i810fb_i2c_chan *chan = data; 5674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas struct i810fb_par *par = chan->par; 57be88ec74cb48d1f60d0c0f059843f846f4481d87Al Viro u8 __iomem *mmio = par->mmio_start_virtual; 5874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 595fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_writel(mmio, chan->ddc_base, (state ? SDA_VAL_OUT : 0) | SDA_DIR | 6074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas SDA_DIR_MASK | SDA_VAL_MASK); 615fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_readl(mmio, chan->ddc_base); /* flush posted write */ 6274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 6374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 6474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplasstatic int i810i2c_getscl(void *data) 6574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 665fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas struct i810fb_i2c_chan *chan = data; 6774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas struct i810fb_par *par = chan->par; 68be88ec74cb48d1f60d0c0f059843f846f4481d87Al Viro u8 __iomem *mmio = par->mmio_start_virtual; 6974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 705fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK); 715fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_writel(mmio, chan->ddc_base, 0); 725fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0); 7374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 7474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 7574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplasstatic int i810i2c_getsda(void *data) 7674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 775fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas struct i810fb_i2c_chan *chan = data; 7874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas struct i810fb_par *par = chan->par; 79be88ec74cb48d1f60d0c0f059843f846f4481d87Al Viro u8 __iomem *mmio = par->mmio_start_virtual; 8074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 815fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK); 825fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_writel(mmio, chan->ddc_base, 0); 835fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); 8474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 8574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 865fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplasstatic int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) 8774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 8874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas int rc; 8974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 9074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas strcpy(chan->adapter.name, name); 9174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->adapter.owner = THIS_MODULE; 9274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->adapter.algo_data = &chan->algo; 9374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->adapter.dev.parent = &chan->par->dev->dev; 945fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas chan->algo.setsda = i810i2c_setsda; 955fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas chan->algo.setscl = i810i2c_setscl; 965fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas chan->algo.getsda = i810i2c_getsda; 975fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas chan->algo.getscl = i810i2c_getscl; 9874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->algo.udelay = 10; 9974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->algo.timeout = (HZ/2); 10074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->algo.data = chan; 10174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 10274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas i2c_set_adapdata(&chan->adapter, chan); 10374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 10474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas /* Raise SCL and SDA */ 10574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->algo.setsda(chan, 1); 10674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas chan->algo.setscl(chan, 1); 10774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas udelay(20); 10874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 10974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas rc = i2c_bit_add_bus(&chan->adapter); 1105fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas 11174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas if (rc == 0) 11274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); 1135fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas else { 11474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " 11574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas "%s.\n", name); 1165fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas chan->par = NULL; 1175fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas } 1185fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas 11974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas return rc; 12074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 12174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 12274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplasvoid i810_create_i2c_busses(struct i810fb_par *par) 12374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 12474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas par->chan[0].par = par; 12574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas par->chan[1].par = par; 1265fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas par->chan[2].par = par; 1275fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas 1285fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas par->chan[0].ddc_base = GPIOA; 1295fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); 1305fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas par->chan[1].ddc_base = GPIOB; 1315fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); 1325fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas par->chan[2].ddc_base = GPIOC; 1335fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); 13474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 13574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 13674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplasvoid i810_delete_i2c_busses(struct i810fb_par *par) 13774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 13874f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas if (par->chan[0].par) 1393269711b76ba27b78862c48398b0d313ccaa99c2Jean Delvare i2c_del_adapter(&par->chan[0].adapter); 14074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas par->chan[0].par = NULL; 1415fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas 14274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas if (par->chan[1].par) 1433269711b76ba27b78862c48398b0d313ccaa99c2Jean Delvare i2c_del_adapter(&par->chan[1].adapter); 14474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas par->chan[1].par = NULL; 1455fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas 1465fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas if (par->chan[2].par) 1473269711b76ba27b78862c48398b0d313ccaa99c2Jean Delvare i2c_del_adapter(&par->chan[2].adapter); 1485fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas par->chan[2].par = NULL; 14974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 15074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 15174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplasint i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) 15274f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas{ 15374f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas struct i810fb_par *par = info->par; 15474f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas u8 *edid = NULL; 15574f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 15600d340b94f6df17d5dc478521e4ee1cfb30c53acManuel Lauss DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1); 15700d340b94f6df17d5dc478521e4ee1cfb30c53acManuel Lauss if (conn < par->ddc_num) { 158e80987f8db7b9c33089bb395ed54cb96d55eae04Antonino A. Daplas edid = fb_ddc_read(&par->chan[conn].adapter); 15974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas } else { 1605fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas const u8 *e = fb_firmware_edid(info->device); 1615fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas 1625fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas if (e != NULL) { 1635fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas DPRINTK("i810-i2c: Getting EDID from BIOS\n"); 164bfba7b3793f59adedfde5fb07dee565c5cc15ab8Alexey Dobriyan edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); 1655fab851ea15206cc375582ad0db79f7827325098Antonino A. Daplas } 16674f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas } 16774f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 1687c518eb84ce75d4c8e8799f4fcad59837f6d1894Antonino A. Daplas *out_edid = edid; 16974f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas 17074f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas return (edid) ? 0 : 1; 17174f6ae84b2315c2fa8a4110b09a1c0f3dca92674Antonino A. Daplas} 172