예제 #1
0
파일: hwsq.c 프로젝트: 19Dan01/linux
int
nvkm_hwsq_fini(struct nvkm_hwsq **phwsq, bool exec)
{
	struct nvkm_hwsq *hwsq = *phwsq;
	int ret = 0, i;
	if (hwsq) {
		struct nvkm_bus *pbus = hwsq->pbus;
		hwsq->c.size = (hwsq->c.size + 4) / 4;
		if (hwsq->c.size <= pbus->hwsq_size) {
			if (exec)
				ret = pbus->hwsq_exec(pbus, (u32 *)hwsq->c.data,
						      hwsq->c.size);
			if (ret)
				nv_error(pbus, "hwsq exec failed: %d\n", ret);
		} else {
			nv_error(pbus, "hwsq ucode too large\n");
			ret = -ENOSPC;
		}

		for (i = 0; ret && i < hwsq->c.size; i++)
			nv_error(pbus, "\t0x%08x\n", ((u32 *)hwsq->c.data)[i]);

		*phwsq = NULL;
		kfree(hwsq);
	}
	return ret;
}
예제 #2
0
파일: nvc0.c 프로젝트: 03199618/linux
static void
nvc0_bus_intr(struct nouveau_subdev *subdev)
{
	struct nouveau_bus *pbus = nouveau_bus(subdev);
	u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140);

	if (stat & 0x0000000e) {
		u32 addr = nv_rd32(pbus, 0x009084);
		u32 data = nv_rd32(pbus, 0x009088);

		nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x [ %s%s%s]\n",
			 (addr & 0x00000002) ? "write" : "read", data,
			 (addr & 0x00fffffc),
			 (stat & 0x00000002) ? "!ENGINE " : "",
			 (stat & 0x00000004) ? "IBUS " : "",
			 (stat & 0x00000008) ? "TIMEOUT " : "");

		nv_wr32(pbus, 0x009084, 0x00000000);
		nv_wr32(pbus, 0x001100, (stat & 0x0000000e));
		stat &= ~0x0000000e;
	}

	if (stat) {
		nv_error(pbus, "unknown intr 0x%08x\n", stat);
		nv_mask(pbus, 0x001140, stat, 0x00000000);
	}
}
예제 #3
0
파일: nv50.c 프로젝트: 24hours/linux
static int
nv50_disp_pioc_init(struct nouveau_object *object)
{
	struct nv50_disp_priv *priv = (void *)object->engine;
	struct nv50_disp_pioc *pioc = (void *)object;
	int chid = pioc->base.chid;
	int ret;

	ret = nv50_disp_chan_init(&pioc->base);
	if (ret)
		return ret;

	nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00002000);
	if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00000000, 0x00000000)) {
		nv_error(pioc, "timeout0: 0x%08x\n",
			 nv_rd32(priv, 0x610200 + (chid * 0x10)));
		return -EBUSY;
	}

	nv_wr32(priv, 0x610200 + (chid * 0x10), 0x00000001);
	if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x00030000, 0x00010000)) {
		nv_error(pioc, "timeout1: 0x%08x\n",
			 nv_rd32(priv, 0x610200 + (chid * 0x10)));
		return -EBUSY;
	}

	return 0;
}
예제 #4
0
파일: anx9805.c 프로젝트: 03199618/linux
static int
anx9805_train(struct nouveau_i2c_port *port, int link_nr, int link_bw, bool enh)
{
	struct anx9805_i2c_port *chan = (void *)port;
	struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent;
	u8 tmp, i;

	nv_wri2cr(mast, chan->addr, 0xa0, link_bw);
	nv_wri2cr(mast, chan->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00));
	nv_wri2cr(mast, chan->addr, 0xa2, 0x01);
	nv_wri2cr(mast, chan->addr, 0xa8, 0x01);

	i = 0;
	while ((tmp = nv_rdi2cr(mast, chan->addr, 0xa8)) & 0x01) {
		mdelay(5);
		if (i++ == 100) {
			nv_error(port, "link training timed out\n");
			return -ETIMEDOUT;
		}
	}

	if (tmp & 0x70) {
		nv_error(port, "link training failed: 0x%02x\n", tmp);
		return -EIO;
	}

	return 1;
}
예제 #5
0
파일: nv50.c 프로젝트: 03199618/linux
static int
nv84_graph_tlb_flush(struct nouveau_engine *engine)
{
	struct nouveau_timer *ptimer = nouveau_timer(engine);
	struct nv50_graph_priv *priv = (void *)engine;
	bool idle, timeout = false;
	unsigned long flags;
	u64 start;
	u32 tmp;

	spin_lock_irqsave(&priv->lock, flags);
	nv_mask(priv, 0x400500, 0x00000001, 0x00000000);

	start = ptimer->read(ptimer);
	do {
		idle = true;

		for (tmp = nv_rd32(priv, 0x400380); tmp && idle; tmp >>= 3) {
			if ((tmp & 7) == 1)
				idle = false;
		}

		for (tmp = nv_rd32(priv, 0x400384); tmp && idle; tmp >>= 3) {
			if ((tmp & 7) == 1)
				idle = false;
		}

		for (tmp = nv_rd32(priv, 0x400388); tmp && idle; tmp >>= 3) {
			if ((tmp & 7) == 1)
				idle = false;
		}
	} while (!idle &&
		 !(timeout = ptimer->read(ptimer) - start > 2000000000));

	if (timeout) {
		nv_error(priv, "PGRAPH TLB flush idle timeout fail\n");

		tmp = nv_rd32(priv, 0x400700);
		nv_error(priv, "PGRAPH_STATUS  : 0x%08x", tmp);
		nouveau_bitfield_print(nv50_pgraph_status, tmp);
		pr_cont("\n");

		nouveau_pgraph_vstatus_print(priv, 0, nv50_pgraph_vstatus_0,
				nv_rd32(priv, 0x400380));
		nouveau_pgraph_vstatus_print(priv, 1, nv50_pgraph_vstatus_1,
				nv_rd32(priv, 0x400384));
		nouveau_pgraph_vstatus_print(priv, 2, nv50_pgraph_vstatus_2,
				nv_rd32(priv, 0x400388));
	}


	nv_wr32(priv, 0x100c80, 0x00000001);
	if (!nv_wait(priv, 0x100c80, 0x00000001, 0x00000000))
		nv_error(priv, "vm flush timeout\n");
	nv_mask(priv, 0x400500, 0x00000001, 0x00000001);
	spin_unlock_irqrestore(&priv->lock, flags);
	return timeout ? -EBUSY : 0;
}
예제 #6
0
파일: ramnve0.c 프로젝트: JorgeFRod/linux
static int
nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq,
		   struct nouveau_ram_data *data)
{
	struct nouveau_bios *bios = nouveau_bios(pfb);
	struct nve0_ram *ram = (void *)pfb->ram;
	u8 strap, cnt, len;

