提交 9efc583e 编写于 作者: B Ben Skeggs

drm/nouveau/i2c: introduce locking at a per-port level

There's also provisions to allow a pad to be locked with a specific
routing, for an indefinite period of time.  This will be used in
future patches.

The G94+ pad driver will now also power-down pads when not required.
Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 d2ae2eb4
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -132,6 +132,9 @@ nouveau-y += core/subdev/i2c/base.o
nouveau-y += core/subdev/i2c/anx9805.o
nouveau-y += core/subdev/i2c/aux.o
nouveau-y += core/subdev/i2c/bit.o
nouveau-y += core/subdev/i2c/pad.o
nouveau-y += core/subdev/i2c/padnv04.o
nouveau-y += core/subdev/i2c/padnv94.o
nouveau-y += core/subdev/i2c/nv04.o
nouveau-y += core/subdev/i2c/nv4e.o
nouveau-y += core/subdev/i2c/nv50.o
......
......@@ -28,6 +28,7 @@ enum nvkm_i2c_event {
struct nouveau_i2c_port {
struct nouveau_object base;
struct i2c_adapter adapter;
struct mutex mutex;
struct list_head head;
u8 index;
......@@ -37,9 +38,6 @@ struct nouveau_i2c_port {
};
struct nouveau_i2c_func {
void (*acquire)(struct nouveau_i2c_port *);
void (*release)(struct nouveau_i2c_port *);
void (*drive_scl)(struct nouveau_i2c_port *, int);
void (*drive_sda)(struct nouveau_i2c_port *, int);
int (*sense_scl)(struct nouveau_i2c_port *);
......@@ -62,12 +60,16 @@ struct nouveau_i2c {
struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index);
struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type);
int (*acquire_pad)(struct nouveau_i2c_port *, unsigned long timeout);
void (*release_pad)(struct nouveau_i2c_port *);
int (*acquire)(struct nouveau_i2c_port *, unsigned long timeout);
void (*release)(struct nouveau_i2c_port *);
int (*identify)(struct nouveau_i2c *, int index,
const char *what, struct nouveau_i2c_board_info *,
bool (*match)(struct nouveau_i2c_port *,
struct i2c_board_info *, void *), void *);
wait_queue_head_t wait;
struct list_head ports;
};
......
......@@ -31,6 +31,7 @@
#include <subdev/vga.h>
#include "priv.h"
#include "pad.h"
/******************************************************************************
* interface to linux i2c bit-banging algorithm
......@@ -90,6 +91,15 @@ nouveau_i2c_getsda(void *data)
* base i2c "port" class implementation
*****************************************************************************/
int
_nouveau_i2c_port_fini(struct nouveau_object *object, bool suspend)
{
struct nouveau_i2c_port *port = (void *)object;
struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port);
nv_ofuncs(pad)->fini(nv_object(pad), suspend);
return nouveau_object_fini(&port->base, suspend);
}
void
_nouveau_i2c_port_dtor(struct nouveau_object *object)
{
......@@ -106,7 +116,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
const struct nouveau_i2c_func *func,
int size, void **pobject)
{
struct nouveau_device *device = nv_device(parent);
struct nouveau_device *device = nv_device(engine);
struct nouveau_i2c *i2c = (void *)engine;
struct nouveau_i2c_port *port;
int ret;
......@@ -123,6 +133,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
port->index = index;
port->aux = -1;
port->func = func;
mutex_init(&port->mutex);
if ( algo == &nouveau_i2c_bit_algo &&
!nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) {
......@@ -201,19 +212,73 @@ nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type)
return NULL;
}
static void
nouveau_i2c_release_pad(struct nouveau_i2c_port *port)
{
struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port);
struct nouveau_i2c *i2c = nouveau_i2c(port);
if (atomic_dec_and_test(&nv_object(pad)->usecount)) {
nv_ofuncs(pad)->fini(nv_object(pad), false);
wake_up_all(&i2c->wait);
}
}
static int
nouveau_i2c_try_acquire_pad(struct nouveau_i2c_port *port)
{
struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port);
if (atomic_add_return(1, &nv_object(pad)->usecount) != 1) {
struct nouveau_object *owner = (void *)pad->port;
do {
if (owner == (void *)port)
return 0;
owner = owner->parent;
} while(owner);
nouveau_i2c_release_pad(port);
return -EBUSY;
}
pad->next = port;
nv_ofuncs(pad)->init(nv_object(pad));
return 0;
}
static int
nouveau_i2c_acquire_pad(struct nouveau_i2c_port *port, unsigned long timeout)
{
struct nouveau_i2c *i2c = nouveau_i2c(port);
if (timeout) {
if (wait_event_timeout(i2c->wait,
nouveau_i2c_try_acquire_pad(port) == 0,
timeout) == 0)
return -EBUSY;
} else {
wait_event(i2c->wait, nouveau_i2c_try_acquire_pad(port) == 0);
}
return 0;
}
static void
nouveau_i2c_release(struct nouveau_i2c_port *port)
__releases(pad->mutex)
{
if (port->func->release)
port->func->release(port);
nouveau_i2c(port)->release_pad(port);
mutex_unlock(&port->mutex);
}
static int
nouveau_i2c_acquire(struct nouveau_i2c_port *port, unsigned long timeout)
__acquires(pad->mutex)
{
if (port->func->acquire)
port->func->acquire(port);
return 0;
int ret;
mutex_lock(&port->mutex);
if ((ret = nouveau_i2c(port)->acquire_pad(port, timeout)))
mutex_unlock(&port->mutex);
return ret;
}
static int
......@@ -391,7 +456,7 @@ nouveau_i2c_create_(struct nouveau_object *parent,
struct nouveau_i2c *i2c;
struct nouveau_object *object;
struct dcb_i2c_entry info;
int ret, i, j, index = -1;
int ret, i, j, index = -1, pad;
struct dcb_output outp;
u8 ver, hdr;
u32 data;
......@@ -405,24 +470,45 @@ nouveau_i2c_create_(struct nouveau_object *parent,
nv_subdev(i2c)->intr = nouveau_i2c_intr;
i2c->find = nouveau_i2c_find;
i2c->find_type = nouveau_i2c_find_type;
i2c->acquire_pad = nouveau_i2c_acquire_pad;
i2c->release_pad = nouveau_i2c_release_pad;
i2c->acquire = nouveau_i2c_acquire;
i2c->release = nouveau_i2c_release;
i2c->identify = nouveau_i2c_identify;
init_waitqueue_head(&i2c->wait);
INIT_LIST_HEAD(&i2c->ports);
while (!dcb_i2c_parse(bios, ++index, &info)) {
if (info.type == DCB_I2C_UNUSED)
continue;
if (info.share != DCB_I2C_UNUSED) {
if (info.type == DCB_I2C_NVIO_AUX)
pad = info.drive;
else
pad = info.share;
oclass = impl->pad_s;
} else {
pad = 0x100 + info.drive;
oclass = impl->pad_x;
}
ret = nouveau_object_ctor(NULL, *pobject, oclass,
NULL, pad, &parent);
if (ret < 0)
continue;
oclass = impl->sclass;
do {
ret = -EINVAL;
if (oclass->handle == info.type) {
ret = nouveau_object_ctor(*pobject, *pobject,
ret = nouveau_object_ctor(parent, *pobject,
oclass, &info,
index, &object);
}
} while (ret && (++oclass)->handle);
nouveau_object_ref(NULL, &parent);
}
/* in addition to the busses specified in the i2c table, there
......
......@@ -126,4 +126,5 @@ nv04_i2c_oclass = &(struct nouveau_i2c_impl) {
.fini = _nouveau_i2c_fini,
},
.sclass = nv04_i2c_sclass,
.pad_x = &nv04_i2c_pad_oclass,
}.base;
......@@ -118,4 +118,5 @@ nv4e_i2c_oclass = &(struct nouveau_i2c_impl) {
.fini = _nouveau_i2c_fini,
},
.sclass = nv4e_i2c_sclass,
.pad_x = &nv04_i2c_pad_oclass,
}.base;
......@@ -131,4 +131,5 @@ nv50_i2c_oclass = &(struct nouveau_i2c_impl) {
.fini = _nouveau_i2c_fini,
},
.sclass = nv50_i2c_sclass,
.pad_x = &nv04_i2c_pad_oclass,
}.base;
......@@ -185,26 +185,8 @@ nv94_aux(struct nouveau_i2c_port *base, bool retry,
return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
}
void
nv94_i2c_acquire(struct nouveau_i2c_port *base)
{
struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine;
struct nv50_i2c_port *port = (void *)base;
if (port->ctrl) {
nv_mask(priv, port->ctrl + 0x0c, 0x00000001, 0x00000000);
nv_mask(priv, port->ctrl + 0x00, 0x0000f003, port->data);
}
}
void
nv94_i2c_release(struct nouveau_i2c_port *base)
{
}
static const struct nouveau_i2c_func
nv94_i2c_func = {
.acquire = nv94_i2c_acquire,
.release = nv94_i2c_release,
.drive_scl = nv50_i2c_drive_scl,
.drive_sda = nv50_i2c_drive_sda,
.sense_scl = nv50_i2c_sense_scl,
......@@ -241,8 +223,6 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
static const struct nouveau_i2c_func
nv94_aux_func = {
.acquire = nv94_i2c_acquire,
.release = nv94_i2c_release,
.aux = nv94_aux,
};
......@@ -303,6 +283,8 @@ nv94_i2c_oclass = &(struct nouveau_i2c_impl) {
.fini = _nouveau_i2c_fini,
},
.sclass = nv94_i2c_sclass,
.pad_x = &nv04_i2c_pad_oclass,
.pad_s = &nv94_i2c_pad_oclass,
.aux = 4,
.aux_stat = nv94_aux_stat,
.aux_mask = nv94_aux_mask,
......
......@@ -42,8 +42,6 @@ nvd0_i2c_sense_sda(struct nouveau_i2c_port *base)
static const struct nouveau_i2c_func
nvd0_i2c_func = {
.acquire = nv94_i2c_acquire,
.release = nv94_i2c_release,
.drive_scl = nv50_i2c_drive_scl,
.drive_sda = nv50_i2c_drive_sda,
.sense_scl = nvd0_i2c_sense_scl,
......@@ -106,6 +104,8 @@ nvd0_i2c_oclass = &(struct nouveau_i2c_impl) {
.fini = _nouveau_i2c_fini,
},
.sclass = nvd0_i2c_sclass,
.pad_x = &nv04_i2c_pad_oclass,
.pad_s = &nv94_i2c_pad_oclass,
.aux = 4,
.aux_stat = nv94_aux_stat,
.aux_mask = nv94_aux_mask,
......
......@@ -64,6 +64,8 @@ nve0_i2c_oclass = &(struct nouveau_i2c_impl) {
.fini = _nouveau_i2c_fini,
},
.sclass = nvd0_i2c_sclass,
.pad_x = &nv04_i2c_pad_oclass,
.pad_s = &nv94_i2c_pad_oclass,
.aux = 4,
.aux_stat = nve0_aux_stat,
.aux_mask = nve0_aux_mask,
......
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "pad.h"
int
_nvkm_i2c_pad_fini(struct nouveau_object *object, bool suspend)
{
struct nvkm_i2c_pad *pad = (void *)object;
DBG("-> NULL\n");
pad->port = NULL;
return nouveau_object_fini(&pad->base, suspend);
}
int
_nvkm_i2c_pad_init(struct nouveau_object *object)
{
struct nvkm_i2c_pad *pad = (void *)object;
DBG("-> PORT:%02x\n", pad->next->index);
pad->port = pad->next;
return nouveau_object_init(&pad->base);
}
int
nvkm_i2c_pad_create_(struct nouveau_object *parent,
struct nouveau_object *engine,
struct nouveau_oclass *oclass, int index,
int size, void **pobject)
{
struct nouveau_i2c *i2c = (void *)engine;
struct nouveau_i2c_port *port;
struct nvkm_i2c_pad *pad;
int ret;
list_for_each_entry(port, &i2c->ports, head) {
pad = nvkm_i2c_pad(port);
if (pad->index == index) {
atomic_inc(&nv_object(pad)->refcount);
*pobject = pad;
return 1;
}
}
ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject);
pad = *pobject;
if (ret)
return ret;
pad->index = index;
return 0;
}
int
_nvkm_i2c_pad_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 index,
struct nouveau_object **pobject)
{
struct nvkm_i2c_pad *pad;
int ret;
ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad);
*pobject = nv_object(pad);
return ret;
}
#ifndef __NVKM_I2C_PAD_H__
#define __NVKM_I2C_PAD_H__
#include "priv.h"
struct nvkm_i2c_pad {
struct nouveau_object base;
int index;
struct nouveau_i2c_port *port;
struct nouveau_i2c_port *next;
};
static inline struct nvkm_i2c_pad *
nvkm_i2c_pad(struct nouveau_i2c_port *port)
{
struct nouveau_object *pad = nv_object(port);
while (pad->parent)
pad = pad->parent;
return (void *)pad;
}
#define nvkm_i2c_pad_create(p,e,o,i,d) \
nvkm_i2c_pad_create_((p), (e), (o), (i), sizeof(**d), (void **)d)
#define nvkm_i2c_pad_destroy(p) ({ \
struct nvkm_i2c_pad *_p = (p); \
_nvkm_i2c_pad_dtor(nv_object(_p)); \
})
#define nvkm_i2c_pad_init(p) ({ \
struct nvkm_i2c_pad *_p = (p); \
_nvkm_i2c_pad_init(nv_object(_p)); \
})
#define nvkm_i2c_pad_fini(p,s) ({ \
struct nvkm_i2c_pad *_p = (p); \
_nvkm_i2c_pad_fini(nv_object(_p), (s)); \
})
int nvkm_i2c_pad_create_(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, int index, int, void **);
int _nvkm_i2c_pad_ctor(struct nouveau_object *, struct nouveau_object *,
struct nouveau_oclass *, void *, u32,
struct nouveau_object **);
#define _nvkm_i2c_pad_dtor nouveau_object_destroy
int _nvkm_i2c_pad_init(struct nouveau_object *);
int _nvkm_i2c_pad_fini(struct nouveau_object *, bool);
#ifndef MSG
#define MSG(l,f,a...) do { \
struct nvkm_i2c_pad *_pad = (void *)pad; \
nv_##l(nv_object(_pad)->engine, "PAD:%c:%02x: "f, \
_pad->index >= 0x100 ? 'X' : 'S', \
_pad->index >= 0x100 ? _pad->index - 0x100 : _pad->index, ##a); \
} while(0)
#define DBG(f,a...) MSG(debug, f, ##a)
#define ERR(f,a...) MSG(error, f, ##a)
#endif
#endif
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "pad.h"
struct nouveau_oclass
nv04_i2c_pad_oclass = {
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = _nvkm_i2c_pad_ctor,
.dtor = _nvkm_i2c_pad_dtor,
.init = _nvkm_i2c_pad_init,
.fini = _nvkm_i2c_pad_fini,
},
};
/*
* Copyright 2014 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "pad.h"
struct nv94_i2c_pad {
struct nvkm_i2c_pad base;
int addr;
};
static int
nv94_i2c_pad_fini(struct nouveau_object *object, bool suspend)
{
struct nouveau_i2c *i2c = (void *)object->engine;
struct nv94_i2c_pad *pad = (void *)object;
nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000001);
return nvkm_i2c_pad_fini(&pad->base, suspend);
}
static int
nv94_i2c_pad_init(struct nouveau_object *object)
{
struct nouveau_i2c *i2c = (void *)object->engine;
struct nv94_i2c_pad *pad = (void *)object;
switch (nv_oclass(pad->base.next)->handle) {
case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX):
nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x00000002);
break;
case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT):
default:
nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x0000c001);
break;
}
nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000000);
return nvkm_i2c_pad_init(&pad->base);
}
static int
nv94_i2c_pad_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
struct nouveau_oclass *oclass, void *data, u32 index,
struct nouveau_object **pobject)
{
struct nv94_i2c_pad *pad;
int ret;
ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad);
*pobject = nv_object(pad);
if (ret)
return ret;
pad->addr = index * 0x50;;
return 0;
}
struct nouveau_oclass
nv94_i2c_pad_oclass = {
.ofuncs = &(struct nouveau_ofuncs) {
.ctor = nv94_i2c_pad_ctor,
.dtor = _nvkm_i2c_pad_dtor,
.init = nv94_i2c_pad_init,
.fini = nv94_i2c_pad_fini,
},
};
......@@ -3,6 +3,9 @@
#include <subdev/i2c.h>
extern struct nouveau_oclass nv04_i2c_pad_oclass;
extern struct nouveau_oclass nv94_i2c_pad_oclass;
#define nouveau_i2c_port_create(p,e,o,i,a,f,d) \
nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f), \
sizeof(**d), (void **)d)
......@@ -22,7 +25,7 @@ int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *,
int, void **);
void _nouveau_i2c_port_dtor(struct nouveau_object *);
#define _nouveau_i2c_port_init nouveau_object_init
#define _nouveau_i2c_port_fini nouveau_object_fini
int _nouveau_i2c_port_fini(struct nouveau_object *, bool);
#define nouveau_i2c_create(p,e,o,d) \
nouveau_i2c_create_((p), (e), (o), sizeof(**d), (void **)d)
......@@ -59,6 +62,8 @@ struct nouveau_i2c_impl {
/* supported i2c port classes */
struct nouveau_oclass *sclass;
struct nouveau_oclass *pad_x;
struct nouveau_oclass *pad_s;
/* number of native dp aux channels present */
int aux;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部