[Openchrome-devel] drm-openchrome: drivers/gpu/drm

James Simmons jsimmons at kemper.freedesktop.org
Sat Dec 22 10:00:35 PST 2012


 drivers/gpu/drm/via/via_analog.c  |   10 -
 drivers/gpu/drm/via/via_display.c |   12 +
 drivers/gpu/drm/via/via_lvds.c    |  278 ++++++++++++++++++++------------------
 3 files changed, 165 insertions(+), 135 deletions(-)

New commits:
commit 97c3881e090532422e4171610bc524d82a51920c
Author: James Simmons <jsimmons at infradead.org>
Date:   Sat Dec 22 13:00:13 2012 -0500

    On initial boot up the LVDS connectors had mode list but once the X org driver starts the connectors no longer have modes listed. Thus via_lcd_get_modes must generate the modes belonging to the connector each time. This always non EDID LVDS to function properly. The via_lcd_detect also had the same problem which was addressed. Sync polarity handling was introduced for TTL as well in this patch.

diff --git a/drivers/gpu/drm/via/via_analog.c b/drivers/gpu/drm/via/via_analog.c
index 1ea889d..221502d 100644
--- a/drivers/gpu/drm/via/via_analog.c
+++ b/drivers/gpu/drm/via/via_analog.c
@@ -163,22 +163,22 @@ via_analog_init(struct drm_device *dev)
 	enc = par;
 
 	/* Piece together our connector */
-	con->ddc_bus = via_find_ddc_bus(0x26);
 	drm_connector_init(dev, &con->base, &via_analog_connector_funcs,
 				DRM_MODE_CONNECTOR_VGA);
 	drm_connector_helper_add(&con->base, &via_analog_connector_helper_funcs);
+	drm_sysfs_connector_add(&con->base);
 
-	con->base.interlace_allowed = true;
+	con->ddc_bus = via_find_ddc_bus(0x26);
 	con->base.doublescan_allowed = false;
+	con->base.interlace_allowed = true;
 
 	/* Setup the encoders and attach them */
 	drm_encoder_init(dev, &enc->base, &via_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
 	drm_encoder_helper_add(&enc->base, &via_dac_enc_helper_funcs);
-	enc->base.possible_clones = 0;
+
 	enc->base.possible_crtcs = BIT(1) | BIT(0);
+	enc->base.possible_clones = 0;
 	enc->diPort = DISP_DI_DAC;
 
 	drm_mode_connector_attach_encoder(&con->base, &enc->base);
-
-	drm_sysfs_connector_add(&con->base);
 }
diff --git a/drivers/gpu/drm/via/via_display.c b/drivers/gpu/drm/via/via_display.c
index 6b257c6..3bf99a9 100644
--- a/drivers/gpu/drm/via/via_display.c
+++ b/drivers/gpu/drm/via/via_display.c
@@ -238,6 +238,12 @@ via_set_sync_polarity(struct drm_encoder *encoder, struct drm_display_mode *mode
 		svga_wcrt_mask(VGABASE, 0x99, syncreg, BIT(6) | BIT(5));
 		break;
 
+	/* For TTL Type LCD */
+	case (DISP_DI_DFPL + DISP_DI_DVP1):
+		svga_wcrt_mask(VGABASE, 0x99, syncreg, BIT(6) | BIT(5));
+		svga_wcrt_mask(VGABASE, 0x9B, syncreg, BIT(6) | BIT(5));
+		break;
+
 	default:
 		DRM_ERROR("No DIPort.\n");
 		break;
@@ -420,7 +426,7 @@ via_display_init(struct drm_device *dev)
 	struct drm_via_private *dev_priv = dev->dev_private;
 	u8 index = 0x3D, value;
 
-	/* Check if spread spectrum is enable */
+	/* Check if spread spectrum is enabled */
 	if (dev->pci_device == PCI_DEVICE_ID_VIA_VX900)
 		index = 0x2C;
 
@@ -436,10 +442,10 @@ via_display_init(struct drm_device *dev)
 	} else
 		dev_priv->spread_spectrum = false;
 
-	/* load fixed CRTC timing registers */
+	/* Load fixed CRTC timing registers */
 	via_init_crtc_regs(dev);
 
