示例#1
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);
}
示例#2
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);
}
示例#3
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;
}
static void
gk20a_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{
	struct gk20a_mem *mem = to_gk20a_mem(*pmem);

	*pmem = NULL;
	if (unlikely(mem == NULL))
		return;

#if defined(__NetBSD__)
	if (likely(mem->base.pages)) {
		const bus_dma_tag_t dmat = nv_device(pfb)->platformdev->dmat;
		bus_dmamap_unload(dmat, mem->base.pages);
		bus_dmamem_unmap(dmat, mem->cpuaddr, mem->dmasize);
		bus_dmamap_destroy(dmat, mem->base.pages);
		bus_dmamem_free(dmat, &mem->dmaseg, 1);
	}
#else
	struct device *dev = nv_device_base(nv_device(pfb));
	if (likely(mem->cpuaddr))
		dma_free_coherent(dev, mem->base.size << PAGE_SHIFT,
				  mem->cpuaddr, mem->handle);

	kfree(mem->base.pages);
#endif
	kfree(mem);
}
示例#5
0
static void
nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
{
	struct drm_device *dev = nv_crtc->base.dev;
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nouveau_channel *evo = nv50_display(dev)->master;
	int ret;

	NV_DEBUG(drm, "\n");

	if (update && !nv_crtc->cursor.visible)
		return;

	ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2);
	if (ret) {
		NV_ERROR(drm, "no space while hiding cursor\n");
		return;
	}
	BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2);
	OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE);
	OUT_RING(evo, 0);
	if (nv_device(drm->device)->chipset != 0x50) {
		BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1);
		OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE);
	}

	if (update) {
		BEGIN_NV04(evo, 0, NV50_EVO_UPDATE, 1);
		OUT_RING(evo, 0);
		FIRE_RING(evo);
		nv_crtc->cursor.visible = false;
	}
}
示例#6
0
u8 *
nouveau_perf_rammap(struct drm_device *dev, u32 freq,
		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
{
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct bit_entry P;
	u8 *perf, i = 0;

	if (!bit_table(dev, 'P', &P) && P.version == 2) {
		u8 *rammap = ROMPTR(dev, P.data[4]);
		if (rammap) {
			u8 *ramcfg = rammap + rammap[1];

			*ver = rammap[0];
			*hdr = rammap[2];
			*cnt = rammap[4];
			*len = rammap[3];

			freq /= 1000;
			for (i = 0; i < rammap[5]; i++) {
				if (freq >= ROM16(ramcfg[0]) &&
				    freq <= ROM16(ramcfg[2]))
					return ramcfg;

				ramcfg += *hdr + (*cnt * *len);
			}
		}

		return NULL;
	}

	if (nv_device(drm->device)->chipset == 0x49 ||
	    nv_device(drm->device)->chipset == 0x4b)
		freq /= 2;

	while ((perf = nouveau_perf_entry(dev, i++, ver, hdr, cnt, len))) {
		if (*ver >= 0x20 && *ver < 0x25) {
			if (perf[0] != 0xff && freq <= ROM16(perf[11]) * 1000)
				break;
		} else
		if (*ver >= 0x25 && *ver < 0x40) {
			if (perf[0] != 0xff && freq <= ROM16(perf[12]) * 1000)
				break;
		}
	}

	if (perf) {
		u8 *ramcfg = perf + *hdr;
		*ver = 0x00;
		*hdr = 0;
		return ramcfg;
	}

	return NULL;
}
示例#7
0
文件: shadowrom.c 项目: 168519/linux
static void *
prom_init(struct nvkm_bios *bios, const char *name)
{
	if (nv_device(bios)->card_type < NV_50) {
		if (nv_device(bios)->card_type == NV_40 &&
		    nv_device(bios)->chipset >= 0x4c)
			return ERR_PTR(-ENODEV);
		nv_mask(bios, 0x001850, 0x00000001, 0x00000000);
	} else {
		nv_mask(bios, 0x088050, 0x00000001, 0x00000000);
	}
	return bios;
}
示例#8
0
文件: nv50.c 项目: 24hours/linux
int
nv50_fan_pwm_clock(struct nouveau_therm *therm, int line)
{
	int chipset = nv_device(therm)->chipset;
	int crystal = nv_device(therm)->crystal;
	int pwm_clock;

	/* determine the PWM source clock */
	if (chipset > 0x50 && chipset < 0x94) {
		u8 pwm_div = nv_rd32(therm, 0x410c);
		if (nv_rd32(therm, 0xc040) & 0x800000) {
			/* Use the HOST clock (100 MHz)
			* Where does this constant(2.4) comes from? */
			pwm_clock = (100000000 >> pwm_div) * 10 / 24;
		} else {
示例#9
0
int
nouveau_therm_fan_get(struct nouveau_therm *therm)
{
	struct nouveau_therm_priv *priv = (void *)therm;
	struct nouveau_gpio *gpio = nouveau_gpio(therm);
	struct dcb_gpio_func func;
	int card_type = nv_device(therm)->card_type;
	u32 divs, duty;
	int ret;

	if (!priv->fan.pwm_get)
		return -ENODEV;

	ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func);
	if (ret == 0) {
		ret = priv->fan.pwm_get(therm, func.line, &divs, &duty);
		if (ret == 0 && divs) {
			divs = max(divs, duty);
			if (card_type <= NV_40 || (func.log[0] & 1))
				duty = divs - duty;
			return (duty * 100) / divs;
		}

		return gpio->get(gpio, 0, func.func, func.line) * 100;
	}

	return -ENODEV;
}
示例#10
0
文件: shadowacpi.c 项目: 168519/linux
static void *
acpi_init(struct nvkm_bios *bios, const char *name)
{
	if (!nouveau_acpi_rom_supported(nv_device(bios)->pdev))
		return ERR_PTR(-ENODEV);
	return NULL;
}
示例#11
0
static enum nv40_sensor_style
nv40_sensor_style(struct nouveau_therm *therm)
{
	struct nouveau_device *device = nv_device(therm);

	switch (device->chipset) {
	case 0x43:
	case 0x44:
	case 0x4a:
	case 0x47:
		return OLD_STYLE;

	case 0x46:
	case 0x49:
	case 0x4b:
	case 0x4e:
	case 0x4c:
	case 0x67:
	case 0x68:
	case 0x63:
		return NEW_STYLE;
	default:
		return INVALID_STYLE;
	}
}
示例#12
0
文件: fanpwm.c 项目: 168519/linux
static int
nvkm_fanpwm_set(struct nvkm_therm *therm, int percent)
{
	struct nvkm_therm_priv *tpriv = (void *)therm;
	struct nvkm_fanpwm_priv *priv = (void *)tpriv->fan;
	int card_type = nv_device(therm)->card_type;
	u32 divs, duty;
	int ret;

	divs = priv->base.perf.pwm_divisor;
	if (priv->base.bios.pwm_freq) {
		divs = 1;
		if (therm->pwm_clock)
			divs = therm->pwm_clock(therm, priv->func.line);
		divs /= priv->base.bios.pwm_freq;
	}

	duty = ((divs * percent) + 99) / 100;
	if (card_type <= NV_40 || (priv->func.log[0] & 1))
		duty = divs - duty;

	ret = therm->pwm_set(therm, priv->func.line, divs, duty);
	if (ret == 0)
		ret = therm->pwm_ctrl(therm, priv->func.line, true);
	return ret;
}
示例#13
0
int
nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode)
{
    struct nouveau_therm_priv *priv = (void *)therm;
    struct nouveau_device *device = nv_device(therm);
    static const char *name[] = {
        "disabled",
        "manual",
        "automatic"
    };

    /* The default PDAEMON ucode interferes with fan management */
    if ((mode >= ARRAY_SIZE(name)) ||
            (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0))
        return -EINVAL;

    /* do not allow automatic fan management if the thermal sensor is
     * not available */
    if (priv->mode == 2 && therm->temp_get(therm) < 0)
        return -EINVAL;

    if (priv->mode == mode)
        return 0;

    nv_info(therm, "fan management: %s\n", name[mode]);
    nouveau_therm_update(therm, mode);
    return 0;
}
示例#14
0
文件: subdev.c 项目: 24hours/linux
int
nouveau_subdev_create_(struct nouveau_object *parent,
		       struct nouveau_object *engine,
		       struct nouveau_oclass *oclass, u32 pclass,
		       const char *subname, const char *sysname,
		       int size, void **pobject)
{
	struct nouveau_subdev *subdev;
	int ret;

	ret = nouveau_object_create_(parent, engine, oclass, pclass |
				     NV_SUBDEV_CLASS, size, pobject);
	subdev = *pobject;
	if (ret)
		return ret;

	__mutex_init(&subdev->mutex, subname, &oclass->lock_class_key);
	subdev->name = subname;

	if (parent) {
		struct nouveau_device *device = nv_device(parent);
		subdev->debug = nouveau_dbgopt(device->dbgopt, subname);
		subdev->mmio  = nv_subdev(device)->mmio;
	}

	return 0;
}
示例#15
0
static int
nv40_temp_get(struct nouveau_therm *therm)
{
	struct nouveau_therm_priv *priv = (void *)therm;
	struct nouveau_device *device = nv_device(therm);
	struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
	int core_temp;

	if (device->chipset >= 0x46) {
		nv_wr32(therm, 0x15b0, 0x80003fff);
		core_temp = nv_rd32(therm, 0x15b4) & 0x3fff;
	} else {
		nv_wr32(therm, 0x15b0, 0xff);
		core_temp = nv_rd32(therm, 0x15b4) & 0xff;
	}

	/* Setup the sensor if the temperature is 0 */
	if (core_temp == 0)
		core_temp = nv40_sensor_setup(therm);

	if (sensor->slope_div == 0)
		sensor->slope_div = 1;
	if (sensor->offset_den == 0)
		sensor->offset_den = 1;
	if (sensor->slope_mult < 1)
		sensor->slope_mult = 1;

	core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
	core_temp = core_temp + sensor->offset_num / sensor->offset_den;
	core_temp = core_temp + sensor->offset_constant - 8;

	return core_temp;
}
示例#16
0
文件: nv50.c 项目: 24hours/linux
static void
nv50_fb_intr(struct nouveau_subdev *subdev)
{
	struct nouveau_device *device = nv_device(subdev);
	struct nouveau_engine *engine;
	struct nv50_fb_priv *priv = (void *)subdev;
	const struct nouveau_enum *en, *cl;
	struct nouveau_object *engctx = NULL;
	u32 trap[6], idx, chan;
	u8 st0, st1, st2, st3;
	int i;

	idx = nv_rd32(priv, 0x100c90);
	if (!(idx & 0x80000000))
		return;
	idx &= 0x00ffffff;

	for (i = 0; i < 6; i++) {
		nv_wr32(priv, 0x100c90, idx | i << 24);
		trap[i] = nv_rd32(priv, 0x100c94);
	}
	nv_wr32(priv, 0x100c90, idx | 0x80000000);

	/* decode status bits into something more useful */
	if (device->chipset  < 0xa3 ||
	    device->chipset == 0xaa || device->chipset == 0xac) {
		st0 = (trap[0] & 0x0000000f) >> 0;
		st1 = (trap[0] & 0x000000f0) >> 4;
		st2 = (trap[0] & 0x00000f00) >> 8;
		st3 = (trap[0] & 0x0000f000) >> 12;
	} else {
示例#17
0
文件: subdev.c 项目: 24hours/linux
void
nouveau_subdev_destroy(struct nouveau_subdev *subdev)
{
	int subidx = nv_hclass(subdev) & 0xff;
	nv_device(subdev)->subdev[subidx] = NULL;
	nouveau_object_destroy(&subdev->base);
}
示例#18
0
文件: fanpwm.c 项目: 168519/linux
int
nvkm_fanpwm_create(struct nvkm_therm *therm, struct dcb_gpio_func *func)
{
	struct nvkm_device *device = nv_device(therm);
	struct nvkm_therm_priv *tpriv = (void *)therm;
	struct nvkm_bios *bios = nvkm_bios(therm);
	struct nvkm_fanpwm_priv *priv;
	struct nvbios_therm_fan fan;
	u32 divs, duty;

	nvbios_fan_parse(bios, &fan);

	if (!nvkm_boolopt(device->cfgopt, "NvFanPWM", func->param) ||
	    !therm->pwm_ctrl || fan.type == NVBIOS_THERM_FAN_TOGGLE ||
	     therm->pwm_get(therm, func->line, &divs, &duty) == -ENODEV)
		return -ENODEV;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	tpriv->fan = &priv->base;
	if (!priv)
		return -ENOMEM;

	priv->base.type = "PWM";
	priv->base.get = nvkm_fanpwm_get;
	priv->base.set = nvkm_fanpwm_set;
	priv->func = *func;
	return 0;
}
示例#19
0
static inline u32
init_nvreg(struct nvbios_init *init, u32 reg)
{
	/* C51 (at least) sometimes has the lower bits set which the VBIOS
	 * interprets to mean that access needs to go through certain IO
	 * ports instead.  The NVIDIA binary driver has been seen to access
	 * these through the NV register address, so lets assume we can
	 * do the same
	 */
	reg &= ~0x00000003;

	/* GF8+ display scripts need register addresses mangled a bit to
	 * select a specific CRTC/OR
	 */
	if (nv_device(init->bios)->card_type >= NV_50) {
		if (reg & 0x80000000) {
			reg += init_crtc(init) * 0x800;
			reg &= ~0x80000000;
		}

		if (reg & 0x40000000) {
			reg += init_or(init) * 0x800;
			reg &= ~0x40000000;
			if (reg & 0x20000000) {
				reg += init_link(init) * 0x80;
				reg &= ~0x20000000;
			}
		}
	}

	if (reg & ~0x00fffffc)
		warn("unknown bits in register 0x%08x\n", reg);
	return reg;
}
示例#20
0
void
_nouveau_mc_dtor(struct nouveau_object *object)
{
	struct nouveau_device *device = nv_device(object);
	struct nouveau_mc *pmc = (void *)object;
	free_irq(device->pdev->irq, pmc);
	nouveau_subdev_destroy(&pmc->base);
}
示例#21
0
int
nouveau_i2c_port_create_(struct nouveau_object *parent,
			 struct nouveau_object *engine,
			 struct nouveau_oclass *oclass, u8 index,
			 const struct i2c_algorithm *algo,
			 int size, void **pobject)
{
	struct nouveau_device *device = nv_device(parent);
	struct nouveau_i2c *i2c = (void *)engine;
	struct nouveau_i2c_port *port;
	int ret;

	ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject);
	port = *pobject;
	if (ret)
		return ret;

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

	if ( algo == &nouveau_i2c_bit_algo &&
	    !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) {
		struct i2c_algo_bit_data *bit;

		bit = kzalloc(sizeof(*bit), GFP_KERNEL);
		if (!bit)
			return -ENOMEM;

		bit->udelay = 10;
		bit->timeout = usecs_to_jiffies(2200);
		bit->data = port;
		bit->pre_xfer = nouveau_i2c_pre_xfer;
		bit->setsda = nouveau_i2c_setsda;
		bit->setscl = nouveau_i2c_setscl;
		bit->getsda = nouveau_i2c_getsda;
		bit->getscl = nouveau_i2c_getscl;

		port->adapter.algo_data = bit;
		ret = i2c_bit_add_bus(&port->adapter);
	} else {
		port->adapter.algo_data = port;
		port->adapter.algo = algo;
		ret = i2c_add_adapter(&port->adapter);
	}

	/* drop port's i2c subdev refcount, i2c handles this itself */
	if (ret == 0) {
		list_add_tail(&port->head, &i2c->ports);
		atomic_dec(&parent->refcount);
		atomic_dec(&engine->refcount);
	}

	return ret;
}
示例#22
0
文件: ramnve0.c 项目: JorgeFRod/linux
static int
nve0_ram_prog(struct nouveau_fb *pfb)
{
	struct nouveau_device *device = nv_device(pfb);
	struct nve0_ram *ram = (void *)pfb->ram;
	struct nve0_ramfuc *fuc = &ram->fuc;
	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true));
	return (ram->base.next == &ram->base.xition);
}
示例#23
0
文件: shadowrom.c 项目: 168519/linux
static void
prom_fini(void *data)
{
	struct nvkm_bios *bios = data;
	if (nv_device(bios)->card_type < NV_50)
		nv_mask(bios, 0x001850, 0x00000001, 0x00000001);
	else
		nv_mask(bios, 0x088050, 0x00000001, 0x00000001);
}
示例#24
0
文件: ramnvc0.c 项目: 24hours/linux
static int
nvc0_ram_prog(struct nouveau_fb *pfb)
{
	struct nouveau_device *device = nv_device(pfb);
	struct nvc0_ram *ram = (void *)pfb->ram;
	struct nvc0_ramfuc *fuc = &ram->fuc;
	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", false));
	return 0;
}
示例#25
0
int
nouveau_i2c_port_create_(struct nouveau_object *parent,
			 struct nouveau_object *engine,
			 struct nouveau_oclass *oclass, u8 index,
			 const struct i2c_algorithm *algo,
			 const struct nouveau_i2c_func *func,
			 int size, void **pobject)
{
	struct nouveau_device *device = nv_device(engine);
	struct nouveau_i2c *i2c = (void *)engine;
	struct nouveau_i2c_port *port;
	int ret;

	ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject);
	port = *pobject;
	if (ret)
		return ret;

	snprintf(port->adapter.name, sizeof(port->adapter.name),
		 "nouveau-%s-%d", device->name, index);
	port->adapter.owner = THIS_MODULE;
	port->adapter.dev.parent = nv_device_base(device);
	port->index = index;
	port->aux = -1;
	port->func = func;
	mutex_init(&port->mutex);

	if ( algo == &nouveau_i2c_bit_algo &&
	    !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) {
		struct i2c_algo_bit_data *bit;

		bit = kzalloc(sizeof(*bit), GFP_KERNEL);
		if (!bit)
			return -ENOMEM;

		bit->udelay = 10;
		bit->timeout = usecs_to_jiffies(2200);
		bit->data = port;
		bit->pre_xfer = nouveau_i2c_pre_xfer;
		bit->post_xfer = nouveau_i2c_post_xfer;
		bit->setsda = nouveau_i2c_setsda;
		bit->setscl = nouveau_i2c_setscl;
		bit->getsda = nouveau_i2c_getsda;
		bit->getscl = nouveau_i2c_getscl;

		port->adapter.algo_data = bit;
		ret = i2c_bit_add_bus(&port->adapter);
	} else {
		port->adapter.algo_data = port;
		port->adapter.algo = algo;
		ret = i2c_add_adapter(&port->adapter);
	}

	if (ret == 0)
		list_add_tail(&port->head, &i2c->ports);
	return ret;
}
示例#26
0
文件: base.c 项目: 3null/linux
static void
nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
{
	struct nouveau_device *device = nv_device(bios);
	u64 addr = 0;
	u32 bar0 = 0;
	int i;

	if (device->card_type >= NV_50) {
		if (device->card_type >= NV_C0 && device->card_type < GM100) {
			if (nv_rd32(bios, 0x022500) & 0x00000001)
				return;
		} else
		if (device->card_type >= GM100) {
			if (nv_rd32(bios, 0x021c04) & 0x00000001)
				return;
		}

		addr = nv_rd32(bios, 0x619f04);
		if (!(addr & 0x00000008)) {
			nv_debug(bios, "... not enabled\n");
			return;
		}
		if ( (addr & 0x00000003) != 1) {
			nv_debug(bios, "... not in vram\n");
			return;
		}

		addr = (addr & 0xffffff00) << 8;
		if (!addr) {
			addr  = (u64)nv_rd32(bios, 0x001700) << 16;
			addr += 0xf0000;
		}

		bar0 = nv_mask(bios, 0x001700, 0xffffffff, addr >> 16);
	}

	/* bail if no rom signature */
	if (nv_rd08(bios, 0x700000) != 0x55 ||
	    nv_rd08(bios, 0x700001) != 0xaa)
		goto out;

	bios->size = nv_rd08(bios, 0x700002) * 512;
	if (!bios->size)
		goto out;

	bios->data = kmalloc(bios->size, GFP_KERNEL);
	if (bios->data) {
		for (i = 0; i < bios->size; i++)
			nv_wo08(bios, i, nv_rd08(bios, 0x700000 + i));
	}

out:
	if (device->card_type >= NV_50)
		nv_wr32(bios, 0x001700, bar0);
}
示例#27
0
文件: vga.c 项目: 03199618/linux
void
nv_wrvgaowner(void *obj, u8 select)
{
	if (nv_device(obj)->card_type < NV_50) {
		u8 owner = (select == 1) ? 3 : select;
		if (nv_device(obj)->chipset == 0x11) {
			/* workaround hw lockup bug */
			nv_rdvgac(obj, 0, 0x1f);
			nv_rdvgac(obj, 1, 0x1f);
		}

		nv_wrvgac(obj, 0, 0x44, owner);

		if (nv_device(obj)->chipset == 0x11) {
			nv_wrvgac(obj, 0, 0x2e, owner);
			nv_wrvgac(obj, 0, 0x2e, owner);
		}
	} else
		nv_error(obj, "wrvgaowner after nv4x\n");
}
示例#28
0
static void
init_wrvgai(struct nvbios_init *init, u16 port, u8 index, u8 value)
{
	/* force head 0 for updates to cr44, it only exists on first head */
	if (nv_device(init->subdev)->card_type < NV_50) {
		if (port == 0x03d4 && index == 0x44)
			init->crtc = 0;
	}

	if (init_exec(init)) {
		int head = init->crtc < 0 ? 0 : init->crtc;
		nv_wrvgai(init->subdev, head, port, index, value);
	}

	/* select head 1 if cr44 write selected it */
	if (nv_device(init->subdev)->card_type < NV_50) {
		if (port == 0x03d4 && index == 0x44 && value == 3)
			init->crtc = 1;
	}
}
示例#29
0
文件: base.c 项目: 03199618/linux
static void
nouveau_bios_shadow_prom(struct nouveau_bios *bios)
{
	struct nouveau_device *device = nv_device(bios);
	u32 pcireg, access;
	u16 pcir;
	int i;

	/* enable access to rom */
	if (device->card_type >= NV_50)
		pcireg = 0x088050;
	else
		pcireg = 0x001850;
	access = nv_mask(bios, pcireg, 0x00000001, 0x00000000);

	/* bail if no rom signature, with a workaround for a PROM reading
	 * issue on some chipsets.  the first read after a period of
	 * inactivity returns the wrong result, so retry the first header
	 * byte a few times before giving up as a workaround
	 */
	i = 16;
	do {
		if (nv_rd08(bios, 0x300000) == 0x55)
			break;
	} while (i--);

	if (!i || nv_rd08(bios, 0x300001) != 0xaa)
		goto out;

	/* additional check (see note below) - read PCI record header */
	pcir = nv_rd08(bios, 0x300018) |
	       nv_rd08(bios, 0x300019) << 8;
	if (nv_rd08(bios, 0x300000 + pcir) != 'P' ||
	    nv_rd08(bios, 0x300001 + pcir) != 'C' ||
	    nv_rd08(bios, 0x300002 + pcir) != 'I' ||
	    nv_rd08(bios, 0x300003 + pcir) != 'R')
		goto out;

	/* read entire bios image to system memory */
	bios->size = nv_rd08(bios, 0x300002) * 512;
	if (!bios->size)
		goto out;

	bios->data = kmalloc(bios->size, GFP_KERNEL);
	if (bios->data) {
		for (i = 0; i < bios->size; i++)
			nv_wo08(bios, i, nv_rd08(bios, 0x300000 + i));
	}

out:
	/* disable access to rom */
	nv_wr32(bios, pcireg, access);
}
示例#30
0
文件: vga.c 项目: 03199618/linux
bool
nv_lockvgac(void *obj, bool lock)
{
	bool locked = !nv_rdvgac(obj, 0, 0x1f);
	u8 data = lock ? 0x99 : 0x57;
	nv_wrvgac(obj, 0, 0x1f, data);
	if (nv_device(obj)->chipset == 0x11) {
		if (!(nv_rd32(obj, 0x001084) & 0x10000000))
			nv_wrvgac(obj, 1, 0x1f, data);
	}
	return locked;
}