Commit 486a45c2 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/i2c: do parsing of i2c-related vbios info in nouveau_i2c.c



Not much point parsing the vbios data into a struct which is only used once
to parse the data into another struct, go directly from vbios to
nouveau_i2c_chan.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 6b5a81a2
Loading
Loading
Loading
Loading
+10 −156
Original line number Diff line number Diff line
@@ -720,116 +720,20 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
	return dcb_entry;
}

static int
read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c)
{
	uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4;
	int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES;
	int recordoffset = 0, rdofs = 1, wrofs = 0;
	uint8_t port_type = 0;

	if (!i2ctable)
		return -EINVAL;

	if (dcb_version >= 0x30) {
		if (i2ctable[0] != dcb_version) /* necessary? */
			NV_WARN(dev,
				"DCB I2C table version mismatch (%02X vs %02X)\n",
				i2ctable[0], dcb_version);
		dcb_i2c_ver = i2ctable[0];
		headerlen = i2ctable[1];
		if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES)
			i2c_entries = i2ctable[2];
		else
			NV_WARN(dev,
				"DCB I2C table has more entries than indexable "
				"(%d entries, max %d)\n", i2ctable[2],
				DCB_MAX_NUM_I2C_ENTRIES);
		entry_len = i2ctable[3];
		/* [4] is i2c_default_indices, read in parse_dcb_table() */
	}
	/*
	 * It's your own fault if you call this function on a DCB 1.1 BIOS --
	 * the test below is for DCB 1.2
	 */
	if (dcb_version < 0x14) {
		recordoffset = 2;
		rdofs = 0;
		wrofs = 1;
	}

	if (index == 0xf)
		return 0;
	if (index >= i2c_entries) {
		NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n",
			 index, i2ctable[2]);
		return -ENOENT;
	}
	if (i2ctable[headerlen + entry_len * index + 3] == 0xff) {
		NV_ERROR(dev, "DCB I2C entry invalid\n");
		return -EINVAL;
	}

	if (dcb_i2c_ver >= 0x30) {
		port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index];

		/*
		 * Fixup for chips using same address offset for read and
		 * write.
		 */
		if (port_type == 4)	/* seen on C51 */
			rdofs = wrofs = 1;
		if (port_type >= 5)	/* G80+ */
			rdofs = wrofs = 0;
	}

	if (dcb_i2c_ver >= 0x40) {
		if (port_type != 5 && port_type != 6)
			NV_WARN(dev, "DCB I2C table has port type %d\n", port_type);

		i2c->entry = ROM32(i2ctable[headerlen + recordoffset + entry_len * index]);
	}

	i2c->port_type = port_type;
	i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index];
	i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index];

	return 0;
}

static struct nouveau_i2c_chan *
init_i2c_device_find(struct drm_device *dev, int i2c_index)
{
	if (i2c_index == 0xff) {
		struct drm_nouveau_private *dev_priv = dev->dev_private;
		struct dcb_table *dcb = &dev_priv->vbios.dcb;

	if (i2c_index == 0xff) {
		/* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
		int idx = dcb_entry_idx_from_crtchead(dev), shift = 0;
		int default_indices = dcb->i2c_default_indices;
		int idx = dcb_entry_idx_from_crtchead(dev);

		i2c_index = NV_I2C_DEFAULT(0);
		if (idx != 0x7f && dcb->entry[idx].i2c_upper_default)
			shift = 4;

		i2c_index = (default_indices >> shift) & 0xf;
	}
	if (i2c_index == 0x80)	/* g80+ */
		i2c_index = dcb->i2c_default_indices & 0xf;
	else
	if (i2c_index == 0x81)
		i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4;

	if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) {
		NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index);
		return NULL;
			i2c_index = NV_I2C_DEFAULT(1);
	}

	/* Make sure i2c table entry has been parsed, it may not
	 * have been if this is a bus not referenced by a DCB encoder
	 */
	read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
			   i2c_index, &dcb->i2c[i2c_index]);

	return nouveau_i2c_find(dev, i2c_index);
}

@@ -5595,10 +5499,6 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
	uint16_t legacy_scripts_offset, legacy_i2c_offset;

	/* load needed defaults in case we can't parse this info */
	bios->dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
	bios->dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
	bios->dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
	bios->dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
	bios->digital_min_front_porch = 0x4b;
	bios->fmaxvco = 256000;
	bios->fminvco = 128000;
