Exemple #1
0
static void
nv50_sor_dp_link_train(struct drm_encoder *encoder)
{
	struct drm_device *dev = encoder->dev;
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct bit_displayport_encoder_table *dpe;
	int dpe_headerlen;

	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
	if (!dpe) {
		NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
		return;
	}

	if (dpe->script0) {
		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
					    nv_encoder->dcb);
	}

	if (!nouveau_dp_link_train(encoder))
		NV_ERROR(dev, "SOR-%d: link training failed\n", nv_encoder->or);

	if (dpe->script1) {
		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
					    nv_encoder->dcb);
	}
}
Exemple #2
0
static enum drm_connector_status
nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct drm_device *dev = encoder->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	enum drm_connector_status status = connector_status_disconnected;
	uint32_t dpms_state, load_pattern, load_state;
	int or = nv_encoder->or;

	nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001);
	dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or));

	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
		0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
	if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
		NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
		NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
			  nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
		return status;
	}

	/* Use bios provided value if possible. */
	if (dev_priv->vbios.dactestval) {
		load_pattern = dev_priv->vbios.dactestval;
		NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n",
			  load_pattern);
	} else {
		load_pattern = 340;
		NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n",
			 load_pattern);
	}

	nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or),
		NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern);
	mdelay(45); /* give it some time to process */
	load_state = nv_rd32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or));

	nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0);
	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state |
		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);

	if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) ==
			  NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT)
		status = connector_status_connected;

	if (status == connector_status_connected)
		NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or);
	else
		NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or);

	return status;
}
Exemple #3
0
static void
nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
{
	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
	struct nouveau_channel *evo = dev_priv->evo;
	struct drm_device *dev = nv_crtc->base.dev;
	int ret;

	NV_DEBUG_KMS(dev, "\n");

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

	ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2);
	if (ret) {
		NV_ERROR(dev, "no space while hiding cursor\n");
		return;
	}
	BEGIN_RING(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 (dev_priv->chipset != 0x50) {
		BEGIN_RING(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1);
		OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE);
	}

	if (update) {
		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
		OUT_RING(evo, 0);
		FIRE_RING(evo);
		nv_crtc->cursor.visible = false;
	}
}
Exemple #4
0
static void
nv50_dac_disconnect(struct drm_encoder *encoder)
{
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct drm_device *dev = encoder->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *evo = dev_priv->evo;
	int ret;

	if (!nv_encoder->crtc)
		return;
	nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true);

	NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or);

	ret = RING_SPACE(evo, 4);
	if (ret) {
		NV_ERROR(dev, "no space while disconnecting DAC\n");
		return;
	}
	BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1);
	OUT_RING  (evo, 0);
	BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
	OUT_RING  (evo, 0);

	nv_encoder->crtc = NULL;
}
Exemple #5
0
static void
nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
		  struct drm_display_mode *adjusted_mode)
{
	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
	struct nouveau_channel *evo = dev_priv->evo;
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct drm_device *dev = encoder->dev;
	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
	uint32_t mode_ctl = 0;
	int ret;

	NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or);

	nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON);

	switch (nv_encoder->dcb->type) {
	case OUTPUT_TMDS:
		if (nv_encoder->dcb->sorconf.link & 1) {
			if (adjusted_mode->clock < 165000)
				mode_ctl = 0x0100;
			else
				mode_ctl = 0x0500;
		} else
			mode_ctl = 0x0200;
		break;
	case OUTPUT_DP:
		mode_ctl |= 0x00050000;
		if (nv_encoder->dcb->sorconf.link & 1)
			mode_ctl |= 0x00000800;
		else
			mode_ctl |= 0x00000900;
		break;
	default:
		break;
	}

	if (crtc->index == 1)
		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC1;
	else
		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0;

	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC;

	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
		mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC;

	ret = RING_SPACE(evo, 2);
	if (ret) {
		NV_ERROR(dev, "no space while connecting SOR\n");
		return;
	}
	BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
	OUT_RING(evo, mode_ctl);
}
Exemple #6
0
static void
nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset)
{
	NV_DEBUG_KMS(nv_crtc->base.dev, "\n");
	if (offset == nv_crtc->cursor.offset)
		return;

	nv_crtc->cursor.offset = offset;
	if (nv_crtc->cursor.visible) {
		nv_crtc->cursor.visible = false;
		nv_crtc->cursor.show(nv_crtc, true);
	}
}
Exemple #7
0
static void
nv50_dac_destroy(struct drm_encoder *encoder)
{
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);

	if (!encoder)
		return;

	NV_DEBUG_KMS(encoder->dev, "\n");

	drm_encoder_cleanup(encoder);
	kfree(nv_encoder);
}
Exemple #8
0
int
nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)
{
	struct nouveau_encoder *nv_encoder = NULL;
	struct drm_encoder *encoder;
	bool dum;
	int type;

	NV_DEBUG_KMS(dev, "\n");

	switch (entry->type) {
	case OUTPUT_TMDS:
		NV_INFO(dev, "Detected a TMDS output\n");
		type = DRM_MODE_ENCODER_TMDS;
		break;
	case OUTPUT_LVDS:
		NV_INFO(dev, "Detected a LVDS output\n");
		type = DRM_MODE_ENCODER_LVDS;

		if (nouveau_bios_parse_lvds_table(dev, 0, &dum, &dum)) {
			NV_ERROR(dev, "Failed parsing LVDS table\n");
			return -EINVAL;
		}
		break;
	case OUTPUT_DP:
		NV_INFO(dev, "Detected a DP output\n");
		type = DRM_MODE_ENCODER_TMDS;
		break;
	default:
		return -EINVAL;
	}

	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
	if (!nv_encoder)
		return -ENOMEM;
	encoder = to_drm_encoder(nv_encoder);

	nv_encoder->dcb = entry;
	nv_encoder->or = ffs(entry->or) - 1;

	nv_encoder->disconnect = nv50_sor_disconnect;

	drm_encoder_init(dev, encoder, &nv50_sor_encoder_funcs, type);
	drm_encoder_helper_add(encoder, &nv50_sor_helper_funcs);

	encoder->possible_crtcs = entry->heads;
	encoder->possible_clones = 0;

	return 0;
}
Exemple #9
0
void
nv50_cursor_fini(struct nouveau_crtc *nv_crtc)
{
	struct drm_device *dev = nv_crtc->base.dev;
	int idx = nv_crtc->index;

	NV_DEBUG_KMS(dev, "\n");

	nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0);
	if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx),
		     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) {
		NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n");
		NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n",
			 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx)));
	}
}
Exemple #10
0
static void
nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
		  struct drm_display_mode *adjusted_mode)
{
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct drm_device *dev = encoder->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *evo = dev_priv->evo;
	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
	uint32_t mode_ctl = 0, mode_ctl2 = 0;
	int ret;

