root/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nvkm_i2c_pad_find
  2. nvkm_i2c_bus_find
  3. nvkm_i2c_aux_find
  4. nvkm_i2c_intr_fini
  5. nvkm_i2c_intr_init
  6. nvkm_i2c_intr_ctor
  7. nvkm_i2c_intr
  8. nvkm_i2c_fini
  9. nvkm_i2c_preinit
  10. nvkm_i2c_init
  11. nvkm_i2c_dtor
  12. nvkm_i2c_new_

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

/* [<][>][^][v][top][bottom][index][help] */