	/* lookup memory config data relevant to the target frequency */
	ram->base.rammap.data = nvbios_rammapEp(bios, freq / 1000,
					       &ram->base.rammap.version,
					       &ram->base.rammap.size,
					       &cnt, &len, &data->bios);
	if (!ram->base.rammap.data || ram->base.rammap.version != 0x11 ||
	     ram->base.rammap.size < 0x09) {
		nv_error(pfb, "invalid/missing rammap entry\n");
		return -EINVAL;
	}

	/* locate specific data set for the attached memory */
	strap = nvbios_ramcfg_index(nv_subdev(pfb));
	ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data,
						ram->base.rammap.version,
						ram->base.rammap.size,
						cnt, len, strap,
						&ram->base.ramcfg.version,
						&ram->base.ramcfg.size,
						&data->bios);
	if (!ram->base.ramcfg.data || ram->base.ramcfg.version != 0x11 ||
	     ram->base.ramcfg.size < 0x08) {
		nv_error(pfb, "invalid/missing ramcfg entry\n");
		return -EINVAL;
	}

	/* lookup memory timings, if bios says they're present */
	strap = nv_ro08(bios, ram->base.ramcfg.data + 0x00);
	if (strap != 0xff) {
		ram->base.timing.data =
			nvbios_timingEp(bios, strap, &ram->base.timing.version,
				       &ram->base.timing.size, &cnt, &len,
				       &data->bios);
		if (!ram->base.timing.data ||
		     ram->base.timing.version != 0x20 ||
		     ram->base.timing.size < 0x33) {
			nv_error(pfb, "invalid/missing timing entry\n");
			return -EINVAL;
		}
	} else {
		ram->base.timing.data = 0;
	}

	data->freq = freq;
	return 0;
}
예제 #7
0
파일: hast_proto.c 프로젝트: 2asoft/freebsd
/*
 * Send the given nv structure via conn.
 * We keep headers in nv structure and pass data in separate argument.
 * There can be no data at all (data is NULL then).
 */
int
hast_proto_send(const struct hast_resource *res, struct proto_conn *conn,
    struct nv *nv, const void *data, size_t size)
{
	struct hast_main_header hdr;
	struct ebuf *eb;
	bool freedata;
	void *dptr, *hptr;
	size_t hsize;
	int ret;

	dptr = (void *)(uintptr_t)data;
	freedata = false;
	ret = -1;

	if (data != NULL) {
		unsigned int ii;

		for (ii = 0; ii < sizeof(pipeline) / sizeof(pipeline[0]);
		    ii++) {
			(void)pipeline[ii].hps_send(res, nv, &dptr, &size,
			    &freedata);
		}
		nv_add_uint32(nv, size, "size");
		if (nv_error(nv) != 0) {
			errno = nv_error(nv);
			goto end;
		}
	}

	eb = nv_hton(nv);
	if (eb == NULL)
		goto end;

	hdr.version = res != NULL ? res->hr_version : HAST_PROTO_VERSION;
	hdr.size = htole32((uint32_t)ebuf_size(eb));
	if (ebuf_add_head(eb, &hdr, sizeof(hdr)) == -1)
		goto end;

	hptr = ebuf_data(eb, &hsize);
	if (proto_send(conn, hptr, hsize) == -1)
		goto end;
	if (data != NULL && proto_send(conn, dptr, size) == -1)
		goto end;