-	/* 3. Init TD timing register (power sequence) */
+	/* Init TD timing register (power sequence) */
 	via_init_td_timing_regs(dev);
 
 	/* I/O address bit to be 1. Enable access */
diff --git a/drivers/gpu/drm/via/via_lvds.c b/drivers/gpu/drm/via/via_lvds.c
index ea5c847..7034000 100644
--- a/drivers/gpu/drm/via/via_lvds.c
+++ b/drivers/gpu/drm/via/via_lvds.c
@@ -74,7 +74,6 @@ via_enable_internal_lvds(struct drm_encoder *encoder)
 
 	/* Turn on LCD panel */
 	if ((enc->diPort & DISP_DI_DFPL) || (enc->diPort == DISP_DI_DVP1)) {
-		/* Software control power sequence */
 		if ((dev->pci_device == PCI_DEVICE_ID_VIA_VT1122) ||
 		    (dev->pci_device == PCI_DEVICE_ID_VIA_CLE266)) {
 			/* Software control power sequence ON */
@@ -356,7 +355,9 @@ via_lcd_detect(struct drm_connector *connector,  bool force)
 		kfree(edid);
 		return connector_status_connected;
 	} else {
-		if (!list_empty(&connector->probed_modes))
+		struct drm_via_private *dev_priv = connector->dev->dev_private;
+
+		if (vga_rcrt(VGABASE, 0x3B) & BIT(1))
 			return connector_status_connected;
 	}
 	return connector_status_disconnected;
@@ -421,21 +422,142 @@ struct drm_connector_funcs via_lcd_connector_funcs = {
 	.destroy = via_connector_destroy,
 };
 
-int via_lcd_get_modes(struct drm_connector *connector)
+static int
+via_lcd_get_modes(struct drm_connector *connector)
 {
 	int count = via_get_edid_modes(connector);
 
+	/* If no edid then we detect the mode using
+	 * the scratch pad registers. */
 	if (!count) {
-		struct drm_display_mode *tmp, *t;
+		struct drm_display_mode *native_mode = NULL;
+		struct drm_device *dev = connector->dev;
+
+		/* OLPC is very special */
+		if (machine_is_olpc()) {
+			native_mode = drm_mode_create(dev);
+
+			native_mode->clock = 56519;
+			native_mode->hdisplay = 1200;
+			native_mode->hsync_start = 1211;
+			native_mode->hsync_end = 1243;
+			native_mode->htotal = 1264;
+			native_mode->hskew = 0;
+			native_mode->vdisplay = 900;
+			native_mode->vsync_start = 901;
+			native_mode->vsync_end = 911;
+			native_mode->vtotal = 912;
+			native_mode->vscan = 0;
+			native_mode->vrefresh = 50;
+			native_mode->hsync = 0;
+		} else {
+			struct drm_via_private *dev_priv = dev->dev_private;
+			u8 reg_value = (vga_rcrt(VGABASE, 0x3F) & 0x0F);
+			int hdisplay = 0, vdisplay = 0;
+
+			switch (reg_value) {
+			case 0x00:
+				hdisplay = 640;
+				vdisplay = 480;
+				break;
+
+			case 0x01:
+				hdisplay = 800;
+				vdisplay = 600;
+				break;
+
+			case 0x02:
+				hdisplay = 1024;
+				vdisplay = 768;
+				break;
+
+			case 0x03:
+				hdisplay = 1280;
+				vdisplay = 768;
+				break;
+
+			case 0x04:
+				hdisplay = 1280;
+				vdisplay = 1024;
+				break;
 
-		list_for_each_entry_safe(tmp, t, &connector->probed_modes, head)
-			count++;
+			case 0x05:
+				hdisplay = 1400;
+				vdisplay = 1050;
+				break;
+
+			case 0x06:
+				hdisplay = 1440;
+				vdisplay = 900;
+				break;
+
+			case 0x07:
+				hdisplay = 1280;
+				vdisplay = 800;
+				break;
+
+			case 0x08:
+				hdisplay = 800;
+				vdisplay = 480;
+				break;
+
+			case 0x09:
+				hdisplay = 1024;
+				vdisplay = 600;
+				break;
+
+			case 0x0A:
+				hdisplay = 1366;
+				vdisplay = 768;
+				break;
+
+			case 0x0B:
+				hdisplay = 1600;
+				vdisplay = 1200;
+				break;
+
+			case 0x0C:
+				hdisplay = 1280;
+				vdisplay = 768;
+				break;
+
+			case 0x0D:
+				hdisplay = 1280;
+				vdisplay = 1024;
+				break;
+
+			case 0x0E:
+				hdisplay = 1600;
+				vdisplay = 1200;
+				break;
+
+			case 0x0F:
+				hdisplay = 480;
+				vdisplay = 640;
+				break;
+
+			default:
+				break;
+			}
+
+			if (hdisplay && vdisplay)
+				native_mode = drm_cvt_mode(dev, hdisplay, vdisplay,
+							60, false, false, false);
+		}
+
+		if (native_mode) {
+			native_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+			drm_mode_set_name(native_mode);
+			drm_mode_probed_add(connector, native_mode);
+			count = 1;
+		}
 	}
 	return count;
 }
 
-int via_lcd_mode_valid(struct drm_connector *connector,
-                struct drm_display_mode *mode)
+static int
+via_lcd_mode_valid(struct drm_connector *connector,
+			struct drm_display_mode *mode)
 {
 	struct drm_property *prop = connector->dev->mode_config.scaling_mode_property;
 	struct drm_display_mode *native_mode = NULL, *tmp, *t;
@@ -474,6 +596,7 @@ int via_lcd_mode_valid(struct drm_connector *connector,
 		if ((mode->hdisplay > native_mode->hdisplay) &&
 		    (mode->vdisplay < native_mode->vdisplay))
 			return MODE_PANEL;
+
 		if ((mode->hdisplay < native_mode->hdisplay) &&
 		    (mode->vdisplay > native_mode->vdisplay))
 			return MODE_PANEL;
@@ -516,17 +639,20 @@ via_lvds_init(struct drm_device *dev)
 	struct via_encoder *enc;
 	struct edid *edid;
 	u8 reg_value;
+	void *par;
 
-	con = kzalloc(sizeof(*con), GFP_KERNEL);
-	if (!con) {
-		DRM_INFO("allocate the connector error\n");
+	par = kzalloc(sizeof(*enc) + sizeof(*con), GFP_KERNEL);
+	if (!par) {
+		DRM_INFO("Failed to allocate LVDS output\n");
 		return;
 	}
-	con->base.interlace_allowed = false;
-	con->base.doublescan_allowed = false;
+	con = par + sizeof(*enc);
+	enc = par;
+
 	drm_connector_init(dev, &con->base, &via_lcd_connector_funcs,
 				DRM_MODE_CONNECTOR_LVDS);
 	drm_connector_helper_add(&con->base, &via_lcd_connector_helper_funcs);
+	drm_sysfs_connector_add(&con->base);
 
 	switch (dev->pci_device) {
 	case PCI_DEVICE_ID_VIA_VX875:
@@ -540,28 +666,7 @@ via_lvds_init(struct drm_device *dev)
 
 	edid = drm_get_edid(&con->base, con->ddc_bus);
 	if (!edid) {
-		struct drm_display_mode *native_mode = NULL;
-
-		/* OLPC is very special */
-		if (machine_is_olpc()) {
-			native_mode = drm_mode_create(dev);
-
-			native_mode->clock = 56519;
-			native_mode->hdisplay = 1200;
-			native_mode->hsync_start = 1211;
-			native_mode->hsync_end = 1243;
-			native_mode->htotal = 1264;
-			native_mode->hskew = 0;
-			native_mode->vdisplay = 900;
-			native_mode->vsync_start = 901;
-			native_mode->vsync_end = 911;
-			native_mode->vtotal = 912;
-			native_mode->vscan = 0;
-			native_mode->vrefresh = 50;
-			native_mode->hsync = 0;
-		} else {
-			int hdisplay = 0, vdisplay = 0;
-
+		if (!machine_is_olpc()) {
 			/* First we have to make sure a LVDS is present */
 			reg_value = (vga_rcrt(VGABASE, 0x3B) & BIT(1));
 			if (!reg_value)
@@ -571,111 +676,36 @@ via_lvds_init(struct drm_device *dev)
 			 * the scratch pad registers. */
 			reg_value = (vga_rcrt(VGABASE, 0x3F) & 0x0F);
 
-			DRM_DEBUG("panel index %x detected\n", reg_value);
 			switch (reg_value) {
-			case 0x00:
-				hdisplay = 640;
-				vdisplay = 480;
-				break;
-
-			case 0x01:
-				hdisplay = 800;
-				vdisplay = 600;
-				break;
-
-			case 0x02:
-				hdisplay = 1024;
-				vdisplay = 768;
-				break;
-
-			case 0x03:
-				hdisplay = 1152;
-				vdisplay = 864;
-				break;
-
 			case 0x04:
-				dual_channel = true;
-				hdisplay = 1280;
-				vdisplay = 1024;
-				break;
-
 			case 0x05:
-				dual_channel = true;
-				hdisplay = 1400;
-				vdisplay = 1050;
-				break;
-
 			case 0x06:
-				dual_channel = true;
-				hdisplay = 1600;
-				vdisplay = 1200;
-				break;
-
-			case 0x08:
-				hdisplay = 800;
-				vdisplay = 480;
-				break;
-
 			case 0x09:
-				dual_channel = true;
-				hdisplay = 1024;
-				vdisplay = 768;
-				break;
-
-			case 0x0A:
-				hdisplay = 1368;
-				vdisplay = 768;
-				break;
-
 			case 0x0B:
-				dual_channel = true;
-				hdisplay = 1024;
-				vdisplay = 768;
-				break;
-
 			case 0x0D:
-				dual_channel = true;
-				hdisplay = 1280;
-				vdisplay = 1024;
-				break;
-
 			case 0x0E:
-				dual_channel = true;
-				hdisplay = 1400;
-				vdisplay = 1050;
-				break;
-
 			case 0x0F:
 				dual_channel = true;
-				hdisplay = 1600;
-				vdisplay = 1200;
 				break;
 
 			default:
 				break;
 			}
 
-			if (hdisplay && vdisplay)
-				native_mode = drm_cvt_mode(dev, hdisplay, vdisplay,
-							60, false, false, false);
+			DRM_DEBUG("panel index %x detected\n", reg_value);
 
 			if (reg_value < 0x0A)
 				dither = DRM_MODE_DITHERING_ON;
 		}
-		if (!native_mode)
-			goto no_device;
-
-		native_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
-		drm_mode_set_name(native_mode);
-		drm_mode_probed_add(&con->base, native_mode);
 	} else {
-		drm_mode_connector_update_edid_property(&con->base, edid);
-		kfree(edid);
-
 		/* 00 LVDS1 + LVDS2  10 = Dual channel. Other are reserved */
 		if ((vga_rseq(VGABASE, 0x13) >> 6) == 2)
 			dual_channel = true;
+
+		kfree(edid);
 	}
+	con->base.doublescan_allowed = false;
+	con->base.interlace_allowed = false;
 
 	drm_mode_create_scaling_mode_property(dev);
 	drm_object_attach_property(&con->base.base,
@@ -689,14 +719,11 @@ via_lvds_init(struct drm_device *dev)
 	via_lcd_set_property(&con->base, dev->mode_config.dithering_mode_property,
 				dither);
 
-	drm_sysfs_connector_add(&con->base);
-
 	/* Now setup the encoder */
-	enc = kzalloc(sizeof(*enc), GFP_KERNEL);
-	if (!enc) {
-		DRM_INFO("allocate the encoder error\n");
-		goto no_device;
-	}
+	drm_encoder_init(dev, &enc->base, &via_lvds_enc_funcs,
+				DRM_MODE_ENCODER_LVDS);
+	drm_encoder_helper_add(&enc->base, &via_lvds_helper_funcs);
+
 	enc->base.possible_crtcs = BIT(1) | BIT(0);
 
 	switch (dev->pci_device) {
@@ -733,14 +760,11 @@ via_lvds_init(struct drm_device *dev)
 	if (dual_channel)
 		enc->flags |= LVDS_DUAL_CHANNEL;
 
-	drm_encoder_init(dev, &enc->base, &via_lvds_enc_funcs,
-				DRM_MODE_ENCODER_LVDS);
-	drm_encoder_helper_add(&enc->base, &via_lvds_helper_funcs);
-
+	/* Put it all together */
 	drm_mode_connector_attach_encoder(&con->base, &enc->base);
 	return;
 
 no_device:
 	drm_connector_cleanup(&con->base);
-	kfree(con);
+	kfree(par);
 }


More information about the Openchrome-devel mailing list