Skip to content

Commit

Permalink
drm/nouveau: use dcb connector table for creating drm connectors
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ben Skeggs committed Feb 25, 2010
1 parent dc5bc4e commit 7f612d8
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 115 deletions.
87 changes: 54 additions & 33 deletions drivers/gpu/drm/nouveau/nouveau_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,53 +742,87 @@ nouveau_connector_create_lvds(struct drm_device *dev,
}

int
nouveau_connector_create(struct drm_device *dev, int index, int type)
nouveau_connector_create(struct drm_device *dev,
struct dcb_connector_table_entry *dcb)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_connector *nv_connector = NULL;
struct drm_connector *connector;
struct drm_encoder *encoder;
int ret;
int ret, type;

NV_DEBUG_KMS(dev, "\n");

nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
if (!nv_connector)
return -ENOMEM;
nv_connector->dcb = nouveau_bios_connector_entry(dev, index);
connector = &nv_connector->base;

switch (type) {
case DRM_MODE_CONNECTOR_VGA:
switch (dcb->type) {
case DCB_CONNECTOR_NONE:
return 0;
case DCB_CONNECTOR_VGA:
NV_INFO(dev, "Detected a VGA connector\n");
type = DRM_MODE_CONNECTOR_VGA;
break;
case DRM_MODE_CONNECTOR_DVID:
NV_INFO(dev, "Detected a DVI-D connector\n");
case DCB_CONNECTOR_TV_0:
case DCB_CONNECTOR_TV_1:
case DCB_CONNECTOR_TV_3:
NV_INFO(dev, "Detected a TV connector\n");
type = DRM_MODE_CONNECTOR_TV;
break;
case DRM_MODE_CONNECTOR_DVII:
case DCB_CONNECTOR_DVI_I:
NV_INFO(dev, "Detected a DVI-I connector\n");
type = DRM_MODE_CONNECTOR_DVII;
break;
case DRM_MODE_CONNECTOR_LVDS:
NV_INFO(dev, "Detected a LVDS connector\n");
case DCB_CONNECTOR_DVI_D:
case DCB_CONNECTOR_HDMI_0:
case DCB_CONNECTOR_HDMI_1:
NV_INFO(dev, "Detected a DVI-D connector\n");
type = DRM_MODE_CONNECTOR_DVID;
break;
case DRM_MODE_CONNECTOR_TV:
NV_INFO(dev, "Detected a TV connector\n");
case DCB_CONNECTOR_LVDS:
NV_INFO(dev, "Detected a LVDS connector\n");
type = DRM_MODE_CONNECTOR_LVDS;
break;
case DRM_MODE_CONNECTOR_DisplayPort:
case DCB_CONNECTOR_DP:
case DCB_CONNECTOR_eDP:
NV_INFO(dev, "Detected a DisplayPort connector\n");
type = DRM_MODE_CONNECTOR_DisplayPort;
break;
default:
NV_ERROR(dev, "Unknown connector, this is not good.\n");
break;
NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
return -EINVAL;
}

nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
if (!nv_connector)
return -ENOMEM;
nv_connector->dcb = dcb;
connector = &nv_connector->base;

/* defaults, will get overridden in detect() */
connector->interlace_allowed = false;
connector->doublescan_allowed = false;

drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);

/* attach encoders */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);

if (nv_encoder->dcb->connector != dcb->index)
continue;

if (get_slave_funcs(nv_encoder))
get_slave_funcs(nv_encoder)->create_resources(encoder, connector);

drm_mode_connector_attach_encoder(connector, encoder);
}

if (!connector->encoder_ids[0]) {
NV_WARN(dev, " no encoders, ignoring\n");
drm_connector_cleanup(connector);
kfree(connector);
return 0;
}

/* Init DVI-I specific properties */
if (type == DRM_MODE_CONNECTOR_DVII) {
drm_mode_create_dvi_i_properties(dev);
Expand Down Expand Up @@ -822,19 +856,6 @@ nouveau_connector_create(struct drm_device *dev, int index, int type)
}
}

/* attach encoders */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);

if (nv_encoder->dcb->connector != index)
continue;

if (get_slave_funcs(nv_encoder))
get_slave_funcs(nv_encoder)->create_resources(encoder, connector);

drm_mode_connector_attach_encoder(connector, encoder);
}

drm_sysfs_connector_add(connector);

if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/nouveau/nouveau_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static inline struct nouveau_connector *nouveau_connector(
return container_of(con, struct nouveau_connector, base);
}

