1/* 2 * Copyright 2009 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24 25#include "drmP.h" 26#include "nouveau_drv.h" 27#include "nouveau_i2c.h" 28#include "nouveau_hw.h" 29 30static void 31nv04_i2c_setscl(void *data, int state) 32{ 33 struct nouveau_i2c_chan *i2c = data; 34 struct drm_device *dev = i2c->dev; 35 uint8_t val; 36 37 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0); 38 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); 39} 40 41static void 42nv04_i2c_setsda(void *data, int state) 43{ 44 struct nouveau_i2c_chan *i2c = data; 45 struct drm_device *dev = i2c->dev; 46 uint8_t val; 47 48 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0); 49 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); 50} 51 52static int 53nv04_i2c_getscl(void *data) 54{ 55 struct nouveau_i2c_chan *i2c = data; 56 struct drm_device *dev = i2c->dev; 57 58 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4); 59} 60 61static int 62nv04_i2c_getsda(void *data) 63{ 64 struct nouveau_i2c_chan *i2c = data; 65 struct drm_device *dev = i2c->dev; 66 67 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8); 68} 69 70static void 71nv4e_i2c_setscl(void *data, int state) 72{ 73 struct nouveau_i2c_chan *i2c = data; 74 struct drm_device *dev = i2c->dev; 75 uint8_t val; 76 77 val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0); 78 nv_wr32(dev, i2c->wr, val | 0x01); 79} 80 81static void 82nv4e_i2c_setsda(void *data, int state) 83{ 84 struct nouveau_i2c_chan *i2c = data; 85 struct drm_device *dev = i2c->dev; 86 uint8_t val; 87 88 val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0); 89 nv_wr32(dev, i2c->wr, val | 0x01); 90} 91 92static int 93nv4e_i2c_getscl(void *data) 94{ 95 struct nouveau_i2c_chan *i2c = data; 96 struct drm_device *dev = i2c->dev; 97 98 return !!((nv_rd32(dev, i2c->rd) >> 16) & 4); 99} 100 101static int 102nv4e_i2c_getsda(void *data) 103{ 104 struct nouveau_i2c_chan *i2c = data; 105 struct drm_device *dev = i2c->dev; 106 107 return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); 108} 109 110static int 111nv50_i2c_getscl(void *data) 112{ 113 struct nouveau_i2c_chan *i2c = data; 114 struct drm_device *dev = i2c->dev; 115 116 return !!(nv_rd32(dev, i2c->rd) & 1); 117} 118 119 120static int 121nv50_i2c_getsda(void *data) 122{ 123 struct nouveau_i2c_chan *i2c = data; 124 struct drm_device *dev = i2c->dev; 125 126 return !!(nv_rd32(dev, i2c->rd) & 2); 127} 128 129static void 130nv50_i2c_setscl(void *data, int state) 131{ 132 struct nouveau_i2c_chan *i2c = data; 133 struct drm_device *dev = i2c->dev; 134 135 nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); 136} 137 138static void 139nv50_i2c_setsda(void *data, int state) 140{ 141 struct nouveau_i2c_chan *i2c = data; 142 struct drm_device *dev = i2c->dev; 143 144 nv_wr32(dev, i2c->wr, 145 (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0)); 146 i2c->data = state; 147} 148 149static const uint32_t nv50_i2c_port[] = { 150 0x00e138, 0x00e150, 0x00e168, 0x00e180, 151 0x00e254, 0x00e274, 0x00e764, 0x00e780, 152 0x00e79c, 0x00e7b8 153}; 154#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) 155 156int 157nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) 158{ 159 struct drm_nouveau_private *dev_priv = dev->dev_private; 160 struct nouveau_i2c_chan *i2c; 161 int ret; 162 163 if (entry->chan) 164 return -EEXIST; 165 166 if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) { 167 NV_ERROR(dev, "unknown i2c port %d\n", entry->read); 168 return -EINVAL; 169 } 170 171 i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); 172 if (i2c == NULL) 173 return -ENOMEM; 174 175 switch (entry->port_type) { 176 case 0: 177 i2c->bit.setsda = nv04_i2c_setsda; 178 i2c->bit.setscl = nv04_i2c_setscl; 179 i2c->bit.getsda = nv04_i2c_getsda; 180 i2c->bit.getscl = nv04_i2c_getscl; 181 i2c->rd = entry->read; 182 i2c->wr = entry->write; 183 break; 184 case 4: 185 i2c->bit.setsda = nv4e_i2c_setsda; 186 i2c->bit.setscl = nv4e_i2c_setscl; 187 i2c->bit.getsda = nv4e_i2c_getsda; 188 i2c->bit.getscl = nv4e_i2c_getscl; 189 i2c->rd = 0x600800 + entry->read; 190 i2c->wr = 0x600800 + entry->write; 191 break; 192 case 5: 193 i2c->bit.setsda = nv50_i2c_setsda; 194 i2c->bit.setscl = nv50_i2c_setscl; 195 i2c->bit.getsda = nv50_i2c_getsda; 196 i2c->bit.getscl = nv50_i2c_getscl; 197 i2c->rd = nv50_i2c_port[entry->read]; 198 i2c->wr = i2c->rd; 199 break; 200 case 6: 201 i2c->rd = entry->read; 202 i2c->wr = entry->write; 203 break; 204 default: 205 NV_ERROR(dev, "DCB I2C port type %d unknown\n", 206 entry->port_type); 207 kfree(i2c); 208 return -EINVAL; 209 } 210 211 snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), 212 "nouveau-%s-%d", pci_name(dev->pdev), index); 213 i2c->adapter.owner = THIS_MODULE; 214 i2c->adapter.dev.parent = &dev->pdev->dev; 215 i2c->dev = dev; 216 i2c_set_adapdata(&i2c->adapter, i2c); 217 218 if (entry->port_type < 6) { 219 i2c->adapter.algo_data = &i2c->bit; 220 i2c->bit.udelay = 40; 221 i2c->bit.timeout = usecs_to_jiffies(5000); 222 i2c->bit.data = i2c; 223 ret = i2c_bit_add_bus(&i2c->adapter); 224 } else { 225 i2c->adapter.algo = &nouveau_dp_i2c_algo; 226 ret = i2c_add_adapter(&i2c->adapter); 227 } 228 229 if (ret) { 230 NV_ERROR(dev, "Failed to register i2c %d\n", index); 231 kfree(i2c); 232 return ret; 233 } 234 235 entry->chan = i2c; 236 return 0; 237} 238 239void 240nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry) 241{ 242 if (!entry->chan) 243 return; 244 245 i2c_del_adapter(&entry->chan->adapter); 246 kfree(entry->chan); 247 entry->chan = NULL; 248} 249 250struct nouveau_i2c_chan * 251nouveau_i2c_find(struct drm_device *dev, int index) 252{ 253 struct drm_nouveau_private *dev_priv = dev->dev_private; 254 struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index]; 255 256 if (index >= DCB_MAX_NUM_I2C_ENTRIES) 257 return NULL; 258 259 if (dev_priv->chipset >= NV_50 && (i2c->entry & 0x00000100)) { 260 uint32_t reg = 0xe500, val; 261 262 if (i2c->port_type == 6) { 263 reg += i2c->read * 0x50; 264 val = 0x2002; 265 } else { 266 reg += ((i2c->entry & 0x1e00) >> 9) * 0x50; 267 val = 0xe001; 268 } 269 270 nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val); 271 } 272 273 if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) 274 return NULL; 275 return i2c->chan; 276} 277 278bool 279nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr) 280{ 281 uint8_t buf[] = { 0 }; 282 struct i2c_msg msgs[] = { 283 { 284 .addr = addr, 285 .flags = 0, 286 .len = 1, 287 .buf = buf, 288 }, 289 { 290 .addr = addr, 291 .flags = I2C_M_RD, 292 .len = 1, 293 .buf = buf, 294 } 295 }; 296 297 return i2c_transfer(&i2c->adapter, msgs, 2) == 2; 298} 299 300int 301nouveau_i2c_identify(struct drm_device *dev, const char *what, 302 struct i2c_board_info *info, int index) 303{ 304 struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); 305 int i; 306 307 NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); 308 309 for (i = 0; info[i].addr; i++) { 310 if (nouveau_probe_i2c_addr(i2c, info[i].addr)) { 311 NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); 312 return i; 313 } 314 } 315 316 NV_DEBUG(dev, "No devices found.\n"); 317 318 return -ENODEV; 319} 320