diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 888384c..95310c2 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -64,7 +64,7 @@ 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 (*identify)(struct nouveau_i2c *, int index, - const char *what, struct i2c_board_info *, + const char *what, int udelay, struct i2c_board_info *, bool (*match)(struct nouveau_i2c_port *, struct i2c_board_info *)); struct list_head ports; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 8ae2625..5fbddbb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -193,11 +193,12 @@ nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type) static int nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, - struct i2c_board_info *info, + int udelay, struct i2c_board_info *info, bool (*match)(struct nouveau_i2c_port *, struct i2c_board_info *)) { struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index); + int orig_udelay; int i; if (!port) { @@ -205,6 +206,13 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, return -ENODEV; } + if ((port->adapter.algo == &i2c_bit_algo) && (udelay != 0)) { +// nv_debug(i2c, "using custom udelay %d\n", what, port->index); + struct i2c_algo_bit_data *algo = port->adapter.algo_data; + orig_udelay = algo->udelay; + algo->udelay = udelay; + } + nv_debug(i2c, "probing %ss on bus: %d\n", what, port->index); for (i = 0; info[i].addr; i++) { if (nv_probe_i2c(port, info[i].addr) && @@ -214,6 +222,11 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, } } + if ((port->adapter.algo == &i2c_bit_algo) && (udelay != 0)) { + struct i2c_algo_bit_data *algo = port->adapter.algo_data; + algo->udelay = orig_udelay; + } + nv_debug(i2c, "no devices found.\n"); return -ENODEV; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index 8b3adec..58a3ae1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c @@ -94,7 +94,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) { } }; - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", + i2c->identify(i2c, NV_I2C_DEFAULT(0), 0, "monitoring device", board, probe_monitoring_device); if (priv->ic) return; @@ -106,7 +106,7 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) { } }; - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", + i2c->identify(i2c, NV_I2C_DEFAULT(0), 20, "monitoring device", board, probe_monitoring_device); if (priv->ic) return; @@ -115,6 +115,6 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) /* The vbios doesn't provide the address of an exisiting monitoring device. Let's try our static list. */ - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", + i2c->identify(i2c, NV_I2C_DEFAULT(0), 0, "monitoring device", nv_board_infos, probe_monitoring_device); } diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 93dd23ff..38161f0 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -641,7 +641,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) get_tmds_slave(encoder)) return; - type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL); + type = i2c->identify(i2c, 2, 0, "TMDS transmitter", info, NULL); if (type < 0) return; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index bf13db4..3c97268 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -55,7 +55,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_i2c *i2c = nouveau_i2c(drm->device); - return i2c->identify(i2c, i2c_index, "TV encoder", + return i2c->identify(i2c, i2c_index, 0, "TV encoder", nv04_tv_encoder_info, NULL); }