@@ -5706,14 +5606,6 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
	bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset];
	bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
	bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
	if (bios->data[legacy_i2c_offset + 4])
		bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
	if (bios->data[legacy_i2c_offset + 5])
		bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
	if (bios->data[legacy_i2c_offset + 6])
		bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
	if (bios->data[legacy_i2c_offset + 7])
		bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];

	if (bmplength > 74) {
		bios->fmaxvco = ROM32(bmp[67]);
@@ -6549,10 +6441,6 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp)
			ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
		if (!ret)
			return 1; /* stop parsing */

		read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
				   entry->i2c_index,
				   &dcb->i2c[entry->i2c_index]);
	}

	return 0;
@@ -6562,7 +6450,6 @@ static int
parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
{
	struct dcb_table *dcb = &bios->dcb;
	u16 i2ctabptr = 0x0000;
	u8 *dcbt;

	dcbt = dcb_table(dev);
@@ -6580,32 +6467,8 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios)

	dcb->version = dcbt[0];
	if (dcb->version >= 0x30) {
		i2ctabptr = ROM16(dcbt[4]);
		dcb->gpio_table_ptr = ROM16(dcbt[10]);
		dcb->connector_table_ptr = ROM16(dcbt[20]);
	} else
	if (dcb->version >= 0x15) {
		i2ctabptr = ROM16(dcbt[2]);
	}

	if (!i2ctabptr)
		NV_WARN(dev, "No pointer to DCB I2C port table\n");
	else {
		dcb->i2c_table = &bios->data[i2ctabptr];
		if (dcb->version >= 0x30)
			dcb->i2c_default_indices = dcb->i2c_table[4];

		/*
		 * Parse the "management" I2C bus, used for hardware
		 * monitoring and some external TMDS transmitters.
		 */
		if (dcb->version >= 0x22) {
			int idx = (dcb->version >= 0x40 ?
				   dcb->i2c_default_indices & 0xf : 2);

			read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
					   idx, &dcb->i2c[idx]);
		}
	}

	dcb_outp_foreach(dev, NULL, parse_dcb_entry);
@@ -6893,19 +6756,6 @@ nouveau_run_vbios_init(struct drm_device *dev)
	return ret;
}

static void
nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nvbios *bios = &dev_priv->vbios;
	struct dcb_i2c_entry *entry;
	int i;

	entry = &bios->dcb.i2c[0];
	for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++)
		nouveau_i2c_fini(dev, entry);
}

