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 <jsimm...@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); } _______________________________________________ Openchrome-devel mailing list Openchrome-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/openchrome-devel