	NV_DEBUG_KMS(dev, "or %d type %d crtc %d\n",
		     nv_encoder->or, nv_encoder->dcb->type, crtc->index);

	nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);

	if (crtc->index == 1)
		mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC1;
	else
		mode_ctl |= NV50_EVO_DAC_MODE_CTRL_CRTC0;

	/* Lacking a working tv-out, this is not a 100% sure. */
	if (nv_encoder->dcb->type == OUTPUT_ANALOG)
		mode_ctl |= 0x40;
	else
	if (nv_encoder->dcb->type == OUTPUT_TV)
		mode_ctl |= 0x100;

	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
		mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NHSYNC;

	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
		mode_ctl2 |= NV50_EVO_DAC_MODE_CTRL2_NVSYNC;

	ret = RING_SPACE(evo, 3);
	if (ret) {
		NV_ERROR(dev, "no space while connecting DAC\n");
		return;
	}
	BEGIN_RING(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2);
	OUT_RING(evo, mode_ctl);
	OUT_RING(evo, mode_ctl2);

	nv_encoder->crtc = encoder->crtc;
}
Exemple #11
0
static void
nv50_sor_disconnect(struct nouveau_encoder *nv_encoder)
{
	struct drm_device *dev = to_drm_encoder(nv_encoder)->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *evo = dev_priv->evo;
	int ret;

	NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or);

	ret = RING_SPACE(evo, 2);
	if (ret) {
		NV_ERROR(dev, "no space while disconnecting SOR\n");
		return;
	}
	BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1);
	OUT_RING(evo, 0);
}
Exemple #12
0
static void
nv50_dac_dpms(struct drm_encoder *encoder, int mode)
{
	struct drm_device *dev = encoder->dev;
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	uint32_t val;
	int or = nv_encoder->or;

	NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);

	/* wait for it to be done */
	if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or),
		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) {
		NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or);
		NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or,
			 nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)));
		return;
	}

	val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F;

	if (mode != DRM_MODE_DPMS_ON)
		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED;

	switch (mode) {
	case DRM_MODE_DPMS_STANDBY:
		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
		break;
	case DRM_MODE_DPMS_SUSPEND:
		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
		break;
	case DRM_MODE_DPMS_OFF:
		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_OFF;
		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF;
		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF;
		break;
	default:
		break;
	}

	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val |
		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING);
}
static void
nv50_crtc_lut_load(struct drm_crtc *crtc)
{
	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
	void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo);
	int i;

	NV_DEBUG_KMS(crtc->dev, "\n");

	for (i = 0; i < 256; i++) {
		writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0);
		writew(nv_crtc->lut.g[i] >> 2, lut + 8*i + 2);
		writew(nv_crtc->lut.b[i] >> 2, lut + 8*i + 4);
	}

	if (nv_crtc->lut.depth == 30) {
		writew(nv_crtc->lut.r[i - 1] >> 2, lut + 8*i + 0);
		writew(nv_crtc->lut.g[i - 1] >> 2, lut + 8*i + 2);
		writew(nv_crtc->lut.b[i - 1] >> 2, lut + 8*i + 4);
	}
static bool
nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
		    struct drm_display_mode *adjusted_mode)
{
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	struct nouveau_connector *connector;

	NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or);

	connector = nouveau_encoder_connector_get(nv_encoder);
	if (!connector) {
		NV_ERROR(encoder->dev, "Encoder has no connector\n");
		return false;
	}

	if (connector->scaling_mode != DRM_MODE_SCALE_NONE &&
	     connector->native_mode)
		drm_mode_copy(adjusted_mode, connector->native_mode);

	return true;
}
Exemple #15
0
static void
nv50_sor_dpms(struct drm_encoder *encoder, int mode)
{
	struct drm_device *dev = encoder->dev;
	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
	uint32_t val;
	int or = nv_encoder->or;

	NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode);

	/* wait for it to be done */
	if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or),
		     NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) {
		NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or);
		NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or,
			 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)));
	}

	val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or));

	if (mode == DRM_MODE_DPMS_ON)
		val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON;
	else
		val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON;

	nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val |
		NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING);
	if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_STATE(or),
		     NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) {
		NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or);
		NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or,
			 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or)));
	}

	if (nv_encoder->dcb->type == OUTPUT_DP && mode == DRM_MODE_DPMS_ON)
		nv50_sor_dp_link_train(encoder);
}