drm/nouveau/i2c: pass the function pointers in at creation time
i2c_bit_add_bus can call the pre_xfer function, which expects the func pointer to be set. Pass in func to the port creation logic so that it is set before i2c_bit_add_bus. See https://bugs.freedesktop.org/show_bug.cgi?id=68456 Reported-by: Hans-Peter Deifel <hpdeifel@gmx.de> Tested-by: Hans-Peter Deifel <hpdeifel@gmx.de> Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
c4a62a7660
commit
c865534f1e
8 changed files with 23 additions and 21 deletions
|
@ -39,8 +39,8 @@ struct nouveau_i2c_func {
|
||||||
int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe);
|
int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define nouveau_i2c_port_create(p,e,o,i,a,d) \
|
#define nouveau_i2c_port_create(p,e,o,i,a,f,d) \
|
||||||
nouveau_i2c_port_create_((p), (e), (o), (i), (a), \
|
nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f), \
|
||||||
sizeof(**d), (void **)d)
|
sizeof(**d), (void **)d)
|
||||||
#define nouveau_i2c_port_destroy(p) ({ \
|
#define nouveau_i2c_port_destroy(p) ({ \
|
||||||
struct nouveau_i2c_port *port = (p); \
|
struct nouveau_i2c_port *port = (p); \
|
||||||
|
@ -53,7 +53,9 @@ struct nouveau_i2c_func {
|
||||||
|
|
||||||
int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *,
|
int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *,
|
||||||
struct nouveau_oclass *, u8,
|
struct nouveau_oclass *, u8,
|
||||||
const struct i2c_algorithm *, int, void **);
|
const struct i2c_algorithm *,
|
||||||
|
const struct nouveau_i2c_func *,
|
||||||
|
int, void **);
|
||||||
void _nouveau_i2c_port_dtor(struct nouveau_object *);
|
void _nouveau_i2c_port_dtor(struct nouveau_object *);
|
||||||
#define _nouveau_i2c_port_init nouveau_object_init
|
#define _nouveau_i2c_port_init nouveau_object_init
|
||||||
#define _nouveau_i2c_port_fini nouveau_object_fini
|
#define _nouveau_i2c_port_fini nouveau_object_fini
|
||||||
|
|
|
@ -118,7 +118,8 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&nouveau_i2c_aux_algo, &chan);
|
&nouveau_i2c_aux_algo, &anx9805_aux_func,
|
||||||
|
&chan);
|
||||||
*pobject = nv_object(chan);
|
*pobject = nv_object(chan);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -140,8 +141,6 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent,
|
||||||
struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
|
struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
|
||||||
algo->udelay = max(algo->udelay, 40);
|
algo->udelay = max(algo->udelay, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
chan->base.func = &anx9805_aux_func;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +233,8 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&anx9805_i2c_algo, &port);
|
&anx9805_i2c_algo, &anx9805_i2c_func,
|
||||||
|
&port);
|
||||||
*pobject = nv_object(port);
|
*pobject = nv_object(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -256,8 +256,6 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent,
|
||||||
struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
|
struct i2c_algo_bit_data *algo = mast->adapter.algo_data;
|
||||||
algo->udelay = max(algo->udelay, 40);
|
algo->udelay = max(algo->udelay, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
port->base.func = &anx9805_i2c_func;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
|
||||||
struct nouveau_object *engine,
|
struct nouveau_object *engine,
|
||||||
struct nouveau_oclass *oclass, u8 index,
|
struct nouveau_oclass *oclass, u8 index,
|
||||||
const struct i2c_algorithm *algo,
|
const struct i2c_algorithm *algo,
|
||||||
|
const struct nouveau_i2c_func *func,
|
||||||
int size, void **pobject)
|
int size, void **pobject)
|
||||||
{
|
{
|
||||||
struct nouveau_device *device = nv_device(parent);
|
struct nouveau_device *device = nv_device(parent);
|
||||||
|
@ -112,6 +113,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,
|
||||||
port->adapter.owner = THIS_MODULE;
|
port->adapter.owner = THIS_MODULE;
|
||||||
port->adapter.dev.parent = &device->pdev->dev;
|
port->adapter.dev.parent = &device->pdev->dev;
|
||||||
port->index = index;
|
port->index = index;
|
||||||
|
port->func = func;
|
||||||
i2c_set_adapdata(&port->adapter, i2c);
|
i2c_set_adapdata(&port->adapter, i2c);
|
||||||
|
|
||||||
if ( algo == &nouveau_i2c_bit_algo &&
|
if ( algo == &nouveau_i2c_bit_algo &&
|
||||||
|
|
|
@ -91,12 +91,12 @@ nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&nouveau_i2c_bit_algo, &port);
|
&nouveau_i2c_bit_algo, &nv04_i2c_func,
|
||||||
|
&port);
|
||||||
*pobject = nv_object(port);
|
*pobject = nv_object(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
port->base.func = &nv04_i2c_func;
|
|
||||||
port->drive = info->drive;
|
port->drive = info->drive;
|
||||||
port->sense = info->sense;
|
port->sense = info->sense;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -84,12 +84,12 @@ nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&nouveau_i2c_bit_algo, &port);
|
&nouveau_i2c_bit_algo, &nv4e_i2c_func,
|
||||||
|
&port);
|
||||||
*pobject = nv_object(port);
|
*pobject = nv_object(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
port->base.func = &nv4e_i2c_func;
|
|
||||||
port->addr = 0x600800 + info->drive;
|
port->addr = 0x600800 + info->drive;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,8 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&nouveau_i2c_bit_algo, &port);
|
&nouveau_i2c_bit_algo, &nv50_i2c_func,
|
||||||
|
&port);
|
||||||
*pobject = nv_object(port);
|
*pobject = nv_object(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -93,7 +94,6 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
if (info->drive >= nv50_i2c_addr_nr)
|
if (info->drive >= nv50_i2c_addr_nr)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
port->base.func = &nv50_i2c_func;
|
|
||||||
port->state = 0x00000007;
|
port->state = 0x00000007;
|
||||||
port->addr = nv50_i2c_addr[info->drive];
|
port->addr = nv50_i2c_addr[info->drive];
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -186,7 +186,8 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&nouveau_i2c_bit_algo, &port);
|
&nouveau_i2c_bit_algo, &nv94_i2c_func,
|
||||||
|
&port);
|
||||||
*pobject = nv_object(port);
|
*pobject = nv_object(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -194,7 +195,6 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
if (info->drive >= nv50_i2c_addr_nr)
|
if (info->drive >= nv50_i2c_addr_nr)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
port->base.func = &nv94_i2c_func;
|
|
||||||
port->state = 7;
|
port->state = 7;
|
||||||
port->addr = nv50_i2c_addr[info->drive];
|
port->addr = nv50_i2c_addr[info->drive];
|
||||||
if (info->share != DCB_I2C_UNUSED) {
|
if (info->share != DCB_I2C_UNUSED) {
|
||||||
|
@ -221,12 +221,12 @@ nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&nouveau_i2c_aux_algo, &port);
|
&nouveau_i2c_aux_algo, &nv94_aux_func,
|
||||||
|
&port);
|
||||||
*pobject = nv_object(port);
|
*pobject = nv_object(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
port->base.func = &nv94_aux_func;
|
|
||||||
port->addr = info->drive;
|
port->addr = info->drive;
|
||||||
if (info->share != DCB_I2C_UNUSED) {
|
if (info->share != DCB_I2C_UNUSED) {
|
||||||
port->ctrl = 0x00e500 + (info->drive * 0x50);
|
port->ctrl = 0x00e500 + (info->drive * 0x50);
|
||||||
|
|
|
@ -60,12 +60,12 @@ nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
ret = nouveau_i2c_port_create(parent, engine, oclass, index,
|
||||||
&nouveau_i2c_bit_algo, &port);
|
&nouveau_i2c_bit_algo, &nvd0_i2c_func,
|
||||||
|
&port);
|
||||||
*pobject = nv_object(port);
|
*pobject = nv_object(port);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
port->base.func = &nvd0_i2c_func;
|
|
||||||
port->state = 0x00000007;
|
port->state = 0x00000007;
|
||||||
port->addr = 0x00d014 + (info->drive * 0x20);
|
port->addr = 0x00d014 + (info->drive * 0x20);
|
||||||
if (info->share != DCB_I2C_UNUSED) {
|
if (info->share != DCB_I2C_UNUSED) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue