aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-05-31 23:32:42 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-07-12 19:41:51 -0400
commitd17f395cdcec39033a481f96d75e8b3d3c41d43a (patch)
treee95a22e58d680ed7cb25c3bec70282df5da31c38
parent2dfe36b1b6cb51ddfd2358774fd8f097528cfdd0 (diff)
drm/nouveau: move LVDS detection back to connector detect() time
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c202
1 files changed, 87 insertions, 115 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 149ed224c3cb..a8c44c9eedf6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -236,20 +236,6 @@ nouveau_connector_detect(struct drm_connector *connector)
236 struct nouveau_i2c_chan *i2c; 236 struct nouveau_i2c_chan *i2c;
237 int type, flags; 237 int type, flags;
238 238
239 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS)
240 nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
241 if (nv_encoder && nv_connector->native_mode) {
242 unsigned status = connector_status_connected;
243
244#if defined(CONFIG_ACPI_BUTTON) || \
245 (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
246 if (!nouveau_ignorelid && !acpi_lid_open())
247 status = connector_status_unknown;
248#endif
249 nouveau_connector_set_encoder(connector, nv_encoder);
250 return status;
251 }
252
253 /* Cleanup the previous EDID block. */ 239 /* Cleanup the previous EDID block. */
254 if (nv_connector->edid) { 240 if (nv_connector->edid) {
255 drm_mode_connector_update_edid_property(connector, NULL); 241 drm_mode_connector_update_edid_property(connector, NULL);
@@ -321,6 +307,67 @@ detect_analog:
321 return connector_status_disconnected; 307 return connector_status_disconnected;
322} 308}
323 309
310static enum drm_connector_status
311nouveau_connector_detect_lvds(struct drm_connector *connector)
312{
313 struct drm_device *dev = connector->dev;
314 struct drm_nouveau_private *dev_priv = dev->dev_private;
315 struct nouveau_connector *nv_connector = nouveau_connector(connector);
316 struct nouveau_encoder *nv_encoder = NULL;
317 enum drm_connector_status status = connector_status_disconnected;
318
319 /* Cleanup the previous EDID block. */
320 if (nv_connector->edid) {
321 drm_mode_connector_update_edid_property(connector, NULL);
322 kfree(nv_connector->edid);
323 nv_connector->edid = NULL;
324 }
325
326 nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
327 if (!nv_encoder)
328 return connector_status_disconnected;
329
330 if (!dev_priv->vbios.fp_no_ddc) {
331 status = nouveau_connector_detect(connector);
332 if (status == connector_status_connected)
333 goto out;
334 }
335
336 /* If no EDID found above, and the VBIOS indicates a hardcoded
337 * modeline is avalilable for the panel, set it as the panel's
338 * native mode and exit.
339 */
340 if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc ||
341 nv_encoder->dcb->lvdsconf.use_straps_for_mode)) {
342 status = connector_status_connected;
343 goto out;
344 }
345
346 /* Still nothing, some VBIOS images have a hardcoded EDID block
347 * stored for the panel stored in them.
348 */
349 if (!dev_priv->vbios.fp_no_ddc) {
350 struct edid *edid =
351 (struct edid *)nouveau_bios_embedded_edid(dev);
352 if (edid) {
353 nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
354 *(nv_connector->edid) = *edid;
355 status = connector_status_connected;
356 }
357 }
358
359out:
360#if defined(CONFIG_ACPI_BUTTON) || \
361 (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
362 if (status == connector_status_connected &&
363 !nouveau_ignorelid && !acpi_lid_open())
364 status = connector_status_unknown;
365#endif
366
367 drm_mode_connector_update_edid_property(connector, nv_connector->edid);
368 return status;
369}
370
324static void 371static void
325nouveau_connector_force(struct drm_connector *connector) 372nouveau_connector_force(struct drm_connector *connector)
326{ 373{
@@ -534,21 +581,28 @@ static int
534nouveau_connector_get_modes(struct drm_connector *connector) 581nouveau_connector_get_modes(struct drm_connector *connector)
535{ 582{
536 struct drm_device *dev = connector->dev; 583 struct drm_device *dev = connector->dev;
584 struct drm_nouveau_private *dev_priv = dev->dev_private;
537 struct nouveau_connector *nv_connector = nouveau_connector(connector); 585 struct nouveau_connector *nv_connector = nouveau_connector(connector);
538 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; 586 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
587 struct drm_display_mode mode;
539 int ret = 0; 588 int ret = 0;
540 589
541 /* If we're not LVDS, destroy the previous native mode, the attached 590 /* destroy the native mode, the attached monitor could have changed.
542 * monitor could have changed.
543 */ 591 */
544 if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS && 592 if (nv_connector->native_mode) {
545 nv_connector->native_mode) {
546 drm_mode_destroy(dev, nv_connector->native_mode); 593 drm_mode_destroy(dev, nv_connector->native_mode);
547 nv_connector->native_mode = NULL; 594 nv_connector->native_mode = NULL;
548 } 595 }
549 596
550 if (nv_connector->edid) 597 if (nv_connector->edid)
551 ret = drm_add_edid_modes(connector, nv_connector->edid); 598 ret = drm_add_edid_modes(connector, nv_connector->edid);
599 else
600 if (nv_encoder->dcb->type == OUTPUT_LVDS &&
601 (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
602 dev_priv->vbios.fp_no_ddc) &&
603 nouveau_bios_fp_mode(dev, &mode)) {
604 nv_connector->native_mode = drm_mode_duplicate(dev, &mode);
605 }
552 606
553 /* Find the native mode if this is a digital panel, if we didn't 607 /* Find the native mode if this is a digital panel, if we didn't
554 * find any modes through DDC previously add the native mode to 608 * find any modes through DDC previously add the native mode to
@@ -662,99 +716,28 @@ nouveau_connector_funcs = {
662 .force = nouveau_connector_force 716 .force = nouveau_connector_force
663}; 717};
664 718
665static int 719static const struct drm_connector_funcs
666nouveau_connector_create_lvds(struct drm_device *dev, 720nouveau_connector_funcs_lvds = {
667 struct drm_connector *connector) 721 .dpms = drm_helper_connector_dpms,
668{ 722 .save = NULL,
669 struct nouveau_connector *nv_connector = nouveau_connector(connector); 723 .restore = NULL,
670 struct drm_nouveau_private *dev_priv = dev->dev_private; 724 .detect = nouveau_connector_detect_lvds,
671 struct nouveau_i2c_chan *i2c = NULL; 725 .destroy = nouveau_connector_destroy,
672 struct nouveau_encoder *nv_encoder; 726 .fill_modes = drm_helper_probe_single_connector_modes,
673 struct drm_display_mode native, *mode, *temp; 727 .set_property = nouveau_connector_set_property,
674 bool dummy, if_is_24bit = false; 728 .force = nouveau_connector_force
675 int ret, flags; 729};
676
677 nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
678 if (!nv_encoder)
679 return -ENODEV;
680
681 ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit);
682 if (ret) {
683 NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n");
684 return ret;
685 }
686 nv_connector->use_dithering = !if_is_24bit;
687
688 /* Firstly try getting EDID over DDC, if allowed and I2C channel
689 * is available.
690 */
691 if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
692 i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
693
694 if (i2c) {
695 nouveau_connector_ddc_prepare(connector, &flags);
696 nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
697 nouveau_connector_ddc_finish(connector, flags);
698 }
699
700 /* If no EDID found above, and the VBIOS indicates a hardcoded
701 * modeline is avalilable for the panel, set it as the panel's
702 * native mode and exit.
703 */
704 if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
705 (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
706 dev_priv->vbios.fp_no_ddc)) {
707 nv_connector->native_mode = drm_mode_duplicate(dev, &native);
708 goto out;
709 }
710
711 /* Still nothing, some VBIOS images have a hardcoded EDID block
712 * stored for the panel stored in them.
713 */
714 if (!nv_connector->edid && !nv_connector->native_mode &&
715 !dev_priv->vbios.fp_no_ddc) {
716 struct edid *edid =
717 (struct edid *)nouveau_bios_embedded_edid(dev);
718 if (edid) {
719 nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
720 *(nv_connector->edid) = *edid;
721 }
722 }
723
724 if (!nv_connector->edid)
725 goto out;
726
727 /* We didn't find/use a panel mode from the VBIOS, so parse the EDID
728 * block and look for the preferred mode there.
729 */
730 ret = drm_add_edid_modes(connector, nv_connector->edid);
731 if (ret == 0)
732 goto out;
733 nv_connector->detected_encoder = nv_encoder;
734 nv_connector->native_mode = nouveau_connector_native_mode(connector);
735 list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
736 drm_mode_remove(connector, mode);
737
738out:
739 if (!nv_connector->native_mode) {
740 NV_ERROR(dev, "LVDS present in DCB table, but couldn't "
741 "determine its native mode. Disabling.\n");
742 return -ENODEV;
743 }
744
745 drm_mode_connector_update_edid_property(connector, nv_connector->edid);
746 return 0;
747}
748 730
749int 731int
750nouveau_connector_create(struct drm_device *dev, 732nouveau_connector_create(struct drm_device *dev,
751 struct dcb_connector_table_entry *dcb) 733 struct dcb_connector_table_entry *dcb)
752{ 734{
735 const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
753 struct drm_nouveau_private *dev_priv = dev->dev_private; 736 struct drm_nouveau_private *dev_priv = dev->dev_private;
754 struct nouveau_connector *nv_connector = NULL; 737 struct nouveau_connector *nv_connector = NULL;
755 struct drm_connector *connector; 738 struct drm_connector *connector;
756 struct drm_encoder *encoder; 739 struct drm_encoder *encoder;
757 int ret, type; 740 int type;
758 741
759 NV_DEBUG_KMS(dev, "\n"); 742 NV_DEBUG_KMS(dev, "\n");
760 743
@@ -787,6 +770,7 @@ nouveau_connector_create(struct drm_device *dev,
787 case DCB_CONNECTOR_LVDS: 770 case DCB_CONNECTOR_LVDS:
788 NV_INFO(dev, "Detected a LVDS connector\n"); 771 NV_INFO(dev, "Detected a LVDS connector\n");
789 type = DRM_MODE_CONNECTOR_LVDS; 772 type = DRM_MODE_CONNECTOR_LVDS;
773 funcs = &nouveau_connector_funcs_lvds;
790 break; 774 break;
791 case DCB_CONNECTOR_DP: 775 case DCB_CONNECTOR_DP:
792 NV_INFO(dev, "Detected a DisplayPort connector\n"); 776 NV_INFO(dev, "Detected a DisplayPort connector\n");
@@ -811,7 +795,7 @@ nouveau_connector_create(struct drm_device *dev,
811 connector->interlace_allowed = false; 795 connector->interlace_allowed = false;
812 connector->doublescan_allowed = false; 796 connector->doublescan_allowed = false;
813 797
814 drm_connector_init(dev, connector, &nouveau_connector_funcs, type); 798 drm_connector_init(dev, connector, funcs, type);
815 drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); 799 drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
816 800
817 /* attach encoders */ 801 /* attach encoders */
@@ -841,9 +825,6 @@ nouveau_connector_create(struct drm_device *dev,
841 drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); 825 drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
842 } 826 }
843 827
844 if (dcb->type != DCB_CONNECTOR_LVDS)
845 nv_connector->use_dithering = false;
846
847 switch (dcb->type) { 828 switch (dcb->type) {
848 case DCB_CONNECTOR_VGA: 829 case DCB_CONNECTOR_VGA:
849 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 830 connector->polled = DRM_CONNECTOR_POLL_CONNECT;
@@ -883,14 +864,5 @@ nouveau_connector_create(struct drm_device *dev,
883 } 864 }
884 865
885 drm_sysfs_connector_add(connector); 866 drm_sysfs_connector_add(connector);
886
887 if (dcb->type == DCB_CONNECTOR_LVDS) {
888 ret = nouveau_connector_create_lvds(dev, connector);
889 if (ret) {
890 connector->funcs->destroy(connector);
891 return ret;
892 }
893 }
894
895 return 0; 867 return 0;
896} 868}