예제 #1
0
static struct nouveau_i2c_port *
init_i2c(struct nvbios_init *init, int index)
{
	struct nouveau_i2c *i2c = nouveau_i2c(init->bios);

	if (index == 0xff) {
		index = NV_I2C_DEFAULT(0);
		if (init->outp && init->outp->i2c_upper_default)
			index = NV_I2C_DEFAULT(1);
	} else
	if (index < 0) {
		if (!init->outp) {
			if (init_exec(init))
				error("script needs output for i2c\n");
			return NULL;
		}

		if (index == -2 && init->outp->location) {
			index = NV_I2C_TYPE_EXTAUX(init->outp->extdev);
			return i2c->find_type(i2c, index);
		}

		index = init->outp->i2c_index;
	}

	return i2c->find(i2c, index);
}
예제 #2
0
static void
nouveau_i2c_post_xfer(struct i2c_adapter *adap)
{
	struct i2c_algo_bit_data *bit = adap->algo_data;
	struct nouveau_i2c_port *port = bit->data;
	return nouveau_i2c(port)->release(port);
}
예제 #3
0
static int
nouveau_i2c_pre_xfer(struct i2c_adapter *adap)
{
	struct i2c_algo_bit_data *bit = adap->algo_data;
	struct nouveau_i2c_port *port = bit->data;
	return nouveau_i2c(port)->acquire(port, bit->timeout);
}
예제 #4
0
파일: tvnv04.c 프로젝트: 03199618/linux
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",
			     nv04_tv_encoder_info, NULL);
}
예제 #5
0
void
nouveau_therm_ic_ctor(struct nouveau_therm *therm)
{
	struct nouveau_therm_priv *priv = (void *)therm;
	struct nouveau_bios *bios = nouveau_bios(therm);
	struct nouveau_i2c *i2c = nouveau_i2c(therm);
	struct nvbios_extdev_func extdev_entry;

	if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) {
		struct nouveau_i2c_board_info board[] = {
		  { { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, 0},
		  { }
		};
예제 #6
0
int
nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
{
	struct nouveau_encoder *nv_encoder;
	struct drm_encoder *encoder;
	struct drm_device *dev = connector->dev;
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
	struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index);
	int type, ret;

	/* Ensure that we can talk to this encoder */
	type = nv04_tv_identify(dev, entry->i2c_index);
	if (type < 0)
		return type;

	/* Allocate the necessary memory */
	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
	if (!nv_encoder)
		return -ENOMEM;

	/* Initialize the common members */
	encoder = to_drm_encoder(nv_encoder);

	drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
	drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs);

	encoder->possible_crtcs = entry->heads;
	encoder->possible_clones = 0;
	nv_encoder->dcb = entry;
	nv_encoder->or = ffs(entry->or) - 1;

	/* Run the slave-specific initialization */
	ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
				   &port->adapter,
				   &nv04_tv_encoder_info[type].dev);
	if (ret < 0)
		goto fail_cleanup;

	/* Attach it to the specified connector. */
	get_slave_funcs(encoder)->create_resources(encoder, connector);
	drm_mode_connector_attach_encoder(connector, encoder);

	return 0;

fail_cleanup:
	drm_encoder_cleanup(encoder);
	kfree(nv_encoder);
	return ret;
}
예제 #7
0
파일: nv94.c 프로젝트: 383530895/linux
int
nv94_aux(struct nouveau_i2c_port *base, bool retry,
	 u8 type, u32 addr, u8 *data, u8 size)
{
	struct nouveau_i2c *aux = nouveau_i2c(base);
	struct nv50_i2c_port *port = (void *)base;
	u32 ctrl, stat, timeout, retries;
	u32 xbuf[4] = {};
	int ch = port->addr;
	int ret, i;

	AUX_DBG("%d: 0x%08x %d\n", type, addr, size);

	ret = auxch_init(aux, ch);
	if (ret)
		goto out;

	stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50));
	if (!(stat & 0x10000000)) {
		AUX_DBG("sink not detected\n");
		ret = -ENXIO;
		goto out;
	}

	if (!(type & 1)) {
		memcpy(xbuf, data, size);
		for (i = 0; i < 16; i += 4) {
			AUX_DBG("wr 0x%08x\n", xbuf[i / 4]);
			nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]);
		}
	}

	ctrl  = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
	ctrl &= ~0x0001f0ff;
	ctrl |= type << 12;
	ctrl |= size - 1;
	nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr);

	/* (maybe) retry transaction a number of times on failure... */
	for (retries = 0; !ret && retries < 32; retries++) {
		/* reset, and delay a while if this is a retry */
		nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);
		nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl);
		if (retries)
			udelay(400);

		/* transaction request, wait up to 1ms for it to complete */
		nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl);

		timeout = 1000;
		do {
			ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50));
			udelay(1);
			if (!timeout--) {
				AUX_ERR("tx req timeout 0x%08x\n", ctrl);
				ret = -EIO;
				goto out;
			}
		} while (ctrl & 0x00010000);
		ret = 1;

		/* read status, and check if transaction completed ok */
		stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0);
		if ((stat & 0x000f0000) == 0x00080000 ||
		    (stat & 0x000f0000) == 0x00020000)
			ret = retry ? 0 : 1;
		if ((stat & 0x00000100))
			ret = -ETIMEDOUT;
		if ((stat & 0x00000e00))
			ret = -EIO;

		AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);
	}

	if (type & 1) {
		for (i = 0; i < 16; i += 4) {
			xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i);
			AUX_DBG("rd 0x%08x\n", xbuf[i / 4]);
		}
		memcpy(data, xbuf, size);
	}

out:
	auxch_fini(aux, ch);
	return ret < 0 ? ret : (stat & 0x000f0000) >> 16;
}