Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e2b734f authored by Martin Peres's avatar Martin Peres Committed by Ben Skeggs
Browse files

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: default avatarMartin Peres <martin.peres@labri.fr>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent fd34381b
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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;
+22 −5
Original line number Diff line number Diff line
@@ -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");
+27 −27
Original line number Diff line number Diff line
@@ -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,8 +89,8 @@ 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},
		  { }
		};

@@ -101,8 +101,8 @@ 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 },
		  { }
		};

+9 −7
Original line number Diff line number Diff line
@@ -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
		         }
		    }, 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 = {
+13 −9
Original line number Diff line number Diff line
@@ -37,7 +37,8 @@

#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) {
@@ -47,6 +48,8 @@ static struct i2c_board_info nv04_tv_encoder_info[] = {
				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;