Home | History | Annotate | Line # | Download | only in i2c
      1 /*	$NetBSD: nouveau_nvkm_subdev_i2c_base.c,v 1.3 2021/12/18 23:45:40 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2013 Red Hat Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: Ben Skeggs
     25  */
     26 #include <sys/cdefs.h>
     27 __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_i2c_base.c,v 1.3 2021/12/18 23:45:40 riastradh Exp $");
     28 
     29 #include "priv.h"
     30 #include "aux.h"
     31 #include "bus.h"
     32 #include "pad.h"
     33 
     34 #include <core/notify.h>
     35 #include <core/option.h>
     36 #include <subdev/bios.h>
     37 #include <subdev/bios/dcb.h>
     38 #include <subdev/bios/i2c.h>
     39 
     40 static struct nvkm_i2c_pad *
     41 nvkm_i2c_pad_find(struct nvkm_i2c *i2c, int id)
     42 {
     43 	struct nvkm_i2c_pad *pad;
     44 
     45 	list_for_each_entry(pad, &i2c->pad, head) {
     46 		if (pad->id == id)
     47 			return pad;
     48 	}
     49 
     50 	return NULL;
     51 }
     52 
     53 struct nvkm_i2c_bus *
     54 nvkm_i2c_bus_find(struct nvkm_i2c *i2c, int id)
     55 {
     56 	struct nvkm_bios *bios = i2c->subdev.device->bios;
     57 	struct nvkm_i2c_bus *bus;
     58 
     59 	if (id == NVKM_I2C_BUS_PRI || id == NVKM_I2C_BUS_SEC) {
     60 		u8  ver, hdr, cnt, len;
     61 		u16 i2c = dcb_i2c_table(bios, &ver, &hdr, &cnt, &len);
     62 		if (i2c && ver >= 0x30) {
     63 			u8 auxidx = nvbios_rd08(bios, i2c + 4);
     64 			if (id == NVKM_I2C_BUS_PRI)
     65 				id = NVKM_I2C_BUS_CCB((auxidx & 0x0f) >> 0);
     66 			else
     67 				id = NVKM_I2C_BUS_CCB((auxidx & 0xf0) >> 4);
     68 		} else {
     69 			id = NVKM_I2C_BUS_CCB(2);
     70 		}
     71 	}
     72 
     73 	list_for_each_entry(bus, &i2c->bus, head) {
     74 		if (bus->id == id)
     75 			return bus;
     76 	}
     77 
     78 	return NULL;
     79 }
     80 
     81 struct nvkm_i2c_aux *
     82 nvkm_i2c_aux_find(struct nvkm_i2c *i2c, int id)
     83 {
     84 	struct nvkm_i2c_aux *aux;
     85 
     86 	list_for_each_entry(aux, &i2c->aux, head) {
     87 		if (aux->id == id)
     88 			return aux;
     89 	}
     90 
     91 	return NULL;
     92 }
     93 
     94 static void
     95 nvkm_i2c_intr_fini(struct nvkm_event *event, int type, int id)
     96 {
     97 	struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event);
     98 	struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id);
     99 	if (aux)
    100 		i2c->func->aux_mask(i2c, type, aux->intr, 0);
    101 }
    102 
    103 static void
    104 nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id)
    105 {
    106 	struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event);
    107 	struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id);
    108 	if (aux)
    109 		i2c->func->aux_mask(i2c, type, aux->intr, aux->intr);
    110 }
    111 
    112 static int
    113 nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size,
    114 		   struct nvkm_notify *notify)
    115 {
    116 	struct nvkm_i2c_ntfy_req *req = data;
    117 	if (!WARN_ON(size != sizeof(*req))) {
    118 		notify->size  = sizeof(struct nvkm_i2c_ntfy_rep);
    119 		notify->types = req->mask;
    120 		notify->index = req->port;
    121 		return 0;
    122 	}
    123 	return -EINVAL;
    124 }
    125 
    126 static const struct nvkm_event_func
    127 nvkm_i2c_intr_func = {
    128 	.ctor = nvkm_i2c_intr_ctor,
    129 	.init = nvkm_i2c_intr_init,
    130 	.fini = nvkm_i2c_intr_fini,
    131 };
    132 
    133 static void
    134 nvkm_i2c_intr(struct nvkm_subdev *subdev)
    135 {
    136 	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
    137 	struct nvkm_i2c_aux *aux;
    138 	u32 hi, lo, rq, tx;
    139 
    140 	if (!i2c->func->aux_stat)
    141 		return;
    142 
    143 	i2c->func->aux_stat(i2c, &hi, &lo, &rq, &tx);
    144 	if (!hi && !lo && !rq && !tx)
    145 		return;
    146 
    147 	list_for_each_entry(aux, &i2c->aux, head) {
    148 		u32 mask = 0;
    149 		if (hi & aux->intr) mask |= NVKM_I2C_PLUG;
    150 		if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG;
    151 		if (rq & aux->intr) mask |= NVKM_I2C_IRQ;
    152 		if (tx & aux->intr) mask |= NVKM_I2C_DONE;
    153 		if (mask) {
    154 			struct nvkm_i2c_ntfy_rep rep = {
    155 				.mask = mask,
    156 			};
    157 			nvkm_event_send(&i2c->event, rep.mask, aux->id,
    158 					&rep, sizeof(rep));
    159 		}
    160 	}
    161 }
    162 
    163 static int
    164 nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend)
    165 {
    166 	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
    167 	struct nvkm_i2c_pad *pad;
    168 	struct nvkm_i2c_bus *bus;
    169 	struct nvkm_i2c_aux *aux;
    170 	u32 mask;
    171 
    172 	list_for_each_entry(aux, &i2c->aux, head) {
    173 		nvkm_i2c_aux_fini(aux);
    174 	}
    175 
    176 	list_for_each_entry(bus, &i2c->bus, head) {
    177 		nvkm_i2c_bus_fini(bus);
    178 	}
    179 
    180 	if ((mask = (1 << i2c->func->aux) - 1), i2c->func->aux_stat) {
    181 		i2c->func->aux_mask(i2c, NVKM_I2C_ANY, mask, 0);
    182 		i2c->func->aux_stat(i2c, &mask, &mask, &mask, &mask);
    183 	}
    184 
    185 	list_for_each_entry(pad, &i2c->pad, head) {
    186 		nvkm_i2c_pad_fini(pad);
    187 	}
    188 
    189 	return 0;
    190 }
    191 
    192 static int
    193 nvkm_i2c_preinit(struct nvkm_subdev *subdev)
    194 {
    195 	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
    196 	struct nvkm_i2c_bus *bus;
    197 	struct nvkm_i2c_pad *pad;
    198 
    199 	/*
    200 	 * We init our i2c busses as early as possible, since they may be
    201 	 * needed by the vbios init scripts on some cards
    202 	 */
    203 	list_for_each_entry(pad, &i2c->pad, head)
    204 		nvkm_i2c_pad_init(pad);
    205 	list_for_each_entry(bus, &i2c->bus, head)
    206 		nvkm_i2c_bus_init(bus);
    207 
    208 	return 0;
    209 }
    210 
    211 static int
    212 nvkm_i2c_init(struct nvkm_subdev *subdev)
    213 {
    214 	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
    215 	struct nvkm_i2c_bus *bus;
    216 	struct nvkm_i2c_pad *pad;
    217 	struct nvkm_i2c_aux *aux;
    218 
    219 	list_for_each_entry(pad, &i2c->pad, head) {
    220 		nvkm_i2c_pad_init(pad);
    221 	}
    222 
    223 	list_for_each_entry(bus, &i2c->bus, head) {
    224 		nvkm_i2c_bus_init(bus);
    225 	}
    226 
    227 	list_for_each_entry(aux, &i2c->aux, head) {
    228 		nvkm_i2c_aux_init(aux);
    229 	}
    230 
    231 	return 0;
    232 }
    233 
    234 static void *
    235 nvkm_i2c_dtor(struct nvkm_subdev *subdev)
    236 {
    237 	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
    238 
    239 	nvkm_event_fini(&i2c->event);
    240 
    241 	while (!list_empty(&i2c->aux)) {
    242 		struct nvkm_i2c_aux *aux =
    243 			list_first_entry(&i2c->aux, typeof(*aux), head);
    244 		nvkm_i2c_aux_del(&aux);
    245 	}
    246 
    247 	while (!list_empty(&i2c->bus)) {
    248 		struct nvkm_i2c_bus *bus =
    249 			list_first_entry(&i2c->bus, typeof(*bus), head);
    250 		nvkm_i2c_bus_del(&bus);
    251 	}
    252 
    253 	while (!list_empty(&i2c->pad)) {
    254 		struct nvkm_i2c_pad *pad =
    255 			list_first_entry(&i2c->pad, typeof(*pad), head);
    256 		nvkm_i2c_pad_del(&pad);
    257 	}
    258 
    259 	return i2c;
    260 }
    261 
    262 static const struct nvkm_subdev_func
    263 nvkm_i2c = {
    264 	.dtor = nvkm_i2c_dtor,
    265 	.preinit = nvkm_i2c_preinit,
    266 	.init = nvkm_i2c_init,
    267 	.fini = nvkm_i2c_fini,
    268 	.intr = nvkm_i2c_intr,
    269 };
    270 
    271 static const struct nvkm_i2c_drv {
    272 	u8 bios;
    273 	u8 addr;
    274 	int (*pad_new)(struct nvkm_i2c_bus *, int id, u8 addr,
    275 		       struct nvkm_i2c_pad **);
    276 }
    277 nvkm_i2c_drv[] = {
    278 	{ 0x0d, 0x39, anx9805_pad_new },
    279 	{ 0x0e, 0x3b, anx9805_pad_new },
    280 	{}
    281 };
    282 
    283 int
    284 nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
    285 	      int index, struct nvkm_i2c **pi2c)
    286 {
    287 	struct nvkm_bios *bios = device->bios;
    288 	struct nvkm_i2c *i2c;
    289 	struct dcb_i2c_entry ccbE;
    290 	struct dcb_output dcbE;
    291 	u8 ver, hdr;
    292 	int ret, i;
    293 
    294 	if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL)))
    295 		return -ENOMEM;
    296 
    297 	nvkm_subdev_ctor(&nvkm_i2c, device, index, &i2c->subdev);
    298 	i2c->func = func;
    299 	INIT_LIST_HEAD(&i2c->pad);
    300 	INIT_LIST_HEAD(&i2c->bus);
    301 	INIT_LIST_HEAD(&i2c->aux);
    302 
    303 	i = -1;
    304 	while (!dcb_i2c_parse(bios, ++i, &ccbE)) {
    305 		struct nvkm_i2c_pad *pad = NULL;
    306 		struct nvkm_i2c_bus *bus = NULL;
    307 		struct nvkm_i2c_aux *aux = NULL;
    308 
    309 		nvkm_debug(&i2c->subdev, "ccb %02x: type %02x drive %02x "
    310 			   "sense %02x share %02x auxch %02x\n", i, ccbE.type,
    311 			   ccbE.drive, ccbE.sense, ccbE.share, ccbE.auxch);
    312 
    313 		if (ccbE.share != DCB_I2C_UNUSED) {
    314 			const int id = NVKM_I2C_PAD_HYBRID(ccbE.share);
    315 			if (!(pad = nvkm_i2c_pad_find(i2c, id)))
    316 				ret = func->pad_s_new(i2c, id, &pad);
    317 			else
    318 				ret = 0;
    319 		} else {
    320 			ret = func->pad_x_new(i2c, NVKM_I2C_PAD_CCB(i), &pad);
    321 		}
    322 
    323 		if (ret) {
    324 			nvkm_error(&i2c->subdev, "ccb %02x pad, %d\n", i, ret);
    325 			nvkm_i2c_pad_del(&pad);
    326 			continue;
    327 		}
    328 
    329 		if (pad->func->bus_new_0 && ccbE.type == DCB_I2C_NV04_BIT) {
    330 			ret = pad->func->bus_new_0(pad, NVKM_I2C_BUS_CCB(i),
    331 						   ccbE.drive,
    332 						   ccbE.sense, &bus);
    333 		} else
    334 		if (pad->func->bus_new_4 &&
    335 		    ( ccbE.type == DCB_I2C_NV4E_BIT ||
    336 		      ccbE.type == DCB_I2C_NVIO_BIT ||
    337 		     (ccbE.type == DCB_I2C_PMGR &&
    338 		      ccbE.drive != DCB_I2C_UNUSED))) {
    339 			ret = pad->func->bus_new_4(pad, NVKM_I2C_BUS_CCB(i),
    340 						   ccbE.drive, &bus);
    341 		}
    342 
    343 		if (ret) {
    344 			nvkm_error(&i2c->subdev, "ccb %02x bus, %d\n", i, ret);
    345 			nvkm_i2c_bus_del(&bus);
    346 		}
    347 
    348 		if (pad->func->aux_new_6 &&
    349 		    ( ccbE.type == DCB_I2C_NVIO_AUX ||
    350 		     (ccbE.type == DCB_I2C_PMGR &&
    351 		      ccbE.auxch != DCB_I2C_UNUSED))) {
    352 			ret = pad->func->aux_new_6(pad, NVKM_I2C_BUS_CCB(i),
    353 						   ccbE.auxch, &aux);
    354 		} else {
    355 			ret = 0;
    356 		}
    357 
    358 		if (ret) {
    359 			nvkm_error(&i2c->subdev, "ccb %02x aux, %d\n", i, ret);
    360 			nvkm_i2c_aux_del(&aux);
    361 		}
    362 
    363 		if (ccbE.type != DCB_I2C_UNUSED && !bus && !aux) {
    364 			nvkm_warn(&i2c->subdev, "ccb %02x was ignored\n", i);
    365 			continue;
    366 		}
    367 	}
    368 
    369 	i = -1;
    370 	while (dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE)) {
    371 		const struct nvkm_i2c_drv *drv = nvkm_i2c_drv;
    372 		struct nvkm_i2c_bus *bus;
    373 		struct nvkm_i2c_pad *pad;
    374 
    375 		/* internal outputs handled by native i2c busses (above) */
    376 		if (!dcbE.location)
    377 			continue;
    378 
    379 		/* we need an i2c bus to talk to the external encoder */
    380 		bus = nvkm_i2c_bus_find(i2c, dcbE.i2c_index);
    381 		if (!bus) {
    382 			nvkm_debug(&i2c->subdev, "dcb %02x no bus\n", i);
    383 			continue;
    384 		}
    385 
    386 		/* ... and a driver for it */
    387 		while (drv->pad_new) {
    388 			if (drv->bios == dcbE.extdev)
    389 				break;
    390 			drv++;
    391 		}
    392 
    393 		if (!drv->pad_new) {
    394 			nvkm_debug(&i2c->subdev, "dcb %02x drv %02x unknown\n",
    395 				   i, dcbE.extdev);
    396 			continue;
    397 		}
    398 
    399 		/* find/create an instance of the driver */
    400 		pad = nvkm_i2c_pad_find(i2c, NVKM_I2C_PAD_EXT(dcbE.extdev));
    401 		if (!pad) {
    402 			const int id = NVKM_I2C_PAD_EXT(dcbE.extdev);
    403 			ret = drv->pad_new(bus, id, drv->addr, &pad);
    404 			if (ret) {
    405 				nvkm_error(&i2c->subdev, "dcb %02x pad, %d\n",
    406 					   i, ret);
    407 				nvkm_i2c_pad_del(&pad);
    408 				continue;
    409 			}
    410 		}
    411 
    412 		/* create any i2c bus / aux channel required by the output */
    413 		if (pad->func->aux_new_6 && dcbE.type == DCB_OUTPUT_DP) {
    414 			const int id = NVKM_I2C_AUX_EXT(dcbE.extdev);
    415 			struct nvkm_i2c_aux *aux = NULL;
    416 			ret = pad->func->aux_new_6(pad, id, 0, &aux);
    417 			if (ret) {
    418 				nvkm_error(&i2c->subdev, "dcb %02x aux, %d\n",
    419 					   i, ret);
    420 				nvkm_i2c_aux_del(&aux);
    421 			}
    422 		} else
    423 		if (pad->func->bus_new_4) {
    424 			const int id = NVKM_I2C_BUS_EXT(dcbE.extdev);
    425 			struct nvkm_i2c_bus *bus = NULL;
    426 			ret = pad->func->bus_new_4(pad, id, 0, &bus);
    427 			if (ret) {
    428 				nvkm_error(&i2c->subdev, "dcb %02x bus, %d\n",
    429 					   i, ret);
    430 				nvkm_i2c_bus_del(&bus);
    431 			}
    432 		}
    433 	}
    434 
    435 	return nvkm_event_init(&nvkm_i2c_intr_func, 4, i, &i2c->event);
    436 }
    437