diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 4f197b15acf6..7ec17e8435a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -22,11 +22,10 @@ * Authors: Ben Skeggs */ #include "priv.h" -#include "aux.h" +#include "auxch.h" #include "bus.h" #include "pad.h" -#include <core/notify.h> #include <core/option.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> @@ -104,23 +103,8 @@ nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id) i2c->func->aux_mask(i2c, type, aux->intr, aux->intr); } -static int -nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nvkm_i2c_ntfy_req *req = data; - if (!WARN_ON(size != sizeof(*req))) { - notify->size = sizeof(struct nvkm_i2c_ntfy_rep); - notify->types = req->mask; - notify->index = req->port; - return 0; - } - return -EINVAL; -} - static const struct nvkm_event_func nvkm_i2c_intr_func = { - .ctor = nvkm_i2c_intr_ctor, .init = nvkm_i2c_intr_init, .fini = nvkm_i2c_intr_fini, }; @@ -145,13 +129,8 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev) if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG; if (rq & aux->intr) mask |= NVKM_I2C_IRQ; if (tx & aux->intr) mask |= NVKM_I2C_DONE; - if (mask) { - struct nvkm_i2c_ntfy_rep rep = { - .mask = mask, - }; - nvkm_event_send(&i2c->event, rep.mask, aux->id, - &rep, sizeof(rep)); - } + if (mask) + nvkm_event_ntfy(&i2c->event, aux->id, mask); } } @@ -160,8 +139,18 @@ nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend) { struct nvkm_i2c *i2c = nvkm_i2c(subdev); struct nvkm_i2c_pad *pad; + struct nvkm_i2c_bus *bus; + struct nvkm_i2c_aux *aux; u32 mask; + list_for_each_entry(aux, &i2c->aux, head) { + nvkm_i2c_aux_fini(aux); + } + + list_for_each_entry(bus, &i2c->bus, head) { + nvkm_i2c_bus_fini(bus); + } + if ((mask = (1 << i2c->func->aux) - 1), i2c->func->aux_stat) { i2c->func->aux_mask(i2c, NVKM_I2C_ANY, mask, 0); i2c->func->aux_stat(i2c, &mask, &mask, &mask, &mask); @@ -175,11 +164,31 @@ nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend) } static int +nvkm_i2c_preinit(struct nvkm_subdev *subdev) +{ + struct nvkm_i2c *i2c = nvkm_i2c(subdev); + struct nvkm_i2c_bus *bus; + struct nvkm_i2c_pad *pad; + + /* + * We init our i2c busses as early as possible, since they may be + * needed by the vbios init scripts on some cards + */ + list_for_each_entry(pad, &i2c->pad, head) + nvkm_i2c_pad_init(pad); + list_for_each_entry(bus, &i2c->bus, head) + nvkm_i2c_bus_init(bus); + + return 0; +} + +static int nvkm_i2c_init(struct nvkm_subdev *subdev) { struct nvkm_i2c *i2c = nvkm_i2c(subdev); struct nvkm_i2c_bus *bus; struct nvkm_i2c_pad *pad; + struct nvkm_i2c_aux *aux; list_for_each_entry(pad, &i2c->pad, head) { nvkm_i2c_pad_init(pad); @@ -189,6 +198,10 @@ nvkm_i2c_init(struct nvkm_subdev *subdev) nvkm_i2c_bus_init(bus); } + list_for_each_entry(aux, &i2c->aux, head) { + nvkm_i2c_aux_init(aux); + } + return 0; } @@ -223,6 +236,7 @@ nvkm_i2c_dtor(struct nvkm_subdev *subdev) static const struct nvkm_subdev_func nvkm_i2c = { .dtor = nvkm_i2c_dtor, + .preinit = nvkm_i2c_preinit, .init = nvkm_i2c_init, .fini = nvkm_i2c_fini, .intr = nvkm_i2c_intr, @@ -242,19 +256,20 @@ nvkm_i2c_drv[] = { int nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, - int index, struct nvkm_i2c **pi2c) + enum nvkm_subdev_type type, int inst, struct nvkm_i2c **pi2c) { struct nvkm_bios *bios = device->bios; struct nvkm_i2c *i2c; + struct nvkm_i2c_aux *aux; struct dcb_i2c_entry ccbE; struct dcb_output dcbE; u8 ver, hdr; - int ret, i; + int ret, i, ids; if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) return -ENOMEM; - nvkm_subdev_ctor(&nvkm_i2c, device, index, &i2c->subdev); + nvkm_subdev_ctor(&nvkm_i2c, device, type, inst, &i2c->subdev); i2c->func = func; INIT_LIST_HEAD(&i2c->pad); INIT_LIST_HEAD(&i2c->bus); @@ -392,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, } } - return nvkm_event_init(&nvkm_i2c_intr_func, 4, i, &i2c->event); + ids = 0; + list_for_each_entry(aux, &i2c->aux, head) + ids = max(ids, aux->id + 1); + if (!ids) + return 0; + + return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event); } |
