1/*
2 * Copyright 2013 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#include "priv.h"
25#include "aux.h"
26#include "bus.h"
27#include "pad.h"
28
29#include <core/option.h>
30#include <subdev/bios.h>
31#include <subdev/bios/dcb.h>
32#include <subdev/bios/i2c.h>
33
34static struct nvkm_i2c_pad *
35nvkm_i2c_pad_find(struct nvkm_i2c *i2c, int id)
36{
37	struct nvkm_i2c_pad *pad;
38
39	list_for_each_entry(pad, &i2c->pad, head) {
40		if (pad->id == id)
41			return pad;
42	}
43
44	return NULL;
45}
46
47struct nvkm_i2c_bus *
48nvkm_i2c_bus_find(struct nvkm_i2c *i2c, int id)
49{
50	struct nvkm_bios *bios = i2c->subdev.device->bios;
51	struct nvkm_i2c_bus *bus;
52
53	if (id == NVKM_I2C_BUS_PRI || id == NVKM_I2C_BUS_SEC) {
54		u8  ver, hdr, cnt, len;
55		u16 i2c = dcb_i2c_table(bios, &ver, &hdr, &cnt, &len);
56		if (i2c && ver >= 0x30) {
57			u8 auxidx = nvbios_rd08(bios, i2c + 4);
58			if (id == NVKM_I2C_BUS_PRI)
59				id = NVKM_I2C_BUS_CCB((auxidx & 0x0f) >> 0);
60			else
61				id = NVKM_I2C_BUS_CCB((auxidx & 0xf0) >> 4);
62		} else {
63			id = NVKM_I2C_BUS_CCB(2);
64		}
65	}
66
67	list_for_each_entry(bus, &i2c->bus, head) {
68		if (bus->id == id)
69			return bus;
70	}
71
72	return NULL;
73}
74
75struct nvkm_i2c_aux *
76nvkm_i2c_aux_find(struct nvkm_i2c *i2c, int id)
77{
78	struct nvkm_i2c_aux *aux;
79
80	list_for_each_entry(aux, &i2c->aux, head) {
81		if (aux->id == id)
82			return aux;
83	}
84
85	return NULL;
86}
87
88static void
89nvkm_i2c_intr_fini(struct nvkm_event *event, int type, int id)
90{
91	struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event);
92	struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id);
93	if (aux)
94		i2c->func->aux_mask(i2c, type, aux->intr, 0);
95}
96
97static void
98nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id)
99{
100	struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event);
101	struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id);
102	if (aux)
103		i2c->func->aux_mask(i2c, type, aux->intr, aux->intr);
104}
105
106static const struct nvkm_event_func
107nvkm_i2c_intr_func = {
108	.init = nvkm_i2c_intr_init,
109	.fini = nvkm_i2c_intr_fini,
110};
111
112static void
113nvkm_i2c_intr(struct nvkm_subdev *subdev)
114{
115	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
116	struct nvkm_i2c_aux *aux;
117	u32 hi, lo, rq, tx;
118
119	if (!i2c->func->aux_stat)
120		return;
121
122	i2c->func->aux_stat(i2c, &hi, &lo, &rq, &tx);
123	if (!hi && !lo && !rq && !tx)
124		return;
125
126	list_for_each_entry(aux, &i2c->aux, head) {
127		u32 mask = 0;
128		if (hi & aux->intr) mask |= NVKM_I2C_PLUG;
129		if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG;
130		if (rq & aux->intr) mask |= NVKM_I2C_IRQ;
131		if (tx & aux->intr) mask |= NVKM_I2C_DONE;
132		if (mask)
133			nvkm_event_ntfy(&i2c->event, aux->id, mask);
134	}
135}
136
137static int
138nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend)
139{
140	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
141	struct nvkm_i2c_pad *pad;
142	struct nvkm_i2c_bus *bus;
143	struct nvkm_i2c_aux *aux;
144	u32 mask;
145
146	list_for_each_entry(aux, &i2c->aux, head) {
147		nvkm_i2c_aux_fini(aux);
148	}
149
150	list_for_each_entry(bus, &i2c->bus, head) {
151		nvkm_i2c_bus_fini(bus);
152	}
153
154	if ((mask = (1 << i2c->func->aux) - 1), i2c->func->aux_stat) {
155		i2c->func->aux_mask(i2c, NVKM_I2C_ANY, mask, 0);
156		i2c->func->aux_stat(i2c, &mask, &mask, &mask, &mask);
157	}
158
159	list_for_each_entry(pad, &i2c->pad, head) {
160		nvkm_i2c_pad_fini(pad);
161	}
162
163	return 0;
164}
165
166static int
167nvkm_i2c_preinit(struct nvkm_subdev *subdev)
168{
169	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
170	struct nvkm_i2c_bus *bus;
171	struct nvkm_i2c_pad *pad;
172
173	/*
174	 * We init our i2c busses as early as possible, since they may be
175	 * needed by the vbios init scripts on some cards
176	 */
177	list_for_each_entry(pad, &i2c->pad, head)
178		nvkm_i2c_pad_init(pad);
179	list_for_each_entry(bus, &i2c->bus, head)
180		nvkm_i2c_bus_init(bus);
181
182	return 0;
183}
184
185static int
186nvkm_i2c_init(struct nvkm_subdev *subdev)
187{
188	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
189	struct nvkm_i2c_bus *bus;
190	struct nvkm_i2c_pad *pad;
191	struct nvkm_i2c_aux *aux;
192
193	list_for_each_entry(pad, &i2c->pad, head) {
194		nvkm_i2c_pad_init(pad);
195	}
196
197	list_for_each_entry(bus, &i2c->bus, head) {
198		nvkm_i2c_bus_init(bus);
199	}
200
201	list_for_each_entry(aux, &i2c->aux, head) {
202		nvkm_i2c_aux_init(aux);
203	}
204
205	return 0;
206}
207
208static void *
209nvkm_i2c_dtor(struct nvkm_subdev *subdev)
210{
211	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
212
213	nvkm_event_fini(&i2c->event);
214
215	while (!list_empty(&i2c->aux)) {
216		struct nvkm_i2c_aux *aux =
217			list_first_entry(&i2c->aux, typeof(*aux), head);
218		nvkm_i2c_aux_del(&aux);
219	}
220
221	while (!list_empty(&i2c->bus)) {
222		struct nvkm_i2c_bus *bus =
223			list_first_entry(&i2c->bus, typeof(*bus), head);
224		nvkm_i2c_bus_del(&bus);
225	}
226
227	while (!list_empty(&i2c->pad)) {
228		struct nvkm_i2c_pad *pad =
229			list_first_entry(&i2c->pad, typeof(*pad), head);
230		nvkm_i2c_pad_del(&pad);
231	}
232
233	return i2c;
234}
235
236static const struct nvkm_subdev_func
237nvkm_i2c = {
238	.dtor = nvkm_i2c_dtor,
239	.preinit = nvkm_i2c_preinit,
240	.init = nvkm_i2c_init,
241	.fini = nvkm_i2c_fini,
242	.intr = nvkm_i2c_intr,
243};
244
245static const struct nvkm_i2c_drv {
246	u8 bios;
247	u8 addr;
248	int (*pad_new)(struct nvkm_i2c_bus *, int id, u8 addr,
249		       struct nvkm_i2c_pad **);
250}
251nvkm_i2c_drv[] = {
252	{ 0x0d, 0x39, anx9805_pad_new },
253	{ 0x0e, 0x3b, anx9805_pad_new },
254	{}
255};
256
257int
258nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
259	      enum nvkm_subdev_type type, int inst, struct nvkm_i2c **pi2c)
260{
261	struct nvkm_bios *bios = device->bios;
262	struct nvkm_i2c *i2c;
263	struct nvkm_i2c_aux *aux;
264	struct dcb_i2c_entry ccbE;
265	struct dcb_output dcbE;
266	u8 ver, hdr;
267	int ret, i, ids;
268
269	if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL)))
270		return -ENOMEM;
271
272	nvkm_subdev_ctor(&nvkm_i2c, device, type, inst, &i2c->subdev);
273	i2c->func = func;
274	INIT_LIST_HEAD(&i2c->pad);
275	INIT_LIST_HEAD(&i2c->bus);
276	INIT_LIST_HEAD(&i2c->aux);
277
278	i = -1;
279	while (!dcb_i2c_parse(bios, ++i, &ccbE)) {
280		struct nvkm_i2c_pad *pad = NULL;
281		struct nvkm_i2c_bus *bus = NULL;
282		struct nvkm_i2c_aux *aux = NULL;
283
284		nvkm_debug(&i2c->subdev, "ccb %02x: type %02x drive %02x "
285			   "sense %02x share %02x auxch %02x\n", i, ccbE.type,
286			   ccbE.drive, ccbE.sense, ccbE.share, ccbE.auxch);
287
288		if (ccbE.share != DCB_I2C_UNUSED) {
289			const int id = NVKM_I2C_PAD_HYBRID(ccbE.share);
290			if (!(pad = nvkm_i2c_pad_find(i2c, id)))
291				ret = func->pad_s_new(i2c, id, &pad);
292			else
293				ret = 0;
294		} else {
295			ret = func->pad_x_new(i2c, NVKM_I2C_PAD_CCB(i), &pad);
296		}
297
298		if (ret) {
299			nvkm_error(&i2c->subdev, "ccb %02x pad, %d\n", i, ret);
300			nvkm_i2c_pad_del(&pad);
301			continue;
302		}
303
304		if (pad->func->bus_new_0 && ccbE.type == DCB_I2C_NV04_BIT) {
305			ret = pad->func->bus_new_0(pad, NVKM_I2C_BUS_CCB(i),
306						   ccbE.drive,
307						   ccbE.sense, &bus);
308		} else
309		if (pad->func->bus_new_4 &&
310		    ( ccbE.type == DCB_I2C_NV4E_BIT ||
311		      ccbE.type == DCB_I2C_NVIO_BIT ||
312		     (ccbE.type == DCB_I2C_PMGR &&
313		      ccbE.drive != DCB_I2C_UNUSED))) {
314			ret = pad->func->bus_new_4(pad, NVKM_I2C_BUS_CCB(i),
315						   ccbE.drive, &bus);
316		}
317
318		if (ret) {
319			nvkm_error(&i2c->subdev, "ccb %02x bus, %d\n", i, ret);
320			nvkm_i2c_bus_del(&bus);
321		}
322
323		if (pad->func->aux_new_6 &&
324		    ( ccbE.type == DCB_I2C_NVIO_AUX ||
325		     (ccbE.type == DCB_I2C_PMGR &&
326		      ccbE.auxch != DCB_I2C_UNUSED))) {
327			ret = pad->func->aux_new_6(pad, NVKM_I2C_BUS_CCB(i),
328						   ccbE.auxch, &aux);
329		} else {
330			ret = 0;
331		}
332
333		if (ret) {
334			nvkm_error(&i2c->subdev, "ccb %02x aux, %d\n", i, ret);
335			nvkm_i2c_aux_del(&aux);
336		}
337
338		if (ccbE.type != DCB_I2C_UNUSED && !bus && !aux) {
339			nvkm_warn(&i2c->subdev, "ccb %02x was ignored\n", i);
340			continue;
341		}
342	}
343
344	i = -1;
345	while (dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE)) {
346		const struct nvkm_i2c_drv *drv = nvkm_i2c_drv;
347		struct nvkm_i2c_bus *bus;
348		struct nvkm_i2c_pad *pad;
349
350		/* internal outputs handled by native i2c busses (above) */
351		if (!dcbE.location)
352			continue;
353
354		/* we need an i2c bus to talk to the external encoder */
355		bus = nvkm_i2c_bus_find(i2c, dcbE.i2c_index);
356		if (!bus) {
357			nvkm_debug(&i2c->subdev, "dcb %02x no bus\n", i);
358			continue;
359		}
360
361		/* ... and a driver for it */
362		while (drv->pad_new) {
363			if (drv->bios == dcbE.extdev)
364				break;
365			drv++;
366		}
367
368		if (!drv->pad_new) {
369			nvkm_debug(&i2c->subdev, "dcb %02x drv %02x unknown\n",
370				   i, dcbE.extdev);
371			continue;
372		}
373
374		/* find/create an instance of the driver */
375		pad = nvkm_i2c_pad_find(i2c, NVKM_I2C_PAD_EXT(dcbE.extdev));
376		if (!pad) {
377			const int id = NVKM_I2C_PAD_EXT(dcbE.extdev);
378			ret = drv->pad_new(bus, id, drv->addr, &pad);
379			if (ret) {
380				nvkm_error(&i2c->subdev, "dcb %02x pad, %d\n",
381					   i, ret);
382				nvkm_i2c_pad_del(&pad);
383				continue;
384			}
385		}
386
387		/* create any i2c bus / aux channel required by the output */
388		if (pad->func->aux_new_6 && dcbE.type == DCB_OUTPUT_DP) {
389			const int id = NVKM_I2C_AUX_EXT(dcbE.extdev);
390			struct nvkm_i2c_aux *aux = NULL;
391			ret = pad->func->aux_new_6(pad, id, 0, &aux);
392			if (ret) {
393				nvkm_error(&i2c->subdev, "dcb %02x aux, %d\n",
394					   i, ret);
395				nvkm_i2c_aux_del(&aux);
396			}
397		} else
398		if (pad->func->bus_new_4) {
399			const int id = NVKM_I2C_BUS_EXT(dcbE.extdev);
400			struct nvkm_i2c_bus *bus = NULL;
401			ret = pad->func->bus_new_4(pad, id, 0, &bus);
402			if (ret) {
403				nvkm_error(&i2c->subdev, "dcb %02x bus, %d\n",
404					   i, ret);
405				nvkm_i2c_bus_del(&bus);
406			}
407		}
408	}
409
410	ids = 0;
411	list_for_each_entry(aux, &i2c->aux, head)
412		ids = max(ids, aux->id + 1);
413	if (!ids)
414		return 0;
415
416	return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event);
417}
418