static bool
nouveau_bios_posted(struct drm_device *dev)
{
@@ -6942,6 +6792,10 @@ nouveau_bios_init(struct drm_device *dev)
	if (ret)
		return ret;

	ret = nouveau_i2c_init(dev);
	if (ret)
		return ret;

	ret = parse_dcb_table(dev, bios);
	if (ret)
		return ret;
@@ -6984,5 +6838,5 @@ nouveau_bios_init(struct drm_device *dev)
void
nouveau_bios_takedown(struct drm_device *dev)
{
	nouveau_bios_i2c_devices_takedown(dev);
	nouveau_i2c_fini(dev);
}
+0 −11
Original line number Diff line number Diff line
@@ -53,13 +53,6 @@ struct bit_entry {

int bit_table(struct drm_device *, u8 id, struct bit_entry *);

struct dcb_i2c_entry {
	uint32_t entry;
	uint8_t port_type;
	uint8_t read, write;
	struct nouveau_i2c_chan *chan;
};

enum dcb_gpio_tag {
	DCB_GPIO_TVDAC0 = 0xc,
	DCB_GPIO_TVDAC1 = 0x2d,
@@ -166,10 +159,6 @@ struct dcb_table {
	int entries;
	struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];

	uint8_t *i2c_table;
	uint8_t i2c_default_indices;
	struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];

	uint16_t gpio_table_ptr;
	struct dcb_gpio_table gpio;
	uint16_t connector_table_ptr;
+1 −0
Original line number Diff line number Diff line
@@ -793,6 +793,7 @@ struct drm_nouveau_private {
	struct nouveau_vm *chan_vm;

	struct nvbios vbios;
	struct list_head i2c_ports;

	struct nv04_mode_state mode_reg;
	struct nv04_mode_state saved_reg;
+200 −102
Original line number Diff line number Diff line
@@ -109,13 +109,6 @@ nv4e_i2c_getsda(void *data)
	return !!((nv_rd32(dev, i2c->rd) >> 16) & 8);
}

static const uint32_t nv50_i2c_port[] = {
	0x00e138, 0x00e150, 0x00e168, 0x00e180,
	0x00e254, 0x00e274, 0x00e764, 0x00e780,
	0x00e79c, 0x00e7b8
};
#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port)

static int
nv50_i2c_getscl(void *data)
{
@@ -125,7 +118,6 @@ nv50_i2c_getscl(void *data)
	return !!(nv_rd32(dev, i2c->rd) & 1);
}


static int
nv50_i2c_getsda(void *data)
{
@@ -166,125 +158,233 @@ nvd0_i2c_getsda(void *data)
	return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20);
}

static const uint32_t nv50_i2c_port[] = {
	0x00e138, 0x00e150, 0x00e168, 0x00e180,
	0x00e254, 0x00e274, 0x00e764, 0x00e780,
	0x00e79c, 0x00e7b8
};

static u8 *
i2c_table(struct drm_device *dev, u8 *version)
{
	u8 *dcb = dcb_table(dev), *i2c = NULL;
	if (dcb) {
		if (dcb[0] >= 0x15)
			i2c = ROMPTR(dev, dcb[2]);
		if (dcb[0] >= 0x30)
			i2c = ROMPTR(dev, dcb[4]);
	}

	/* early revisions had no version number, use dcb version */
	if (i2c) {
		*version = dcb[0];
		if (*version >= 0x30)
			*version = i2c[0];
	}

	return i2c;
}

int
nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index)
nouveau_i2c_init(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_i2c_chan *i2c;
	int ret;
	struct nvbios *bios = &dev_priv->vbios;
	struct nouveau_i2c_chan *port;
	u8 *i2c, *entry, legacy[2][4] = {};
	u8 version, entries, recordlen;
	int ret, i;

	INIT_LIST_HEAD(&dev_priv->i2c_ports);

	i2c = i2c_table(dev, &version);
	if (!i2c) {
		u8 *bmp = &bios->data[bios->offset];
		if (bios->type != NVBIOS_BMP)
			return -ENODEV;

	if (entry->chan)
		return -EEXIST;
		legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX;
		legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX;
		legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX;
		legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX;

		/* BMP (from v4.0) has i2c info in the structure, it's in a
		 * fixed location on earlier VBIOS
		 */
		if (bmp[5] < 4)
			i2c = &bios->data[0x48];
		else
			i2c = &bmp[0x36];

		if (i2c[4]) legacy[0][0] = i2c[4];
		if (i2c[5]) legacy[0][1] = i2c[5];
		if (i2c[6]) legacy[1][0] = i2c[6];
		if (i2c[7]) legacy[1][1] = i2c[7];
	}

	if (dev_priv->card_type >= NV_50 &&
	    dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) {
		NV_ERROR(dev, "unknown i2c port %d\n", entry->read);
		return -EINVAL;
	if (i2c && version >= 0x30) {
		entry     = i2c[1] + i2c;
		entries   = i2c[2];
		recordlen = i2c[3];
	} else
	if (i2c) {
		entry     = i2c;
		entries   = 16;
		recordlen = 4;
	} else {
		entry     = legacy[0];
		entries   = 2;
		recordlen = 4;
	}

	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
	if (i2c == NULL)
	for (i = 0; i < entries; i++, entry += recordlen) {
		port = kzalloc(sizeof(*port), GFP_KERNEL);
		if (port == NULL) {
			nouveau_i2c_fini(dev);
			return -ENOMEM;
		}

		port->type = entry[3];
		if (version < 0x30) {
			port->type &= 0x07;
			if (port->type == 0x07)
				port->type = 0xff;
		}

		if (port->type == 0xff) {
			kfree(port);
			continue;
		}

	switch (entry->port_type) {
	case 0:
		i2c->bit.setsda = nv04_i2c_setsda;
		i2c->bit.setscl = nv04_i2c_setscl;
		i2c->bit.getsda = nv04_i2c_getsda;
		i2c->bit.getscl = nv04_i2c_getscl;
		i2c->rd = entry->read;
		i2c->wr = entry->write;
		switch (port->type) {
		case 0: /* NV04:NV50 */
			port->wr = entry[0];
			port->rd = entry[1];
			port->bit.setsda = nv04_i2c_setsda;
			port->bit.setscl = nv04_i2c_setscl;
			port->bit.getsda = nv04_i2c_getsda;
			port->bit.getscl = nv04_i2c_getscl;
			break;
	case 4:
		i2c->bit.setsda = nv4e_i2c_setsda;
		i2c->bit.setscl = nv4e_i2c_setscl;
		i2c->bit.getsda = nv4e_i2c_getsda;
		i2c->bit.getscl = nv4e_i2c_getscl;
		i2c->rd = 0x600800 + entry->read;
		i2c->wr = 0x600800 + entry->write;
		case 4: /* NV4E */
			port->wr = 0x600800 + entry[1];
			port->rd = port->wr;
			port->bit.setsda = nv4e_i2c_setsda;
			port->bit.setscl = nv4e_i2c_setscl;
			port->bit.getsda = nv4e_i2c_getsda;
			port->bit.getscl = nv4e_i2c_getscl;
			break;
	case 5:
		i2c->bit.setsda = nv50_i2c_setsda;
		i2c->bit.setscl = nv50_i2c_setscl;
		case 5: /* NV50- */
			port->wr = entry[0] & 0x0f;
			if (dev_priv->card_type < NV_D0) {
			i2c->bit.getsda = nv50_i2c_getsda;
			i2c->bit.getscl = nv50_i2c_getscl;
			i2c->rd = nv50_i2c_port[entry->read];
			i2c->wr = i2c->rd;
				if (port->wr >= ARRAY_SIZE(nv50_i2c_port))
					break;
				port->wr = nv50_i2c_port[port->wr];
				port->rd = port->wr;
				port->bit.getsda = nv50_i2c_getsda;
				port->bit.getscl = nv50_i2c_getscl;
			} else {
			i2c->bit.getsda = nvd0_i2c_getsda;
			i2c->bit.getscl = nvd0_i2c_getscl;
			i2c->rd = 0x00d014 + (entry->read * 0x20);
			i2c->wr = i2c->rd;
				port->wr = 0x00d014 + (port->wr * 0x20);
				port->rd = port->wr;
				port->bit.getsda = nvd0_i2c_getsda;
				port->bit.getscl = nvd0_i2c_getscl;
			}
			port->bit.setsda = nv50_i2c_setsda;
			port->bit.setscl = nv50_i2c_setscl;
			break;
	case 6:
		i2c->rd = entry->read;
		i2c->wr = entry->write;
		case 6: /* NV50- DP AUX */
			port->wr = entry[0];
			port->rd = port->wr;
			port->adapter.algo = &nouveau_dp_i2c_algo;
			break;
		default:
		NV_ERROR(dev, "DCB I2C port type %d unknown\n",
			 entry->port_type);
		kfree(i2c);
		return -EINVAL;
	}

	snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
		 "nouveau-%s-%d", pci_name(dev->pdev), index);
	i2c->adapter.owner = THIS_MODULE;
	i2c->adapter.dev.parent = &dev->pdev->dev;
	i2c->dev = dev;
	i2c_set_adapdata(&i2c->adapter, i2c);

	if (entry->port_type < 6) {
		i2c->adapter.algo_data = &i2c->bit;
		i2c->bit.udelay = 40;
		i2c->bit.timeout = usecs_to_jiffies(5000);
		i2c->bit.data = i2c;
		ret = i2c_bit_add_bus(&i2c->adapter);
			break;
		}

		if (!port->adapter.algo && !port->wr) {
			NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n",
				 i, port->type, port->wr, port->rd);
			kfree(port);
			continue;
		}

		snprintf(port->adapter.name, sizeof(port->adapter.name),
			 "nouveau-%s-%d", pci_name(dev->pdev), i);
		port->adapter.owner = THIS_MODULE;
		port->adapter.dev.parent = &dev->pdev->dev;
		port->dev = dev;
		port->index = i;
		port->dcb = ROM32(entry[0]);
		i2c_set_adapdata(&port->adapter, i2c);

		if (port->adapter.algo != &nouveau_dp_i2c_algo) {
			port->adapter.algo_data = &port->bit;
			port->bit.udelay = 40;
			port->bit.timeout = usecs_to_jiffies(5000);
			port->bit.data = port;
			ret = i2c_bit_add_bus(&port->adapter);
		} else {
		i2c->adapter.algo = &nouveau_dp_i2c_algo;
		ret = i2c_add_adapter(&i2c->adapter);
			port->adapter.algo = &nouveau_dp_i2c_algo;
			ret = i2c_add_adapter(&port->adapter);
		}

		if (ret) {
		NV_ERROR(dev, "Failed to register i2c %d\n", index);
		kfree(i2c);
		return ret;
			NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret);
			kfree(port);
			continue;
		}

		list_add_tail(&port->head, &dev_priv->i2c_ports);
	}

	entry->chan = i2c;
	return 0;
}

