blob: c6143df48b9f8a385d97e2b4d045c891f399ad90 [file] [log] [blame]
Ben Skeggs6ee73862009-12-11 19:24:15 +10001/*
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
Paul Gortmakere0cd3602011-08-30 11:04:30 -040025#include <linux/module.h>
26
Ben Skeggs6ee73862009-12-11 19:24:15 +100027#include "drmP.h"
28#include "nouveau_drv.h"
29#include "nouveau_i2c.h"
30#include "nouveau_hw.h"
31
32static void
33nv04_i2c_setscl(void *data, int state)
34{
35 struct nouveau_i2c_chan *i2c = data;
36 struct drm_device *dev = i2c->dev;
37 uint8_t val;
38
39 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
40 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
41}
42
43static void
44nv04_i2c_setsda(void *data, int state)
45{
46 struct nouveau_i2c_chan *i2c = data;
47 struct drm_device *dev = i2c->dev;
48 uint8_t val;
49
50 val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
51 NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01);
52}
53
54static int
55nv04_i2c_getscl(void *data)
56{
57 struct nouveau_i2c_chan *i2c = data;
58 struct drm_device *dev = i2c->dev;
59
60 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4);
61}
62
63static int
64nv04_i2c_getsda(void *data)
65{
66 struct nouveau_i2c_chan *i2c = data;
67 struct drm_device *dev = i2c->dev;
68
69 return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8);
70}
71
72static void
73nv4e_i2c_setscl(void *data, int state)
74{
75 struct nouveau_i2c_chan *i2c = data;
76 struct drm_device *dev = i2c->dev;
77 uint8_t val;
78
79 val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0);
80 nv_wr32(dev, i2c->wr, val | 0x01);
81}
82
83static void
84nv4e_i2c_setsda(void *data, int state)
85{
86 struct nouveau_i2c_chan *i2c = data;
87 struct drm_device *dev = i2c->dev;
88 uint8_t val;
89
90 val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0);
91 nv_wr32(dev, i2c->wr, val | 0x01);
92}
93
94static int
95nv4e_i2c_getscl(void *data)
96{
97 struct nouveau_i2c_chan *i2c = data;
98 struct drm_device *dev = i2c->dev;
99
100 return !!((nv_rd32(dev, i2c->rd) >> 16) & 4);
101}
102
103static int
104nv4e_i2c_getsda(void *data)
105{
106 struct nouveau_i2c_chan *i2c = data;
107 struct drm_device *dev = i2c->dev;
108
109 return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
110}
111
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000112static const uint32_t nv50_i2c_port[] = {
113 0x00e138, 0x00e150, 0x00e168, 0x00e180,
114 0x00e254, 0x00e274, 0x00e764, 0x00e780,
115 0x00e79c, 0x00e7b8
116};
117#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)
118
Ben Skeggs6ee73862009-12-11 19:24:15 +1000119static int
120nv50_i2c_getscl(void *data)
121{
122 struct nouveau_i2c_chan *i2c = data;
123 struct drm_device *dev = i2c->dev;
124
125 return !!(nv_rd32(dev, i2c->rd) & 1);
126}
127
128
129static int
130nv50_i2c_getsda(void *data)
131{
132 struct nouveau_i2c_chan *i2c = data;
133 struct drm_device *dev = i2c->dev;
134
135 return !!(nv_rd32(dev, i2c->rd) & 2);
136}
137
138static void
139nv50_i2c_setscl(void *data, int state)
140{
141 struct nouveau_i2c_chan *i2c = data;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000142
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000143 nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0));
Ben Skeggs6ee73862009-12-11 19:24:15 +1000144}
145
146static void
147nv50_i2c_setsda(void *data, int state)
148{
149 struct nouveau_i2c_chan *i2c = data;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000150
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000151 nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0));
Ben Skeggs6ee73862009-12-11 19:24:15 +1000152 i2c->data = state;
153}
154
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000155static int
156nvd0_i2c_getscl(void *data)
157{
158 struct nouveau_i2c_chan *i2c = data;
159 return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10);
160}
161
162static int
163nvd0_i2c_getsda(void *data)
164{
165 struct nouveau_i2c_chan *i2c = data;
166 return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20);
167}
Ben Skeggs6ee73862009-12-11 19:24:15 +1000168
169int
170nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
171{
172 struct drm_nouveau_private *dev_priv = dev->dev_private;
173 struct nouveau_i2c_chan *i2c;
174 int ret;
175
176 if (entry->chan)
177 return -EEXIST;
178
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000179 if (dev_priv->card_type >= NV_50 &&
180 dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) {
Ben Skeggs6ee73862009-12-11 19:24:15 +1000181 NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
182 return -EINVAL;
183 }
184
185 i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
186 if (i2c == NULL)
187 return -ENOMEM;
188
189 switch (entry->port_type) {
190 case 0:
Ben Skeggsc020c9a2010-07-29 21:01:45 +1000191 i2c->bit.setsda = nv04_i2c_setsda;
192 i2c->bit.setscl = nv04_i2c_setscl;
193 i2c->bit.getsda = nv04_i2c_getsda;
194 i2c->bit.getscl = nv04_i2c_getscl;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000195 i2c->rd = entry->read;
196 i2c->wr = entry->write;
197 break;
198 case 4:
Ben Skeggsc020c9a2010-07-29 21:01:45 +1000199 i2c->bit.setsda = nv4e_i2c_setsda;
200 i2c->bit.setscl = nv4e_i2c_setscl;
201 i2c->bit.getsda = nv4e_i2c_getsda;
202 i2c->bit.getscl = nv4e_i2c_getscl;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000203 i2c->rd = 0x600800 + entry->read;
204 i2c->wr = 0x600800 + entry->write;
205 break;
206 case 5:
Ben Skeggsc020c9a2010-07-29 21:01:45 +1000207 i2c->bit.setsda = nv50_i2c_setsda;
208 i2c->bit.setscl = nv50_i2c_setscl;
Ben Skeggseeb3ca12011-07-02 20:43:42 +1000209 if (dev_priv->card_type < NV_D0) {
210 i2c->bit.getsda = nv50_i2c_getsda;
211 i2c->bit.getscl = nv50_i2c_getscl;
212 i2c->rd = nv50_i2c_port[entry->read];
213 i2c->wr = i2c->rd;
214 } else {
215 i2c->bit.getsda = nvd0_i2c_getsda;
216 i2c->bit.getscl = nvd0_i2c_getscl;
217 i2c->rd = 0x00d014 + (entry->read * 0x20);
218 i2c->wr = i2c->rd;
219 }
Ben Skeggs6ee73862009-12-11 19:24:15 +1000220 break;
221 case 6:
222 i2c->rd = entry->read;
223 i2c->wr = entry->write;
224 break;
225 default:
226 NV_ERROR(dev, "DCB I2C port type %d unknown\n",
227 entry->port_type);
228 kfree(i2c);
229 return -EINVAL;
230 }
231
232 snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
233 "nouveau-%s-%d", pci_name(dev->pdev), index);
234 i2c->adapter.owner = THIS_MODULE;
235 i2c->adapter.dev.parent = &dev->pdev->dev;
236 i2c->dev = dev;
237 i2c_set_adapdata(&i2c->adapter, i2c);
238
239 if (entry->port_type < 6) {
Ben Skeggsc020c9a2010-07-29 21:01:45 +1000240 i2c->adapter.algo_data = &i2c->bit;
241 i2c->bit.udelay = 40;
242 i2c->bit.timeout = usecs_to_jiffies(5000);
243 i2c->bit.data = i2c;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000244 ret = i2c_bit_add_bus(&i2c->adapter);
245 } else {
Ben Skeggsc020c9a2010-07-29 21:01:45 +1000246 i2c->adapter.algo = &nouveau_dp_i2c_algo;
247 ret = i2c_add_adapter(&i2c->adapter);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000248 }
249
250 if (ret) {
251 NV_ERROR(dev, "Failed to register i2c %d\n", index);
252 kfree(i2c);
253 return ret;
254 }
255
256 entry->chan = i2c;
257 return 0;
258}
259
260void
261nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry)
262{
263 if (!entry->chan)
264 return;
265
266 i2c_del_adapter(&entry->chan->adapter);
267 kfree(entry->chan);
268 entry->chan = NULL;
269}
270
271struct nouveau_i2c_chan *
272nouveau_i2c_find(struct drm_device *dev, int index)
273{
274 struct drm_nouveau_private *dev_priv = dev->dev_private;
Ben Skeggs7e99a9b2010-04-24 03:53:14 +1000275 struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index];
Ben Skeggs6ee73862009-12-11 19:24:15 +1000276
Marcin Slusarzb762b8c2010-02-17 19:04:01 +0100277 if (index >= DCB_MAX_NUM_I2C_ENTRIES)
Ben Skeggs6ee73862009-12-11 19:24:15 +1000278 return NULL;
279
Francisco Jerezc1b60ec2010-11-11 00:56:37 +0100280 if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) {
Ben Skeggs7e99a9b2010-04-24 03:53:14 +1000281 uint32_t reg = 0xe500, val;
282
283 if (i2c->port_type == 6) {
284 reg += i2c->read * 0x50;
285 val = 0x2002;
286 } else {
287 reg += ((i2c->entry & 0x1e00) >> 9) * 0x50;
288 val = 0xe001;
289 }
290
Ben Skeggs6b70e482011-07-19 15:59:39 +1000291 /* nfi, but neither auxch or i2c work if it's 1 */
292 nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000);
293 /* nfi, but switches auxch vs normal i2c */
294 nv_mask(dev, reg + 0x00, 0x0000f003, val);
Ben Skeggs6ee73862009-12-11 19:24:15 +1000295 }
296
Ben Skeggs7e99a9b2010-04-24 03:53:14 +1000297 if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
298 return NULL;
299 return i2c->chan;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000300}
301
Francisco Jerez6d416d82010-07-19 15:55:08 +0200302bool
303nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
304{
Francisco Jerezf1feda72010-07-23 23:17:57 +0200305 uint8_t buf[] = { 0 };
306 struct i2c_msg msgs[] = {
307 {
308 .addr = addr,
309 .flags = 0,
310 .len = 1,
311 .buf = buf,
312 },
313 {
314 .addr = addr,
315 .flags = I2C_M_RD,
316 .len = 1,
317 .buf = buf,
318 }
Francisco Jerez6d416d82010-07-19 15:55:08 +0200319 };
320
Francisco Jerezf1feda72010-07-23 23:17:57 +0200321 return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200322}
323
324int
325nouveau_i2c_identify(struct drm_device *dev, const char *what,
Francisco Jerez66146da2010-09-23 21:00:40 +0200326 struct i2c_board_info *info,
327 bool (*match)(struct nouveau_i2c_chan *,
328 struct i2c_board_info *),
329 int index)
Francisco Jerez6d416d82010-07-19 15:55:08 +0200330{
331 struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
Francisco Jerez946fd352010-07-24 17:41:48 +0200332 int i;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200333
Francisco Jerez6d416d82010-07-19 15:55:08 +0200334 NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
335
336 for (i = 0; info[i].addr; i++) {
Francisco Jerez66146da2010-09-23 21:00:40 +0200337 if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
338 (!match || match(i2c, &info[i]))) {
Francisco Jerez6d416d82010-07-19 15:55:08 +0200339 NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
Francisco Jerez946fd352010-07-24 17:41:48 +0200340 return i;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200341 }
342 }
343
344 NV_DEBUG(dev, "No devices found.\n");
Francisco Jerez6d416d82010-07-19 15:55:08 +0200345
Francisco Jerez946fd352010-07-24 17:41:48 +0200346 return -ENODEV;
Francisco Jerez6d416d82010-07-19 15:55:08 +0200347}