drm/nv04-nv40: Disable connector polling when there're no spare CRTCs left.

Load detection needs the connector wired to a CRTC, when there are no
inactive CRTCs left that means we need to cut some other head off for
a while, causing intermittent flickering.

Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 13f2e1e..c2524ca 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -698,6 +698,44 @@
 	return NULL;
 }
 
+void
+nouveau_connector_set_polling(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	bool spare_crtc = false;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		spare_crtc |= !crtc->enabled;
+
+	connector->polled = 0;
+
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_VGA:
+	case DRM_MODE_CONNECTOR_TV:
+		if (dev_priv->card_type >= NV_50 ||
+		    (nv_gf4_disp_arch(dev) && spare_crtc))
+			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+		break;
+
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_DVID:
+	case DRM_MODE_CONNECTOR_HDMIA:
+	case DRM_MODE_CONNECTOR_DisplayPort:
+	case DRM_MODE_CONNECTOR_eDP:
+		if (dev_priv->card_type >= NV_50)
+			connector->polled = DRM_CONNECTOR_POLL_HPD;
+		else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
+			 spare_crtc)
+			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+		break;
+
+	default:
+		break;
+	}
+}
+
 static const struct drm_connector_helper_funcs
 nouveau_connector_helper_funcs = {
 	.get_modes = nouveau_connector_get_modes,
@@ -818,7 +856,6 @@
 
 	switch (dcb->type) {
 	case DCB_CONNECTOR_VGA:
-		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 		if (dev_priv->card_type >= NV_50) {
 			drm_connector_attach_property(connector,
 					dev->mode_config.scaling_mode_property,
@@ -830,17 +867,6 @@
 	case DCB_CONNECTOR_TV_3:
 		nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
 		break;
-	case DCB_CONNECTOR_DP:
-	case DCB_CONNECTOR_eDP:
-	case DCB_CONNECTOR_HDMI_0:
-	case DCB_CONNECTOR_HDMI_1:
-	case DCB_CONNECTOR_DVI_I:
-	case DCB_CONNECTOR_DVI_D:
-		if (dev_priv->card_type >= NV_50)
-			connector->polled = DRM_CONNECTOR_POLL_HPD;
-		else
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
-		/* fall-through */
 	default:
 		nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
 
@@ -854,6 +880,8 @@
 		break;
 	}
 
+	nouveau_connector_set_polling(connector);
+
 	drm_sysfs_connector_add(connector);
 	dcb->drm = connector;
 	return dcb->drm;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 1ce3d91..0d2e668 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -52,4 +52,7 @@
 struct drm_connector *
 nouveau_connector_create(struct drm_device *, int index);
 
+void
+nouveau_connector_set_polling(struct drm_connector *);
+
 #endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index eba687f1..1c20c08 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -157,6 +157,7 @@
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
 	unsigned char seq1 = 0, crtc17 = 0;
 	unsigned char crtc1A;
 
@@ -211,6 +212,10 @@
 	NVVgaSeqReset(dev, nv_crtc->index, false);
 
 	NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
+
+	/* Update connector polling modes */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		nouveau_connector_set_polling(connector);
 }
 
 static bool