Ejemplo n.º 1
0
/**
 * INIT_REPEAT - opcode 0x33
 *
 */
static void
init_repeat(struct nvbios_init *init)
{
	struct nouveau_bios *bios = init->bios;
	u8 count = nv_ro08(bios, init->offset + 1);
	u16 repeat = init->repeat;

	trace("REPEAT\t0x%02x\n", count);
	init->offset += 2;

	init->repeat = init->offset;
	init->repend = init->offset;
	while (count--) {
		init->offset = init->repeat;
		nvbios_exec(init);
Ejemplo n.º 2
0
Archivo: nv50.c Proyecto: 24hours/linux
static bool
exec_script(struct nv50_disp_priv *priv, int head, int id)
{
	struct nouveau_bios *bios = nouveau_bios(priv);
	struct nvbios_outp info;
	struct dcb_output dcb;
	u8  ver, hdr, cnt, len;
	u16 data;
	u32 ctrl = 0x00000000;
	u32 reg;
	int i;

	/* DAC */
	for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
		ctrl = nv_rd32(priv, 0x610b5c + (i * 8));

	/* SOR */
	if (!(ctrl & (1 << head))) {
		if (nv_device(priv)->chipset  < 0x90 ||
		    nv_device(priv)->chipset == 0x92 ||
		    nv_device(priv)->chipset == 0xa0) {
			reg = 0x610b74;
		} else {
			reg = 0x610798;
		}
		for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
			ctrl = nv_rd32(priv, reg + (i * 8));
		i += 4;
	}

	/* PIOR */
	if (!(ctrl & (1 << head))) {
		for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
			ctrl = nv_rd32(priv, 0x610b84 + (i * 8));
		i += 8;
	}

	if (!(ctrl & (1 << head)))
		return false;
	i--;

	data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info);
	if (data) {
		struct nvbios_init init = {
			.subdev = nv_subdev(priv),
			.bios = bios,
			.offset = info.script[id],
			.outp = &dcb,
			.crtc = head,
			.execute = 1,
		};

		return nvbios_exec(&init) == 0;
	}

	return false;
}

static u32
exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,
	    struct dcb_output *outp)
{
	struct nouveau_bios *bios = nouveau_bios(priv);
	struct nvbios_outp info1;
	struct nvbios_ocfg info2;
	u8  ver, hdr, cnt, len;
	u32 ctrl = 0x00000000;
	u32 data, conf = ~0;
	u32 reg;
	int i;

	/* DAC */
	for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++)
		ctrl = nv_rd32(priv, 0x610b58 + (i * 8));

	/* SOR */
	if (!(ctrl & (1 << head))) {
		if (nv_device(priv)->chipset  < 0x90 ||
		    nv_device(priv)->chipset == 0x92 ||
		    nv_device(priv)->chipset == 0xa0) {
			reg = 0x610b70;
		} else {
			reg = 0x610794;
		}
		for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++)
			ctrl = nv_rd32(priv, reg + (i * 8));
		i += 4;
	}

	/* PIOR */
	if (!(ctrl & (1 << head))) {
		for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++)
			ctrl = nv_rd32(priv, 0x610b80 + (i * 8));
		i += 8;
	}

	if (!(ctrl & (1 << head)))
		return conf;
	i--;

	data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1);
	if (!data)
		return conf;

	if (outp->location == 0) {
		switch (outp->type) {
		case DCB_OUTPUT_TMDS:
			conf = (ctrl & 0x00000f00) >> 8;
			if (pclk >= 165000)
				conf |= 0x0100;
			break;
		case DCB_OUTPUT_LVDS:
			conf = priv->sor.lvdsconf;
			break;
		case DCB_OUTPUT_DP:
			conf = (ctrl & 0x00000f00) >> 8;
			break;
		case DCB_OUTPUT_ANALOG:
		default:
			conf = 0x00ff;
			break;
		}
	} else {
		conf = (ctrl & 0x00000f00) >> 8;
		pclk = pclk / 2;
	}

	data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
	if (data && id < 0xff) {
		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
		if (data) {
			struct nvbios_init init = {
				.subdev = nv_subdev(priv),
				.bios = bios,
				.offset = data,
				.outp = outp,
				.crtc = head,
				.execute = 1,
			};

			nvbios_exec(&init);
		}
	}

	return conf;
}
Ejemplo n.º 3
0
static bool
exec_script(struct nv50_disp_priv *priv, int head, int id)
{
    struct nouveau_bios *bios = nouveau_bios(priv);
    struct nvbios_outp info;
    struct dcb_output dcb;
    u8  ver, hdr, cnt, len;
    u32 ctrl = 0x00000000;
    u16 data;
    int outp;

    for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) {
        ctrl = nv_rd32(priv, 0x640180 + (outp * 0x20));
        if (ctrl & (1 << head))
            break;
    }

    if (outp == 8)
        return false;

    data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info);
    if (data) {
        struct nvbios_init init = {
            .subdev = nv_subdev(priv),
            .bios = bios,
            .offset = info.script[id],
            .outp = &dcb,
            .crtc = head,
            .execute = 1,
        };

        return nvbios_exec(&init) == 0;
    }

    return false;
}

