aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-02-23 21:07:31 -0500
committerBen Skeggs <bskeggs@redhat.com>2010-02-25 00:09:32 -0500
commit7f612d87f8b4b1ddbcee04264a93e5af7b9f21c7 (patch)
tree2424853fa26091abdfb946aecbcc4d6b78d24ce8
parentdc5bc4ed3815dfec2f3ecfbf6f7983440040fe22 (diff)
drm/nouveau: use dcb connector table for creating drm connectors
This makes this code common to both the nv04 and nv50 paths. For the moment, we keep the previous behaviour with HDMI/eDP connectors and report them as DVI-D/DP instead. This will be fixed once the rest of the code has been fixed to deal with those types. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c87
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h3
-rw-r--r--drivers/gpu/drm/nouveau/nv04_display.c47
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c40
4 files changed, 62 insertions, 115 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 36a9692c4654..9d118737f88f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -742,46 +742,60 @@ out:
742} 742}
743 743
744int 744int
745nouveau_connector_create(struct drm_device *dev, int index, int type) 745nouveau_connector_create(struct drm_device *dev,
746 struct dcb_connector_table_entry *dcb)
746{ 747{
747 struct drm_nouveau_private *dev_priv = dev->dev_private; 748 struct drm_nouveau_private *dev_priv = dev->dev_private;
748 struct nouveau_connector *nv_connector = NULL; 749 struct nouveau_connector *nv_connector = NULL;
749 struct drm_connector *connector; 750 struct drm_connector *connector;
750 struct drm_encoder *encoder; 751 struct drm_encoder *encoder;
751 int ret; 752 int ret, type;
752 753
753 NV_DEBUG_KMS(dev, "\n"); 754 NV_DEBUG_KMS(dev, "\n");
754 755
755 nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); 756 switch (dcb->type) {
756 if (!nv_connector) 757 case DCB_CONNECTOR_NONE:
757 return -ENOMEM; 758 return 0;
758 nv_connector->dcb = nouveau_bios_connector_entry(dev, index); 759 case DCB_CONNECTOR_VGA:
759 connector = &nv_connector->base;
760
761 switch (type) {
762 case DRM_MODE_CONNECTOR_VGA:
763 NV_INFO(dev, "Detected a VGA connector\n"); 760 NV_INFO(dev, "Detected a VGA connector\n");
761 type = DRM_MODE_CONNECTOR_VGA;
764 break; 762 break;
765 case DRM_MODE_CONNECTOR_DVID: 763 case DCB_CONNECTOR_TV_0:
766 NV_INFO(dev, "Detected a DVI-D connector\n"); 764 case DCB_CONNECTOR_TV_1:
765 case DCB_CONNECTOR_TV_3:
766 NV_INFO(dev, "Detected a TV connector\n");
767 type = DRM_MODE_CONNECTOR_TV;
767 break; 768 break;
768 case DRM_MODE_CONNECTOR_DVII: 769 case DCB_CONNECTOR_DVI_I:
769 NV_INFO(dev, "Detected a DVI-I connector\n"); 770 NV_INFO(dev, "Detected a DVI-I connector\n");
771 type = DRM_MODE_CONNECTOR_DVII;
770 break; 772 break;
771 case DRM_MODE_CONNECTOR_LVDS: 773 case DCB_CONNECTOR_DVI_D:
772 NV_INFO(dev, "Detected a LVDS connector\n"); 774 case DCB_CONNECTOR_HDMI_0:
775 case DCB_CONNECTOR_HDMI_1:
776 NV_INFO(dev, "Detected a DVI-D connector\n");
777 type = DRM_MODE_CONNECTOR_DVID;
773 break; 778 break;
774 case DRM_MODE_CONNECTOR_TV: 779 case DCB_CONNECTOR_LVDS:
775 NV_INFO(dev, "Detected a TV connector\n"); 780 NV_INFO(dev, "Detected a LVDS connector\n");
781 type = DRM_MODE_CONNECTOR_LVDS;
776 break; 782 break;
777 case DRM_MODE_CONNECTOR_DisplayPort: 783 case DCB_CONNECTOR_DP:
784 case DCB_CONNECTOR_eDP:
778 NV_INFO(dev, "Detected a DisplayPort connector\n"); 785 NV_INFO(dev, "Detected a DisplayPort connector\n");
786 type = DRM_MODE_CONNECTOR_DisplayPort;
779 break; 787 break;
780 default: 788 default:
781 NV_ERROR(dev, "Unknown connector, this is not good.\n"); 789 NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
782 break; 790 return -EINVAL;
783 } 791 }
784 792
793 nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
794 if (!nv_connector)
795 return -ENOMEM;
796 nv_connector->dcb = dcb;
797 connector = &nv_connector->base;
798
785 /* defaults, will get overridden in detect() */ 799 /* defaults, will get overridden in detect() */
786 connector->interlace_allowed = false; 800 connector->interlace_allowed = false;
787 connector->doublescan_allowed = false; 801 connector->doublescan_allowed = false;
@@ -789,6 +803,26 @@ nouveau_connector_create(struct drm_device *dev, int index, int type)
789 drm_connector_init(dev, connector, &nouveau_connector_funcs, type); 803 drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
790 drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); 804 drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
791 805
806 /* attach encoders */
807 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
808 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
809
810 if (nv_encoder->dcb->connector != dcb->index)
811 continue;
812
813 if (get_slave_funcs(nv_encoder))
814 get_slave_funcs(nv_encoder)->create_resources(encoder, connector);
815
816 drm_mode_connector_attach_encoder(connector, encoder);
817 }
818
819 if (!connector->encoder_ids[0]) {
820 NV_WARN(dev, " no encoders, ignoring\n");
821 drm_connector_cleanup(connector);
822 kfree(connector);
823 return 0;
824 }
825
792 /* Init DVI-I specific properties */ 826 /* Init DVI-I specific properties */
793 if (type == DRM_MODE_CONNECTOR_DVII) { 827 if (type == DRM_MODE_CONNECTOR_DVII) {
794 drm_mode_create_dvi_i_properties(dev); 828 drm_mode_create_dvi_i_properties(dev);
@@ -822,19 +856,6 @@ nouveau_connector_create(struct drm_device *dev, int index, int type)
822 } 856 }
823 } 857 }
824 858
825 /* attach encoders */
826 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
827 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
828
829 if (nv_encoder->dcb->connector != index)
830 continue;
831
832 if (get_slave_funcs(nv_encoder))
833 get_slave_funcs(nv_encoder)->create_resources(encoder, connector);
834
835 drm_mode_connector_attach_encoder(connector, encoder);
836 }
837
838 drm_sysfs_connector_add(connector); 859 drm_sysfs_connector_add(connector);
839 860
840 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { 861 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 728b8090e5ff..4ef38abc2d9c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -49,6 +49,7 @@ static inline struct nouveau_connector *nouveau_connector(
49 return container_of(con, struct nouveau_connector, base); 49 return container_of(con, struct nouveau_connector, base);
50} 50}
51 51
52int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type); 52int nouveau_connector_create(struct drm_device *,
53 struct dcb_connector_table_entry *);
53 54
54#endif /* __NOUVEAU_CONNECTOR_H__ */ 55#endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c
index 76060f4423f4..c7898b4f6dfb 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/nv04_display.c
@@ -96,7 +96,6 @@ nv04_display_create(struct drm_device *dev)
96 struct dcb_table *dcb = &dev_priv->vbios.dcb; 96 struct dcb_table *dcb = &dev_priv->vbios.dcb;
97 struct drm_encoder *encoder; 97 struct drm_encoder *encoder;
98 struct drm_crtc *crtc; 98 struct drm_crtc *crtc;
99 uint16_t connector[16] = { 0 };
100 int i, ret; 99 int i, ret;
101 100
102 NV_DEBUG_KMS(dev, "\n"); 101 NV_DEBUG_KMS(dev, "\n");
@@ -154,52 +153,10 @@ nv04_display_create(struct drm_device *dev)
154 153
155 if (ret) 154 if (ret)
156 continue; 155 continue;
157
158 connector[dcbent->connector] |= (1 << dcbent->type);
159 } 156 }
160 157
161 for (i = 0; i < dcb->entries; i++) { 158 for (i = 0; i < dcb->connector.entries; i++)
162 struct dcb_entry *dcbent = &dcb->entry[i]; 159 nouveau_connector_create(dev, &dcb->connector.entry[i]);
163 uint16_t encoders;
164 int type;
165
166 encoders = connector[dcbent->connector];
167 if (!(encoders & (1 << dcbent->type)))
168 continue;
169 connector[dcbent->connector] = 0;
170
171 switch (dcbent->type) {
172 case OUTPUT_ANALOG:
173 if (!MULTIPLE_ENCODERS(encoders))
174 type = DRM_MODE_CONNECTOR_VGA;
175 else
176 type = DRM_MODE_CONNECTOR_DVII;
177 break;
178 case OUTPUT_TMDS:
179 if (!MULTIPLE_ENCODERS(encoders))
180 type = DRM_MODE_CONNECTOR_DVID;
181 else
182 type = DRM_MODE_CONNECTOR_DVII;
183 break;
184 case OUTPUT_LVDS:
185 type = DRM_MODE_CONNECTOR_LVDS;
186#if 0
187 /* don't create i2c adapter when lvds ddc not allowed */
188 if (dcbent->lvdsconf.use_straps_for_mode ||
189 dev_priv->vbios->fp_no_ddc)
190 i2c_index = 0xf;
191#endif
192 break;
193 case OUTPUT_TV:
194 type = DRM_MODE_CONNECTOR_TV;
195 break;
196 default:
197 type = DRM_MODE_CONNECTOR_Unknown;
198 continue;
199 }
200
201 nouveau_connector_create(dev, dcbent->connector, type);
202 }
203 160
204 /* Save previous state */ 161 /* Save previous state */
205 NVLockVgaCrtcs(dev, false); 162 NVLockVgaCrtcs(dev, false);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index c406be6fdc5f..ebcd8bf2406f 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -466,7 +466,6 @@ int nv50_display_create(struct drm_device *dev)
466{ 466{
467 struct drm_nouveau_private *dev_priv = dev->dev_private; 467 struct drm_nouveau_private *dev_priv = dev->dev_private;
468 struct dcb_table *dcb = &dev_priv->vbios.dcb; 468 struct dcb_table *dcb = &dev_priv->vbios.dcb;
469 uint32_t connector[16] = {};
470 int ret, i; 469 int ret, i;
471 470
472 NV_DEBUG_KMS(dev, "\n"); 471 NV_DEBUG_KMS(dev, "\n");
@@ -522,44 +521,13 @@ int nv50_display_create(struct drm_device *dev)
522 NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); 521 NV_WARN(dev, "DCB encoder %d unknown\n", entry->type);
523 continue; 522 continue;
524 } 523 }
525
526 connector[entry->connector] |= (1 << entry->type);
527 } 524 }
528 525
529 /* It appears that DCB 3.0+ vbios has a connector table, however, 526 for (i = 0 ; i < dcb->connector.entries; i++) {
530 * I'm not 100% certain how to decode it correctly yet so just 527 if (i != 0 && dcb->connector.entry[i].index ==
531 * look at what encoders are present on each connector index and 528 dcb->connector.entry[i - 1].index)
532 * attempt to derive the connector type from that.
533 */
534 for (i = 0 ; i < dcb->entries; i++) {
535 struct dcb_entry *entry = &dcb->entry[i];
536 uint16_t encoders;
537 int type;
538
539 encoders = connector[entry->connector];
540 if (!(encoders & (1 << entry->type)))
541 continue; 529 continue;
542 connector[entry->connector] = 0; 530 nouveau_connector_create(dev, &dcb->connector.entry[i]);
543
544 if (encoders & (1 << OUTPUT_DP)) {
545 type = DRM_MODE_CONNECTOR_DisplayPort;
546 } else if (encoders & (1 << OUTPUT_TMDS)) {
547 if (encoders & (1 << OUTPUT_ANALOG))
548 type = DRM_MODE_CONNECTOR_DVII;
549 else
550 type = DRM_MODE_CONNECTOR_DVID;
551 } else if (encoders & (1 << OUTPUT_ANALOG)) {
552 type = DRM_MODE_CONNECTOR_VGA;
553 } else if (encoders & (1 << OUTPUT_LVDS)) {
554 type = DRM_MODE_CONNECTOR_LVDS;
555 } else {
556 type = DRM_MODE_CONNECTOR_Unknown;
557 }
558
559 if (type == DRM_MODE_CONNECTOR_Unknown)
560 continue;
561
562 nouveau_connector_create(dev, entry->connector, type);
563 } 531 }
564 532
565 ret = nv50_display_init(dev); 533 ret = nv50_display_init(dev);