drm/nouveau/i2c: use a custom bitbanging delay for the adt7473
This patch adds a way to define a custom delay when scanning for i2c devices because the adt7473 sometimes doesn't like the default bitbanging udelay. Signed-off-by: Martin Peres <martin.peres@labri.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
fd34381b0e
commit
9e2b734f1c
|
@ -60,13 +60,18 @@ void _nouveau_i2c_port_dtor(struct nouveau_object *);
|
|||
#define _nouveau_i2c_port_init nouveau_object_init
|
||||
#define _nouveau_i2c_port_fini nouveau_object_fini
|
||||
|
||||
struct nouveau_i2c_board_info {
|
||||
struct i2c_board_info dev;
|
||||
u8 udelay; /* set to 0 to use the standard delay */
|
||||
};
|
||||
|
||||
struct nouveau_i2c {
|
||||
struct nouveau_subdev base;
|
||||
|
||||
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, struct nouveau_i2c_board_info *,
|
||||
bool (*match)(struct nouveau_i2c_port *,
|
||||
struct i2c_board_info *));
|
||||
struct list_head ports;
|
||||
|
|
|
@ -195,7 +195,7 @@ 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,
|
||||
struct nouveau_i2c_board_info *info,
|
||||
bool (*match)(struct nouveau_i2c_port *,
|
||||
struct i2c_board_info *))
|
||||
{
|
||||
|
@ -208,12 +208,29 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,
|
|||
}
|
||||
|
||||
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) &&
|
||||
(!match || match(port, &info[i]))) {
|
||||
nv_info(i2c, "detected %s: %s\n", what, info[i].type);
|
||||
for (i = 0; info[i].dev.addr; i++) {
|
||||
u8 orig_udelay = 0;
|
||||
|
||||
if ((port->adapter.algo == &i2c_bit_algo) &&
|
||||
(info[i].udelay != 0)) {
|
||||
struct i2c_algo_bit_data *algo = port->adapter.algo_data;
|
||||
nv_debug(i2c, "using custom udelay %d instead of %d\n",
|
||||
info[i].udelay, algo->udelay);
|
||||
orig_udelay = algo->udelay;
|
||||
algo->udelay = info[i].udelay;
|
||||
}
|
||||
|
||||
if (nv_probe_i2c(port, info[i].dev.addr) &&
|
||||
(!match || match(port, &info[i].dev))) {
|
||||
nv_info(i2c, "detected %s: %s\n", what,
|
||||
info[i].dev.type);
|
||||
return i;
|
||||
}
|
||||
|
||||
if (orig_udelay) {
|
||||
struct i2c_algo_bit_data *algo = port->adapter.algo_data;
|
||||
algo->udelay = orig_udelay;
|
||||
}
|
||||
}
|
||||
|
||||
nv_debug(i2c, "no devices found.\n");
|
||||
|
|
|
@ -55,28 +55,28 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
|
|||
return true;
|
||||
}
|
||||
|
||||
static struct i2c_board_info
|
||||
static struct nouveau_i2c_board_info
|
||||
nv_board_infos[] = {
|
||||
{ I2C_BOARD_INFO("w83l785ts", 0x2d) },
|
||||
{ I2C_BOARD_INFO("w83781d", 0x2d) },
|
||||
{ I2C_BOARD_INFO("adt7473", 0x2e) },
|
||||
{ I2C_BOARD_INFO("adt7473", 0x2d) },
|
||||
{ I2C_BOARD_INFO("adt7473", 0x2c) },
|
||||
{ I2C_BOARD_INFO("f75375", 0x2e) },
|
||||
{ I2C_BOARD_INFO("lm99", 0x4c) },
|
||||
{ I2C_BOARD_INFO("lm90", 0x4c) },
|
||||
{ I2C_BOARD_INFO("lm90", 0x4d) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x18) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x19) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x1a) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x29) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x2a) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x2b) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x4c) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x4d) },
|
||||
{ I2C_BOARD_INFO("adm1021", 0x4e) },
|
||||
{ I2C_BOARD_INFO("lm63", 0x18) },
|
||||
{ I2C_BOARD_INFO("lm63", 0x4e) },
|
||||
{ { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 0 },
|
||||
{ { I2C_BOARD_INFO("w83781d", 0x2d) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adt7473", 0x2e) }, 20 },
|
||||
{ { I2C_BOARD_INFO("adt7473", 0x2d) }, 20 },
|
||||
{ { I2C_BOARD_INFO("adt7473", 0x2c) }, 20 },
|
||||
{ { I2C_BOARD_INFO("f75375", 0x2e) }, 0 },
|
||||
{ { I2C_BOARD_INFO("lm99", 0x4c) }, 0 },
|
||||
{ { I2C_BOARD_INFO("lm90", 0x4c) }, 0 },
|
||||
{ { I2C_BOARD_INFO("lm90", 0x4d) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x18) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x19) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x1a) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x29) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x2a) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x2b) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x4c) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x4d) }, 0 },
|
||||
{ { I2C_BOARD_INFO("adm1021", 0x4e) }, 0 },
|
||||
{ { I2C_BOARD_INFO("lm63", 0x18) }, 0 },
|
||||
{ { I2C_BOARD_INFO("lm63", 0x4e) }, 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -89,9 +89,9 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
|
|||
struct nvbios_extdev_func extdev_entry;
|
||||
|
||||
if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) {
|
||||
struct i2c_board_info board[] = {
|
||||
{ I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) },
|
||||
{ }
|
||||
struct nouveau_i2c_board_info board[] = {
|
||||
{ { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, 0},
|
||||
{ }
|
||||
};
|
||||
|
||||
i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
|
||||
|
@ -101,9 +101,9 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)
|
|||
}
|
||||
|
||||
if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) {
|
||||
struct i2c_board_info board[] = {
|
||||
{ I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) },
|
||||
{ }
|
||||
struct nouveau_i2c_board_info board[] = {
|
||||
{ { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, 20 },
|
||||
{ }
|
||||
};
|
||||
|
||||
i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device",
|
||||
|
|
|
@ -625,13 +625,15 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
|
|||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
|
||||
struct nouveau_i2c_port *port = i2c->find(i2c, 2);
|
||||
struct i2c_board_info info[] = {
|
||||
struct nouveau_i2c_board_info info[] = {
|
||||
{
|
||||
.type = "sil164",
|
||||
.addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38),
|
||||
.platform_data = &(struct sil164_encoder_params) {
|
||||
SIL164_INPUT_EDGE_RISING
|
||||
}
|
||||
{
|
||||
.type = "sil164",
|
||||
.addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38),
|
||||
.platform_data = &(struct sil164_encoder_params) {
|
||||
SIL164_INPUT_EDGE_RISING
|
||||
}
|
||||
}, 0
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
@ -646,7 +648,7 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)
|
|||
return;
|
||||
|
||||
drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
|
||||
&port->adapter, &info[type]);
|
||||
&port->adapter, &info[type].dev);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = {
|
||||
|
|
|
@ -37,15 +37,18 @@
|
|||
|
||||
#include <subdev/i2c.h>
|
||||
|
||||
static struct i2c_board_info nv04_tv_encoder_info[] = {
|
||||
static struct nouveau_i2c_board_info nv04_tv_encoder_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("ch7006", 0x75),
|
||||
.platform_data = &(struct ch7006_encoder_params) {
|
||||
CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
|
||||
0, 0, 0,
|
||||
CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
|
||||
CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
|
||||
}
|
||||
{
|
||||
I2C_BOARD_INFO("ch7006", 0x75),
|
||||
.platform_data = &(struct ch7006_encoder_params) {
|
||||
CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
|
||||
0, 0, 0,
|
||||
CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
|
||||
CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
|
||||
}
|
||||
},
|
||||
0
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
@ -229,7 +232,8 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
|
|||
|
||||
/* Run the slave-specific initialization */
|
||||
ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
|
||||
&port->adapter, &nv04_tv_encoder_info[type]);
|
||||
&port->adapter,
|
||||
&nv04_tv_encoder_info[type].dev);
|
||||
if (ret < 0)
|
||||
goto fail_cleanup;
|
||||
|
||||
|
|
Loading…
Reference in New Issue