static u32
exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
            u32 pclk, struct dcb_output *dcb)
{
    struct nouveau_bios *bios = nouveau_bios(priv);
    struct nvbios_outp info1;
    struct nvbios_ocfg info2;
    u8  ver, hdr, cnt, len;
    u32 ctrl = 0x00000000;
    u32 data, conf = ~0;
    int outp;

    for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) {
        ctrl = nv_rd32(priv, 0x660180 + (outp * 0x20));
        if (ctrl & (1 << head))
            break;
    }

    if (outp == 8)
        return false;

    data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1);
    if (data == 0x0000)
        return conf;

    switch (dcb->type) {
    case DCB_OUTPUT_TMDS:
        conf = (ctrl & 0x00000f00) >> 8;
        if (pclk >= 165000)
            conf |= 0x0100;
        break;
    case DCB_OUTPUT_LVDS:
        conf = priv->sor.lvdsconf;
        break;
    case DCB_OUTPUT_DP:
        conf = (ctrl & 0x00000f00) >> 8;
        break;
    case DCB_OUTPUT_ANALOG:
    default:
        conf = 0x00ff;
        break;
    }

    data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2);
    if (data && id < 0xff) {
        data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
        if (data) {
            struct nvbios_init init = {
                .subdev = nv_subdev(priv),
                .bios = bios,
                .offset = data,
                .outp = dcb,
                .crtc = head,
                .execute = 1,
            };

            nvbios_exec(&init);
        }
    }

    return conf;
}

static void
nvd0_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head)
{
    exec_script(priv, head, 1);
}
Ejemplo n.º 4
0
int
nv50_devinit_init(struct nouveau_object *object)
{
	struct nouveau_bios *bios = nouveau_bios(object);
	struct nv50_devinit_priv *priv = (void *)object;
	struct nvbios_outp info;
	struct dcb_output outp;
	u8  ver = 0xff, hdr, cnt, len;
	int ret, i = 0;

	if (!priv->base.post) {
		if (!nv_rdvgac(priv, 0, 0x00) &&
		    !nv_rdvgac(priv, 0, 0x1a)) {
			nv_info(priv, "adaptor not initialised\n");
			priv->base.post = true;
		}
	}

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

	/* if we ran the init tables, we have to execute the first script
	 * pointer of each dcb entry's display encoder table in order
	 * to properly initialise each encoder.
	 */
	while (priv->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) {
		if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
				     &ver, &hdr, &cnt, &len, &info)) {
			struct nvbios_init init = {
				.subdev = nv_subdev(priv),
				.bios = bios,
				.offset = info.script[0],
				.outp = &outp,
				.crtc = -1,
				.execute = 1,
			};

			nvbios_exec(&init);
		}
		i++;
	}

	return 0;
}

static int
nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
		  struct nouveau_oclass *oclass, void *data, u32 size,
		  struct nouveau_object **pobject)
{
	struct nv50_devinit_priv *priv;
	int ret;

	ret = nouveau_devinit_create(parent, engine, oclass, &priv);
	*pobject = nv_object(priv);
	if (ret)
		return ret;

	priv->base.pll_set = nv50_devinit_pll_set;
	return 0;
}

struct nouveau_oclass
nv50_devinit_oclass = {
	.handle = NV_SUBDEV(DEVINIT, 0x50),
	.ofuncs = &(struct nouveau_ofuncs) {
		.ctor = nv50_devinit_ctor,
		.dtor = _nouveau_devinit_dtor,
		.init = nv50_devinit_init,
		.fini = _nouveau_devinit_fini,
	},
};
Ejemplo n.º 5
0
void
nv50_devinit_init(struct nvkm_devinit *base)
{
	struct nv50_devinit *init = nv50_devinit(base);
	struct nvkm_subdev *subdev = &init->base.subdev;
	struct nvkm_device *device = subdev->device;
	struct nvkm_bios *bios = device->bios;
	struct nvbios_outp info;
	struct dcb_output outp;
	u8  ver = 0xff, hdr, cnt, len;
	int i = 0;

	/* if we ran the init tables, we have to execute the first script
	 * pointer of each dcb entry's display encoder table in order
	 * to properly initialise each encoder.
	 */
	while (init->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) {
		if (nvbios_outp_match(bios, outp.hasht, outp.hashm,
				      &ver, &hdr, &cnt, &len, &info)) {
			struct nvbios_init exec = {
				.subdev = subdev,
				.bios = bios,
				.offset = info.script[0],
				.outp = &outp,
				.crtc = -1,
				.execute = 1,
			};

			nvbios_exec(&exec);
		}
		i++;
	}
}

int
nv50_devinit_new_(const struct nvkm_devinit_func *func,
		  struct nvkm_device *device, int index,
		  struct nvkm_devinit **pinit)
{
	struct nv50_devinit *init;

	if (!(init = kzalloc(sizeof(*init), GFP_KERNEL)))
		return -ENOMEM;
	*pinit = &init->base;

	nvkm_devinit_ctor(func, device, index, &init->base);
	return 0;
}

static const struct nvkm_devinit_func
nv50_devinit = {
	.preinit = nv50_devinit_preinit,
	.init = nv50_devinit_init,
	.post = nv04_devinit_post,
	.pll_set = nv50_devinit_pll_set,
	.disable = nv50_devinit_disable,
};

int
nv50_devinit_new(struct nvkm_device *device, int index,
		 struct nvkm_devinit **pinit)
{
	return nv50_devinit_new_(&nv50_devinit, device, index, pinit);
}