diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-02-23 21:07:31 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-02-25 00:09:32 -0500 |
commit | 7f612d87f8b4b1ddbcee04264a93e5af7b9f21c7 (patch) | |
tree | 2424853fa26091abdfb946aecbcc4d6b78d24ce8 | |
parent | dc5bc4ed3815dfec2f3ecfbf6f7983440040fe22 (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.c | 87 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_display.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 40 |
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 | ||
744 | int | 744 | int |
745 | nouveau_connector_create(struct drm_device *dev, int index, int type) | 745 | nouveau_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 | ||
52 | int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type); | 52 | int 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); |