	ret = 0;
end:
	if (freedata)
		free(dptr);
	return (ret);
}
예제 #8
0
파일: nv50.c 프로젝트: 24hours/linux
static u16
exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
	    struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
	    struct nvbios_outp *info)
{
	struct nouveau_bios *bios = nouveau_bios(priv);
	u16 mask, type, data;

	if (outp < 4) {
		type = DCB_OUTPUT_ANALOG;
		mask = 0;
	} else
	if (outp < 8) {
		switch (ctrl & 0x00000f00) {
		case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
		case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
		case 0x00000200: type = DCB_OUTPUT_TMDS; mask = 2; break;
		case 0x00000500: type = DCB_OUTPUT_TMDS; mask = 3; break;
		case 0x00000800: type = DCB_OUTPUT_DP; mask = 1; break;
		case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
		default:
			nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
			return 0x0000;
		}
		outp -= 4;
	} else {
		outp = outp - 8;
		type = 0x0010;
		mask = 0;
		switch (ctrl & 0x00000f00) {
		case 0x00000000: type |= priv->pior.type[outp]; break;
		default:
			nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl);
			return 0x0000;
		}
	}

	mask  = 0x00c0 & (mask << 6);
	mask |= 0x0001 << outp;
	mask |= 0x0100 << head;

	data = dcb_outp_match(bios, type, mask, ver, hdr, dcb);
	if (!data)
		return 0x0000;

	/* off-chip encoders require matching the exact encoder type */
	if (dcb->location != 0)
		type |= dcb->extdev << 8;

	return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info);
}
예제 #9
0
static void
nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)
{
	u32 ustat = nv_rd32(priv, 0x409c18);

	if (ustat & 0x00000001)
		nv_error(priv, "CTXCTRL ucode error\n");
	if (ustat & 0x00080000)
		nv_error(priv, "CTXCTRL watchdog timeout\n");
	if (ustat & ~0x00080001)
		nv_error(priv, "CTXCTRL 0x%08x\n", ustat);

	nvc0_graph_ctxctl_debug(priv);
	nv_wr32(priv, 0x409c20, ustat);
}
예제 #10
0
static irqreturn_t
nouveau_mc_intr(int irq, void *arg)
{
	struct nouveau_mc *pmc = arg;
	const struct nouveau_mc_intr *map = pmc->intr_map;
	struct nouveau_subdev *unit;
	u32 stat, intr;

	intr = stat = nv_rd32(pmc, 0x000100);
	while (stat && map->stat) {
		if (stat & map->stat) {
			unit = nouveau_subdev(pmc, map->unit);
			if (unit && unit->intr)
				unit->intr(unit);
			intr &= ~map->stat;
		}
		map++;
	}

	if (intr) {
		nv_error(pmc, "unknown intr 0x%08x\n", stat);
	}

	return stat ? IRQ_HANDLED : IRQ_NONE;
}
예제 #11
0
파일: vga.c 프로젝트: 03199618/linux
/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied)
 * it affects only the 8 bit vga io regs, which we access using mmio at
 * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d*
 * in general, the set value of cr44 does not matter: reg access works as
 * expected and values can be set for the appropriate head by using a 0x2000
 * offset as required
 * however:
 * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and
 *    cr44 must be set to 0 or 3 for accessing values on the correct head
 *    through the common 0xc03c* addresses
 * b) in tied mode (4) head B is programmed to the values set on head A, and
 *    access using the head B addresses can have strange results, ergo we leave
 *    tied mode in init once we know to what cr44 should be restored on exit
 *
 * the owner parameter is slightly abused:
 * 0 and 1 are treated as head values and so the set value is (owner * 3)
 * other values are treated as literal values to set
 */
