[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