nv_i2c.c revision 2707cd016b12d5e64c4feefcb5740b65f0c46845
1/* 2 * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c 3 * 4 * Copyright 2004 Antonino A. Daplas <adaplas @pol.net> 5 * 6 * Based on rivafb-i2c.c 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file COPYING in the main directory of this archive 10 * for more details. 11 */ 12 13#include <linux/module.h> 14#include <linux/kernel.h> 15#include <linux/delay.h> 16#include <linux/pci.h> 17#include <linux/fb.h> 18 19#include <asm/io.h> 20 21#include "nv_type.h" 22#include "nv_local.h" 23#include "nv_proto.h" 24 25#include "../edid.h" 26 27static void nvidia_gpio_setscl(void *data, int state) 28{ 29 struct nvidia_i2c_chan *chan = data; 30 struct nvidia_par *par = chan->par; 31 u32 val; 32 33 VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); 34 val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0; 35 36 if (state) 37 val |= 0x20; 38 else 39 val &= ~0x20; 40 41 VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); 42 VGA_WR08(par->PCIO, 0x3d5, val | 0x1); 43} 44 45static void nvidia_gpio_setsda(void *data, int state) 46{ 47 struct nvidia_i2c_chan *chan = data; 48 struct nvidia_par *par = chan->par; 49 u32 val; 50 51 VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); 52 val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0; 53 54 if (state) 55 val |= 0x10; 56 else 57 val &= ~0x10; 58 59 VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); 60 VGA_WR08(par->PCIO, 0x3d5, val | 0x1); 61} 62 63static int nvidia_gpio_getscl(void *data) 64{ 65 struct nvidia_i2c_chan *chan = data; 66 struct nvidia_par *par = chan->par; 67 u32 val = 0; 68 69 VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base); 70 if (VGA_RD08(par->PCIO, 0x3d5) & 0x04) 71 val = 1; 72 73 return val; 74} 75 76static int nvidia_gpio_getsda(void *data) 77{ 78 struct nvidia_i2c_chan *chan = data; 79 struct nvidia_par *par = chan->par; 80 u32 val = 0; 81 82 VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base); 83 if (VGA_RD08(par->PCIO, 0x3d5) & 0x08) 84 val = 1; 85 86 return val; 87} 88 89static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name) 90{ 91 int rc; 92 93 strcpy(chan->adapter.name, name); 94 chan->adapter.owner = THIS_MODULE; 95 chan->adapter.id = I2C_HW_B_NVIDIA; 96 chan->adapter.algo_data = &chan->algo; 97 chan->adapter.dev.parent = &chan->par->pci_dev->dev; 98 chan->algo.setsda = nvidia_gpio_setsda; 99 chan->algo.setscl = nvidia_gpio_setscl; 100 chan->algo.getsda = nvidia_gpio_getsda; 101 chan->algo.getscl = nvidia_gpio_getscl; 102 chan->algo.udelay = 40; 103 chan->algo.timeout = msecs_to_jiffies(2); 104 chan->algo.data = chan; 105 106 i2c_set_adapdata(&chan->adapter, chan); 107 108 /* Raise SCL and SDA */ 109 nvidia_gpio_setsda(chan, 1); 110 nvidia_gpio_setscl(chan, 1); 111 udelay(20); 112 113 rc = i2c_bit_add_bus(&chan->adapter); 114 if (rc == 0) 115 dev_dbg(&chan->par->pci_dev->dev, 116 "I2C bus %s registered.\n", name); 117 else { 118 dev_warn(&chan->par->pci_dev->dev, 119 "Failed to register I2C bus %s.\n", name); 120 chan->par = NULL; 121 } 122 123 return rc; 124} 125 126void nvidia_create_i2c_busses(struct nvidia_par *par) 127{ 128 par->bus = 3; 129 130 par->chan[0].par = par; 131 par->chan[1].par = par; 132 par->chan[2].par = par; 133 134 par->chan[0].ddc_base = 0x36; 135 nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0"); 136 137 par->chan[1].ddc_base = 0x3e; 138 nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1"); 139 140 par->chan[2].ddc_base = 0x50; 141 nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2"); 142} 143 144void nvidia_delete_i2c_busses(struct nvidia_par *par) 145{ 146 if (par->chan[0].par) 147 i2c_del_adapter(&par->chan[0].adapter); 148 par->chan[0].par = NULL; 149 150 if (par->chan[1].par) 151 i2c_del_adapter(&par->chan[1].adapter); 152 par->chan[1].par = NULL; 153 154 if (par->chan[2].par) 155 i2c_del_adapter(&par->chan[2].adapter); 156 par->chan[2].par = NULL; 157 158} 159 160int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) 161{ 162 struct nvidia_par *par = info->par; 163 u8 *edid = NULL; 164 165 if (par->chan[conn - 1].par) 166 edid = fb_ddc_read(&par->chan[conn - 1].adapter); 167 168 if (!edid && conn == 1) { 169 /* try to get from firmware */ 170 const u8 *e = fb_firmware_edid(info->device); 171 172 if (e != NULL) 173 edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); 174 } 175 176 *out_edid = edid; 177 178 return (edid) ? 0 : 1; 179} 180