u8
nv_rdvgaowner(void *obj)
{
	if (nv_device(obj)->card_type < NV_50) {
		if (nv_device(obj)->chipset == 0x11) {
			u32 tied = nv_rd32(obj, 0x001084) & 0x10000000;
			if (tied == 0) {
				u8 slA = nv_rdvgac(obj, 0, 0x28) & 0x80;
				u8 tvA = nv_rdvgac(obj, 0, 0x33) & 0x01;
				u8 slB = nv_rdvgac(obj, 1, 0x28) & 0x80;
				u8 tvB = nv_rdvgac(obj, 1, 0x33) & 0x01;
				if (slA && !tvA) return 0x00;
				if (slB && !tvB) return 0x03;
				if (slA) return 0x00;
				if (slB) return 0x03;
				return 0x00;
			}
			return 0x04;
		}

		return nv_rdvgac(obj, 0, 0x44);
	}

	nv_error(obj, "rdvgaowner after nv4x\n");
	return 0x00;
}
예제 #12
0
static void
nve0_graph_mp_trap(struct nvc0_graph_priv *priv, int gpc, int tp)
{
	int i;
	u32 werr = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x648));
	u32 gerr = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x650));

	nv_error(priv, "GPC%i/TP%i/MP trap:", gpc, tp);

	for (i = 0; i <= 31; ++i) {
		if (!(gerr & (1 << i)))
			continue;
		pr_cont(" ");
		nouveau_enum_print(nve0_mp_global_error, i);
	}
	if (werr) {
		pr_cont(" ");
		nouveau_enum_print(nve0_mp_warp_error, werr & 0xffff);
	}
	pr_cont("\n");

	/* disable MP trap to avoid spam */
	nv_mask(priv, TPC_UNIT(gpc, tp, 0x50c), 0x2, 0x0);

	/* TODO: figure out how to resume after an MP trap */
}
예제 #13
0
파일: nv50.c 프로젝트: 168519/linux
int
nv50_mpeg_init(struct nvkm_object *object)
{
	struct nv50_mpeg_priv *priv = (void *)object;
	int ret;

	ret = nvkm_mpeg_init(&priv->base);
	if (ret)
		return ret;

	nv_wr32(priv, 0x00b32c, 0x00000000);
	nv_wr32(priv, 0x00b314, 0x00000100);
	nv_wr32(priv, 0x00b0e0, 0x0000001a);

	nv_wr32(priv, 0x00b220, 0x00000044);
	nv_wr32(priv, 0x00b300, 0x00801ec1);
	nv_wr32(priv, 0x00b390, 0x00000000);
	nv_wr32(priv, 0x00b394, 0x00000000);
	nv_wr32(priv, 0x00b398, 0x00000000);
	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);

	nv_wr32(priv, 0x00b100, 0xffffffff);
	nv_wr32(priv, 0x00b140, 0xffffffff);

	if (!nv_wait(priv, 0x00b200, 0x00000001, 0x00000000)) {
		nv_error(priv, "timeout 0x%08x\n", nv_rd32(priv, 0x00b200));
		return -EBUSY;
	}

	return 0;
}
예제 #14
0
static void
nv20_devinit_meminit(struct nouveau_devinit *devinit)
{
	struct nv20_devinit_priv *priv = (void *)devinit;
	struct nouveau_device *device = nv_device(priv);
	uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900);
	uint32_t amount, off;
	struct io_mapping *fb;

	/* Map the framebuffer aperture */
	fb = fbmem_init(nv_device(priv)->pdev);
	if (!fb) {
		nv_error(priv, "failed to map fb\n");
		return;
	}

	nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1);

	/* Allow full addressing */
	nv_mask(priv, NV04_PFB_CFG0, 0, mask);

	amount = nv_rd32(priv, 0x10020c);
	for (off = amount; off > 0x2000000; off -= 0x2000000)
		fbmem_poke(fb, off - 4, off);

	amount = nv_rd32(priv, 0x10020c);
	if (amount != fbmem_peek(fb, amount - 4))
		/* IC missing - disable the upper half memory space. */
		nv_mask(priv, NV04_PFB_CFG0, mask, 0);

	fbmem_fini(fb);
}
예제 #15
0
파일: nv50.c 프로젝트: 24hours/linux
static int
nv50_disp_dmac_init(struct nouveau_object *object)
{
	struct nv50_disp_priv *priv = (void *)object->engine;
	struct nv50_disp_dmac *dmac = (void *)object;
	int chid = dmac->base.chid;
	int ret;

	ret = nv50_disp_chan_init(&dmac->base);
	if (ret)
		return ret;

	/* enable error reporting */
	nv_mask(priv, 0x610028, 0x00010001 << chid, 0x00010001 << chid);

	/* initialise channel for dma command submission */
	nv_wr32(priv, 0x610204 + (chid * 0x0010), dmac->push);
	nv_wr32(priv, 0x610208 + (chid * 0x0010), 0x00010000);
	nv_wr32(priv, 0x61020c + (chid * 0x0010), chid);
	nv_mask(priv, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010);
	nv_wr32(priv, 0x640000 + (chid * 0x1000), 0x00000000);
	nv_wr32(priv, 0x610200 + (chid * 0x0010), 0x00000013);

	/* wait for it to go inactive */
	if (!nv_wait(priv, 0x610200 + (chid * 0x10), 0x80000000, 0x00000000)) {
		nv_error(dmac, "init timeout, 0x%08x\n",
			 nv_rd32(priv, 0x610200 + (chid * 0x10)));
		return -EBUSY;
	}

	return 0;
}
예제 #16
0
파일: nvd0.c 프로젝트: thornbirdblue/linux
static int
nvd0_disp_mast_init(struct nouveau_object *object)
{
    struct nv50_disp_priv *priv = (void *)object->engine;
    struct nv50_disp_dmac *mast = (void *)object;
    int ret;

    ret = nv50_disp_chan_init(&mast->base);
    if (ret)
        return ret;

    /* enable error reporting */
    nv_mask(priv, 0x610090, 0x00000001, 0x00000001);
    nv_mask(priv, 0x6100a0, 0x00000001, 0x00000001);

    /* initialise channel for dma command submission */
    nv_wr32(priv, 0x610494, mast->push);
    nv_wr32(priv, 0x610498, 0x00010000);
    nv_wr32(priv, 0x61049c, 0x00000001);
    nv_mask(priv, 0x610490, 0x00000010, 0x00000010);
    nv_wr32(priv, 0x640000, 0x00000000);
    nv_wr32(priv, 0x610490, 0x01000013);

    /* wait for it to go inactive */
    if (!nv_wait(priv, 0x610490, 0x80000000, 0x00000000)) {
        nv_error(mast, "init: 0x%08x\n", nv_rd32(priv, 0x610490));
        return -EBUSY;
    }

    return 0;
}
예제 #17
0
static u16 therm_table(struct nouveau_device *device, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
{
    struct bit_entry bit_P;
    u16 therm = 0;
    
    if (!nouveau_bit_entry(device, 'P', &bit_P)) {
        if (bit_P.version == 1)
            therm = nv_ro16(device, bit_P.offset + 12);
        else if (bit_P.version == 2)
            therm = nv_ro16(device, bit_P.offset + 16);
        else
            nv_error(device,
                     "unknown offset for thermal in BIT P %d\n",
                     bit_P.version);
    }
    
    /* exit now if we haven't found the thermal table */
    if (!therm)
        return 0x0000;
    
    *ver = nv_ro08(device, therm + 0);
    *hdr = nv_ro08(device, therm + 1);
    *len = nv_ro08(device, therm + 2);
    *cnt = nv_ro08(device, therm + 3);
    
    return therm + nv_ro08(device, therm + 1);
}
예제 #18
0
파일: nvd0.c 프로젝트: thornbirdblue/linux
static int
nvd0_disp_pioc_init(struct nouveau_object *object)
{
    struct nv50_disp_priv *priv = (void *)object->engine;
    struct nv50_disp_pioc *pioc = (void *)object;
    int chid = pioc->base.chid;
    int ret;

    ret = nv50_disp_chan_init(&pioc->base);
    if (ret)
        return ret;

    /* enable error reporting */
    nv_mask(priv, 0x610090, 0x00000001 << chid, 0x00000001 << chid);
    nv_mask(priv, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);

    /* activate channel */
    nv_wr32(priv, 0x610490 + (chid * 0x10), 0x00000001);
    if (!nv_wait(priv, 0x610490 + (chid * 0x10), 0x00030000, 0x00010000)) {
        nv_error(pioc, "init: 0x%08x\n",
                 nv_rd32(priv, 0x610490 + (chid * 0x10)));
        return -EBUSY;
    }

    return 0;
}
예제 #19
0
static void
nv84_crypt_intr(struct nouveau_subdev *subdev)
{
	struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
	struct nouveau_engine *engine = nv_engine(subdev);
	struct nouveau_object *engctx;
	struct nv84_crypt_priv *priv = (void *)subdev;
	u32 stat = nv_rd32(priv, 0x102130);
	u32 mthd = nv_rd32(priv, 0x102190);
	u32 data = nv_rd32(priv, 0x102194);
	u32 inst = nv_rd32(priv, 0x102188) & 0x7fffffff;
	int chid;

	engctx = nouveau_engctx_get(engine, inst);
	chid   = pfifo->chid(pfifo, engctx);

	if (stat) {
		nv_error(priv, "%s", "");
		nouveau_bitfield_print(nv84_crypt_intr_mask, stat);
		pr_cont(" ch %d [0x%010llx %s] mthd 0x%04x data 0x%08x\n",
		       chid, (u64)inst << 12, nouveau_client_name(engctx),
		       mthd, data);
	}

	nv_wr32(priv, 0x102130, stat);
	nv_wr32(priv, 0x10200c, 0x10);

	nouveau_engctx_put(engctx);
}
예제 #20
0
파일: nv10.c 프로젝트: 03199618/linux
static void
nv10_devinit_meminit(struct nouveau_devinit *devinit)
{
	struct nv10_devinit_priv *priv = (void *)devinit;
	const int mem_width[] = { 0x10, 0x00, 0x20 };
	const int mem_width_count = nv_device(priv)->chipset >= 0x17 ? 3 : 2;
	uint32_t patt = 0xdeadbeef;
	struct io_mapping *fb;
	int i, j, k;

	/* Map the framebuffer aperture */
	fb = fbmem_init(nv_device(priv)->pdev);
	if (!fb) {
		nv_error(priv, "failed to map fb\n");
		return;
	}

	nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1);

	/* Probe memory bus width */
	for (i = 0; i < mem_width_count; i++) {
		nv_mask(priv, NV04_PFB_CFG0, 0x30, mem_width[i]);

		for (j = 0; j < 4; j++) {
			for (k = 0; k < 4; k++)
				fbmem_poke(fb, 0x1c, 0);

			fbmem_poke(fb, 0x1c, patt);
			fbmem_poke(fb, 0x3c, 0);

			if (fbmem_peek(fb, 0x1c) == patt)
				goto mem_width_found;
		}
	}

mem_width_found:
	patt <<= 1;

	/* Probe amount of installed memory */
	for (i = 0; i < 4; i++) {
		int off = nv_rd32(priv, 0x10020c) - 0x100000;

		fbmem_poke(fb, off, patt);
		fbmem_poke(fb, 0, 0);

		fbmem_peek(fb, 0);
		fbmem_peek(fb, 0);
		fbmem_peek(fb, 0);
		fbmem_peek(fb, 0);

		if (fbmem_peek(fb, off) == patt)
			goto amount_found;
	}

	/* IC missing - disable the upper half memory space. */
	nv_mask(priv, NV04_PFB_CFG0, 0x1000, 0);

amount_found:
	fbmem_fini(fb);
}
예제 #21
0
static int
nvd0_disp_base_init(struct nouveau_object *object)
{
	struct nv50_disp_priv *priv = (void *)object->engine;
	struct nv50_disp_base *base = (void *)object;
	int ret, i;
	u32 tmp;

	ret = nouveau_parent_init(&base->base);
	if (ret)
		return ret;

	/* The below segments of code copying values from one register to
	 * another appear to inform EVO of the display capabilities or
	 * something similar.
	 */

	/* ... CRTC caps */
	for (i = 0; i < priv->head.nr; i++) {
		tmp = nv_rd32(priv, 0x616104 + (i * 0x800));
		nv_wr32(priv, 0x6101b4 + (i * 0x800), tmp);
		tmp = nv_rd32(priv, 0x616108 + (i * 0x800));
		nv_wr32(priv, 0x6101b8 + (i * 0x800), tmp);
		tmp = nv_rd32(priv, 0x61610c + (i * 0x800));
		nv_wr32(priv, 0x6101bc + (i * 0x800), tmp);
	}

	/* ... DAC caps */
	for (i = 0; i < priv->dac.nr; i++) {
		tmp = nv_rd32(priv, 0x61a000 + (i * 0x800));
		nv_wr32(priv, 0x6101c0 + (i * 0x800), tmp);
	}

	/* ... SOR caps */
	for (i = 0; i < priv->sor.nr; i++) {
		tmp = nv_rd32(priv, 0x61c000 + (i * 0x800));
		nv_wr32(priv, 0x6301c4 + (i * 0x800), tmp);
	}

	/* steal display away from vbios, or something like that */
	if (nv_rd32(priv, 0x6100ac) & 0x00000100) {
		nv_wr32(priv, 0x6100ac, 0x00000100);
		nv_mask(priv, 0x6194e8, 0x00000001, 0x00000000);
		if (!nv_wait(priv, 0x6194e8, 0x00000002, 0x00000000)) {
			nv_error(priv, "timeout acquiring display\n");
			return -EBUSY;
		}
	}

	/* point at display engine memory area (hash table, objects) */
	nv_wr32(priv, 0x610010, (nv_gpuobj(object->parent)->addr >> 8) | 9);

	/* enable supervisor interrupts, disable everything else */
	nv_wr32(priv, 0x610090, 0x00000000);
	nv_wr32(priv, 0x6100a0, 0x00000000);
	nv_wr32(priv, 0x6100b0, 0x00000307);

	return 0;
}
예제 #22
0
파일: pllnva3.c 프로젝트: 24hours/linux
int
nva3_pll_calc(struct nouveau_subdev *subdev, struct nvbios_pll *info,
	      u32 freq, int *pN, int *pfN, int *pM, int *P)
{
	u32 best_err = ~0, err;
	int M, lM, hM, N, fN;

	*P = info->vco1.max_freq / freq;
	if (*P > info->max_p)
		*P = info->max_p;
	if (*P < info->min_p)
		*P = info->min_p;

	lM = (info->refclk + info->vco1.max_inputfreq) / info->vco1.max_inputfreq;
	lM = max(lM, (int)info->vco1.min_m);
	hM = (info->refclk + info->vco1.min_inputfreq) / info->vco1.min_inputfreq;
	hM = min(hM, (int)info->vco1.max_m);
	lM = min(lM, hM);

	for (M = lM; M <= hM; M++) {
		u32 tmp = freq * *P * M;
		N  = tmp / info->refclk;
		fN = tmp % info->refclk;

		if (!pfN) {
			if (fN >= info->refclk / 2)
				N++;
		} else {
			if (fN <  info->refclk / 2)
				N--;
			fN = tmp - (N * info->refclk);
		}

		if (N < info->vco1.min_n)
			continue;
		if (N > info->vco1.max_n)
			break;

		err = abs(freq - (info->refclk * N / M / *P));
		if (err < best_err) {
			best_err = err;
			*pN = N;
			*pM = M;
		}

		if (pfN) {
			*pfN = ((fN << 13) + info->refclk / 2) / info->refclk;
			*pfN = (*pfN - 4096) & 0xffff;
			return freq;
		}
	}

	if (unlikely(best_err == ~0)) {
		nv_error(subdev, "unable to find matching pll values\n");
		return -EINVAL;
	}

	return info->refclk * *pN / *pM / *P;
}
예제 #23
0
파일: vga.c 프로젝트: 03199618/linux
void
nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value)
{
	if      (port == 0x03c4) nv_wrvgas(obj, head, index, value);
	else if (port == 0x03ce) nv_wrvgag(obj, head, index, value);
	else if (port == 0x03d4) nv_wrvgac(obj, head, index, value);
	else nv_error(obj, "unknown indexed vga port 0x%04x\n", port);
}
예제 #24
0
파일: metadata.c 프로젝트: 2asoft/freebsd
int
metadata_write(struct hast_resource *res)
{
	struct ebuf *eb;
	struct nv *nv;
	unsigned char *buf, *ptr;
	size_t size;
	ssize_t done;
	int ret;

	buf = calloc(1, METADATA_SIZE);
	if (buf == NULL) {
		pjdlog_error("Unable to allocate %zu bytes for metadata.",
		    (size_t)METADATA_SIZE);
		return (-1);
	}

	ret = -1;

	nv = nv_alloc();
	nv_add_string(nv, res->hr_name, "resource");
	nv_add_uint64(nv, (uint64_t)res->hr_datasize, "datasize");
	nv_add_uint32(nv, (uint32_t)res->hr_extentsize, "extentsize");
	nv_add_uint32(nv, (uint32_t)res->hr_keepdirty, "keepdirty");
	nv_add_uint64(nv, (uint64_t)res->hr_localoff, "offset");
	nv_add_uint64(nv, res->hr_resuid, "resuid");
	if (res->hr_role == HAST_ROLE_PRIMARY ||
	    res->hr_role == HAST_ROLE_INIT) {
		nv_add_uint64(nv, res->hr_primary_localcnt, "localcnt");
		nv_add_uint64(nv, res->hr_primary_remotecnt, "remotecnt");
	} else /* if (res->hr_role == HAST_ROLE_SECONDARY) */ {
		PJDLOG_ASSERT(res->hr_role == HAST_ROLE_SECONDARY);
		nv_add_uint64(nv, res->hr_secondary_localcnt, "localcnt");
		nv_add_uint64(nv, res->hr_secondary_remotecnt, "remotecnt");
	}
	nv_add_string(nv, role2str(res->hr_role), "prevrole");
	if (nv_error(nv) != 0) {
		pjdlog_error("Unable to create metadata.");
		goto end;
	}
	res->hr_previous_role = res->hr_role;
	eb = nv_hton(nv);
	PJDLOG_ASSERT(eb != NULL);
	ptr = ebuf_data(eb, &size);
	PJDLOG_ASSERT(ptr != NULL);
	PJDLOG_ASSERT(size < METADATA_SIZE);
	bcopy(ptr, buf, size);
	done = pwrite(res->hr_localfd, buf, METADATA_SIZE, 0);
	if (done == -1 || done != METADATA_SIZE) {
		pjdlog_errno(LOG_ERR, "Unable to write metadata");
		goto end;
	}
	ret = 0;
end:
	free(buf);
	nv_free(nv);
	return (ret);
}
예제 #25
0
파일: nv50.c 프로젝트: 24hours/linux
static void
nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid)
{
	struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;
	u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08));
	u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08));
	u32 code = (addr & 0x00ff0000) >> 16;
	u32 type = (addr & 0x00007000) >> 12;
	u32 mthd = (addr & 0x00000ffc);
	const struct nouveau_enum *ec, *et;
	char ecunk[6], etunk[6];

	et = nouveau_enum_find(nv50_disp_intr_error_type, type);
	if (!et)
		snprintf(etunk, sizeof(etunk), "UNK%02X", type);

	ec = nouveau_enum_find(nv50_disp_intr_error_code, code);
	if (!ec)
		snprintf(ecunk, sizeof(ecunk), "UNK%02X", code);

	nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n",
		 et ? et->name : etunk, ec ? ec->name : ecunk,
		 chid, mthd, data);

	if (chid == 0) {
		switch (mthd) {
		case 0x0080:
			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0,
					    impl->mthd.core);
			break;
		default:
			break;
		}
	} else
	if (chid <= 2) {
		switch (mthd) {
		case 0x0080:
			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1,
					    impl->mthd.base);
			break;
		default:
			break;
		}
	} else
	if (chid <= 4) {
		switch (mthd) {
		case 0x0080:
			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3,
					    impl->mthd.ovly);
			break;
		default:
			break;
		}
	}

	nv_wr32(priv, 0x610020, 0x00010000 << chid);
	nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);
}
예제 #26
0
파일: vga.c 프로젝트: 03199618/linux
u8
nv_rdvgai(void *obj, int head, u16 port, u8 index)
{
	if (port == 0x03c4) return nv_rdvgas(obj, head, index);
	if (port == 0x03ce) return nv_rdvgag(obj, head, index);
	if (port == 0x03d4) return nv_rdvgac(obj, head, index);
	nv_error(obj, "unknown indexed vga port 0x%04x\n", port);
	return 0x00;
}
예제 #27
0
파일: fan.c 프로젝트: 383530895/linux
int
nouveau_therm_fan_ctor(struct nouveau_therm *therm)
{
	struct nouveau_therm_priv *priv = (void *)therm;
	struct nouveau_gpio *gpio = nouveau_gpio(therm);
	struct nouveau_bios *bios = nouveau_bios(therm);
	struct dcb_gpio_func func;
	int ret;

	/* attempt to locate a drivable fan, and determine control method */
	ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
	if (ret == 0) {
		/* FIXME: is this really the place to perform such checks ? */
		if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
			nv_debug(therm, "GPIO_FAN is in input mode\n");
			ret = -EINVAL;
		} else {
			ret = nouveau_fanpwm_create(therm, &func);
			if (ret != 0)
				ret = nouveau_fantog_create(therm, &func);
		}
	}

	/* no controllable fan found, create a dummy fan module */
	if (ret != 0) {
		ret = nouveau_fannil_create(therm);
		if (ret)
			return ret;
	}

	nv_info(therm, "FAN control: %s\n", priv->fan->type);

	/* read the current speed, it is useful when resuming */
	priv->fan->percent = nouveau_therm_fan_get(therm);

	/* attempt to detect a tachometer connection */
	ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach);
	if (ret)
		priv->fan->tach.func = DCB_GPIO_UNUSED;

	/* initialise fan bump/slow update handling */
	priv->fan->parent = therm;
	nouveau_alarm_init(&priv->fan->alarm, nouveau_fan_alarm);
	spin_lock_init(&priv->fan->lock);

	/* other random init... */
	nouveau_therm_fan_set_defaults(therm);
	nvbios_perf_fan_parse(bios, &priv->fan->perf);
	if (!nvbios_fan_parse(bios, &priv->fan->bios)) {
		nv_debug(therm, "parsing the fan table failed\n");
		if (nvbios_therm_fan_parse(bios, &priv->fan->bios))
			nv_error(therm, "parsing both fan tables failed\n");
	}
	nouveau_therm_fan_safety_checks(therm);
	return 0;
}
예제 #28
0
파일: nv50.c 프로젝트: 03199618/linux
static int
nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)
{
	struct nv50_devinit_priv *priv = (void *)devinit;
	struct nouveau_bios *bios = nouveau_bios(priv);
	struct nvbios_pll info;
	int N1, M1, N2, M2, P;
	int ret;

	ret = nvbios_pll_parse(bios, type, &info);
	if (ret) {
		nv_error(devinit, "failed to retrieve pll data, %d\n", ret);
		return ret;
	}

	ret = nv04_pll_calc(nv_subdev(devinit), &info, freq, &N1, &M1, &N2, &M2, &P);
	if (!ret) {
		nv_error(devinit, "failed pll calculation\n");
		return ret;
	}

	switch (info.type) {
	case PLL_VPLL0:
	case PLL_VPLL1:
		nv_wr32(priv, info.reg + 0, 0x10000611);
		nv_mask(priv, info.reg + 4, 0x00ff00ff, (M1 << 16) | N1);
		nv_mask(priv, info.reg + 8, 0x7fff00ff, (P  << 28) |
							(M2 << 16) | N2);
		break;
	case PLL_MEMORY:
		nv_mask(priv, info.reg + 0, 0x01ff0000, (P << 22) |
						        (info.bias_p << 19) |
							(P << 16));
		nv_wr32(priv, info.reg + 4, (N1 << 8) | M1);
		break;
	default:
		nv_mask(priv, info.reg + 0, 0x00070000, (P << 16));
		nv_wr32(priv, info.reg + 4, (N1 << 8) | M1);
		break;
	}

	return 0;
}
예제 #29
0
파일: nvd0.c 프로젝트: thornbirdblue/linux
static u16
exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
            struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
            struct nvbios_outp *info)
{
    struct nouveau_bios *bios = nouveau_bios(priv);
    u16 mask, type, data;