int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type);
int nouveau_connector_create(struct drm_device *,
struct dcb_connector_table_entry *);

#endif /* __NOUVEAU_CONNECTOR_H__ */
47 changes: 2 additions & 45 deletions drivers/gpu/drm/nouveau/nv04_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ nv04_display_create(struct drm_device *dev)
struct dcb_table *dcb = &dev_priv->vbios.dcb;
struct drm_encoder *encoder;
struct drm_crtc *crtc;
uint16_t connector[16] = { 0 };
int i, ret;

NV_DEBUG_KMS(dev, "\n");
Expand Down Expand Up @@ -154,52 +153,10 @@ nv04_display_create(struct drm_device *dev)

if (ret)
continue;

connector[dcbent->connector] |= (1 << dcbent->type);
}

for (i = 0; i < dcb->entries; i++) {
struct dcb_entry *dcbent = &dcb->entry[i];
uint16_t encoders;
int type;

encoders = connector[dcbent->connector];
if (!(encoders & (1 << dcbent->type)))
continue;
connector[dcbent->connector] = 0;

switch (dcbent->type) {
case OUTPUT_ANALOG:
if (!MULTIPLE_ENCODERS(encoders))
type = DRM_MODE_CONNECTOR_VGA;
else
type = DRM_MODE_CONNECTOR_DVII;
break;
case OUTPUT_TMDS:
if (!MULTIPLE_ENCODERS(encoders))
type = DRM_MODE_CONNECTOR_DVID;
else
type = DRM_MODE_CONNECTOR_DVII;
break;
case OUTPUT_LVDS:
type = DRM_MODE_CONNECTOR_LVDS;
#if 0
/* don't create i2c adapter when lvds ddc not allowed */
if (dcbent->lvdsconf.use_straps_for_mode ||
dev_priv->vbios->fp_no_ddc)
i2c_index = 0xf;
#endif
break;
case OUTPUT_TV:
type = DRM_MODE_CONNECTOR_TV;
break;
default:
type = DRM_MODE_CONNECTOR_Unknown;
continue;
}

nouveau_connector_create(dev, dcbent->connector, type);
}
for (i = 0; i < dcb->connector.entries; i++)
nouveau_connector_create(dev, &dcb->connector.entry[i]);

/* Save previous state */
NVLockVgaCrtcs(dev, false);
Expand Down
40 changes: 4 additions & 36 deletions drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,6 @@ int nv50_display_create(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct dcb_table *dcb = &dev_priv->vbios.dcb;
uint32_t connector[16] = {};
int ret, i;

NV_DEBUG_KMS(dev, "\n");
Expand Down Expand Up @@ -522,44 +521,13 @@ int nv50_display_create(struct drm_device *dev)
NV_WARN(dev, "DCB encoder %d unknown\n", entry->type);
continue;
}

connector[entry->connector] |= (1 << entry->type);
}

/* It appears that DCB 3.0+ vbios has a connector table, however,
* I'm not 100% certain how to decode it correctly yet so just
* look at what encoders are present on each connector index and
* attempt to derive the connector type from that.
*/
for (i = 0 ; i < dcb->entries; i++) {
struct dcb_entry *entry = &dcb->entry[i];
uint16_t encoders;
int type;

encoders = connector[entry->connector];
if (!(encoders & (1 << entry->type)))
for (i = 0 ; i < dcb->connector.entries; i++) {
if (i != 0 && dcb->connector.entry[i].index ==
dcb->connector.entry[i - 1].index)
continue;
connector[entry->connector] = 0;

if (encoders & (1 << OUTPUT_DP)) {
type = DRM_MODE_CONNECTOR_DisplayPort;
} else if (encoders & (1 << OUTPUT_TMDS)) {
if (encoders & (1 << OUTPUT_ANALOG))
type = DRM_MODE_CONNECTOR_DVII;
else
type = DRM_MODE_CONNECTOR_DVID;
} else if (encoders & (1 << OUTPUT_ANALOG)) {
type = DRM_MODE_CONNECTOR_VGA;
} else if (encoders & (1 << OUTPUT_LVDS)) {
type = DRM_MODE_CONNECTOR_LVDS;
} else {
type = DRM_MODE_CONNECTOR_Unknown;
}

if (type == DRM_MODE_CONNECTOR_Unknown)
continue;

nouveau_connector_create(dev, entry->connector, type);
nouveau_connector_create(dev, &dcb->connector.entry[i]);
}

ret = nv50_display_init(dev);
Expand Down

0 comments on commit 7f612d8

Please sign in to comment.