void
nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry)
nouveau_i2c_fini(struct drm_device *dev)
{
	if (!entry->chan)
		return;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_i2c_chan *port, *tmp;

	i2c_del_adapter(&entry->chan->adapter);
	kfree(entry->chan);
	entry->chan = NULL;
	list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) {
		i2c_del_adapter(&port->adapter);
		kfree(port);
	}
}

struct nouveau_i2c_chan *
nouveau_i2c_find(struct drm_device *dev, int index)
nouveau_i2c_find(struct drm_device *dev, u8 index)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index];
	struct nouveau_i2c_chan *port;

	if (index == NV_I2C_DEFAULT(0) ||
	    index == NV_I2C_DEFAULT(1)) {
		u8 version, *i2c = i2c_table(dev, &version);
		if (i2c && version >= 0x30) {
			if (index == NV_I2C_DEFAULT(0))
				index = (i2c[4] & 0x0f);
			else
				index = (i2c[4] & 0xf0) >> 4;
		} else {
			index = 2;
		}
	}

	if (index >= DCB_MAX_NUM_I2C_ENTRIES)
		return NULL;
	list_for_each_entry(port, &dev_priv->i2c_ports, head) {
		if (port->index == index)
			break;
	}

	if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) {
		uint32_t reg = 0xe500, val;
	if (&port->head == &dev_priv->i2c_ports)
		return NULL;

		if (i2c->port_type == 6) {
			reg += i2c->read * 0x50;
	if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) {
		u32 reg = 0x00e500, val;
		if (port->type == 6) {
			reg += port->rd * 0x50;
			val  = 0x2002;
		} else {
			reg += ((i2c->entry & 0x1e00) >> 9) * 0x50;
			reg += ((port->dcb & 0x1e00) >> 9) * 0x50;
			val  = 0xe001;
		}

@@ -294,9 +394,7 @@ nouveau_i2c_find(struct drm_device *dev, int index)
		nv_mask(dev, reg + 0x00, 0x0000f003, val);
	}

	if (!i2c->chan && nouveau_i2c_init(dev, i2c, index))
		return NULL;
	return i2c->chan;
	return port;
}

bool
+10 −4
Original line number Diff line number Diff line
@@ -27,20 +27,26 @@
#include <linux/i2c-algo-bit.h>
#include "drm_dp_helper.h"

struct dcb_i2c_entry;
#define NV_I2C_PORT(n)    (0x00 + (n))
#define NV_I2C_PORT_NUM    0x10
#define NV_I2C_DEFAULT(n) (0x80 + (n))

struct nouveau_i2c_chan {
	struct i2c_adapter adapter;
	struct drm_device *dev;
	struct i2c_algo_bit_data bit;
	struct list_head head;
	u8  index;
	u8  type;
	u32 dcb;
	unsigned rd;
	unsigned wr;
	unsigned data;
};

int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
int  nouveau_i2c_init(struct drm_device *);
void nouveau_i2c_fini(struct drm_device *);
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index);
bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
int nouveau_i2c_identify(struct drm_device *dev, const char *what,
			 struct i2c_board_info *info,
Loading