    if (outp < 4) {
        type = DCB_OUTPUT_ANALOG;
        mask = 0;
    } else {
        outp -= 4;
        switch (ctrl & 0x00000f00) {
        case 0x00000000:
            type = DCB_OUTPUT_LVDS;
            mask = 1;
            break;
        case 0x00000100:
            type = DCB_OUTPUT_TMDS;
            mask = 1;
            break;
        case 0x00000200:
            type = DCB_OUTPUT_TMDS;
            mask = 2;
            break;
        case 0x00000500:
            type = DCB_OUTPUT_TMDS;
            mask = 3;
            break;
        case 0x00000800:
            type = DCB_OUTPUT_DP;
            mask = 1;
            break;
        case 0x00000900:
            type = DCB_OUTPUT_DP;
            mask = 2;
            break;
        default:
            nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
            return 0x0000;
        }
        dcb->sorconf.link = mask;
    }

    mask  = 0x00c0 & (mask << 6);
    mask |= 0x0001 << outp;
    mask |= 0x0100 << head;

    data = dcb_outp_match(bios, type, mask, ver, hdr, dcb);
    if (!data)
        return 0x0000;

    return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info);
}
예제 #30
0
static void
nve0_graph_tp_trap(struct nvc0_graph_priv *priv, int gpc, int tp)
{
	u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x508));

	if (stat & 0x1) {
		u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x224));
		nv_error(priv, "GPC%i/TP%i/TEX trap: %08x\n",
			 gpc, tp, trap);

		nv_wr32(priv, TPC_UNIT(gpc, tp, 0x224), 0xc0000000);
		stat &= ~0x1;
	}

	if (stat & 0x2) {
		nve0_graph_mp_trap(priv, gpc, tp);
		stat &= ~0x2;
	}

	if (stat & 0x4) {
		u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x084));
		nv_error(priv, "GPC%i/TP%i/POLY trap: %08x\n",
			 gpc, tp, trap);

		nv_wr32(priv, TPC_UNIT(gpc, tp, 0x084), 0xc0000000);
		stat &= ~0x4;
	}

	if (stat & 0x8) {
		u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x48c));
		nv_error(priv, "GPC%i/TP%i/L1C trap: %08x\n",
			 gpc, tp, trap);

		nv_wr32(priv, TPC_UNIT(gpc, tp, 0x48c), 0xc0000000);
		stat &= ~0x8;
	}

	if (stat) {
		nv_error(priv, "GPC%i/TP%i: unknown stat %08x\n",
			 gpc, tp, stat);
	}
}