Skip to content

Commit

Permalink
drm/nouveau: tidy connector/encoder creation a little
Browse files Browse the repository at this point in the history
Create connectors before encoders to avoid having to do another loop across
encoder list whenever we create a new connector.  This allows us to pass
the connector to the encoder creation functions, and avoid using a
create_resources() callback since we can now call it directly.

This can also potentially modify the connector ordering on nv50.  On cards
where the DCB connector and encoder tables are in the same order, things
will be unchanged.  However, there's some cards where the ordering between
the tables differ, and in one case, leads us to naming the connectors
"wrongly".

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Jul 13, 2010
1 parent 3195c5f commit 8f1a608
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 83 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_bios.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct dcb_connector_table_entry {
enum dcb_connector_type type;
uint8_t index2;
uint8_t gpio_tag;
void *drm;
};

struct dcb_connector_table {
Expand Down
51 changes: 15 additions & 36 deletions drivers/gpu/drm/nouveau/nouveau_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -729,66 +729,62 @@ nouveau_connector_funcs_lvds = {
.force = nouveau_connector_force
};

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

NV_DEBUG_KMS(dev, "\n");

if (index >= dev_priv->vbios.dcb.connector.entries)
return ERR_PTR(-EINVAL);

dcb = &dev_priv->vbios.dcb.connector.entry[index];
if (dcb->drm)
return dcb->drm;

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 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 DCB_CONNECTOR_DVI_I:
NV_INFO(dev, "Detected a DVI-I connector\n");
type = DRM_MODE_CONNECTOR_DVII;
break;
case DCB_CONNECTOR_DVI_D:
NV_INFO(dev, "Detected a DVI-D connector\n");
type = DRM_MODE_CONNECTOR_DVID;
break;
case DCB_CONNECTOR_HDMI_0:
case DCB_CONNECTOR_HDMI_1:
NV_INFO(dev, "Detected a HDMI connector\n");
type = DRM_MODE_CONNECTOR_HDMIA;
break;
case DCB_CONNECTOR_LVDS:
NV_INFO(dev, "Detected a LVDS connector\n");
type = DRM_MODE_CONNECTOR_LVDS;
funcs = &nouveau_connector_funcs_lvds;
break;
case DCB_CONNECTOR_DP:
NV_INFO(dev, "Detected a DisplayPort connector\n");
type = DRM_MODE_CONNECTOR_DisplayPort;
break;
case DCB_CONNECTOR_eDP:
NV_INFO(dev, "Detected an eDP connector\n");
type = DRM_MODE_CONNECTOR_eDP;
break;
default:
NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
return -EINVAL;
return ERR_PTR(-EINVAL);
}

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

Expand All @@ -799,24 +795,6 @@ nouveau_connector_create(struct drm_device *dev,
drm_connector_init(dev, 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");
goto fail;
}

/* Check if we need dithering enabled */
if (dcb->type == DCB_CONNECTOR_LVDS) {
bool dummy, is_24bit = false;
Expand Down Expand Up @@ -877,11 +855,12 @@ nouveau_connector_create(struct drm_device *dev,
}

drm_sysfs_connector_add(connector);
return 0;
dcb->drm = connector;
return dcb->drm;

fail:
drm_connector_cleanup(connector);
kfree(connector);
return ret;
return ERR_PTR(ret);

}
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static inline struct nouveau_connector *nouveau_connector(
return container_of(con, struct nouveau_connector, base);
}

int nouveau_connector_create(struct drm_device *,
struct dcb_connector_table_entry *);
struct drm_connector *
nouveau_connector_create(struct drm_device *, int index);

#endif /* __NOUVEAU_CONNECTOR_H__ */
8 changes: 4 additions & 4 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1072,13 +1072,13 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg);

/* nv04_dac.c */
extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry);
extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *);
extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
extern int nv04_dac_output_offset(struct drm_encoder *encoder);
extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);

/* nv04_dfp.c */
extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry);
extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *);
extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent);
extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
int head, bool dl);
Expand All @@ -1087,10 +1087,10 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode);

/* nv04_tv.c */
extern int nv04_tv_identify(struct drm_device *dev, int i2c_index);
extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry);
extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *);

/* nv17_tv.c */
extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry);
extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *);

/* nv04_display.c */
extern int nv04_display_create(struct drm_device *);
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)

struct nouveau_connector *
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry);
int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry);
int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
int nv50_dac_create(struct drm_connector *, struct dcb_entry *);

struct bit_displayport_encoder_table {
uint32_t match;
Expand Down
7 changes: 5 additions & 2 deletions drivers/gpu/drm/nouveau/nv04_dac.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,11 +501,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = {
.destroy = nv04_dac_destroy,
};

int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
int
nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
{
const struct drm_encoder_helper_funcs *helper;
struct drm_encoder *encoder;
struct nouveau_encoder *nv_encoder = NULL;
struct drm_device *dev = connector->dev;
struct drm_encoder *encoder;

nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
if (!nv_encoder)
Expand All @@ -527,5 +529,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;

drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}
8 changes: 5 additions & 3 deletions drivers/gpu/drm/nouveau/nv04_dfp.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,11 +584,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = {
.destroy = nv04_dfp_destroy,
};

int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
int
nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry)
{
const struct drm_encoder_helper_funcs *helper;
struct drm_encoder *encoder;
struct nouveau_encoder *nv_encoder = NULL;
struct drm_encoder *encoder;
int type;

switch (entry->type) {
Expand All @@ -613,11 +614,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
nv_encoder->dcb = entry;
nv_encoder->or = ffs(entry->or) - 1;

drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type);
drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type);
drm_encoder_helper_add(encoder, helper);

encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;

drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}
23 changes: 17 additions & 6 deletions drivers/gpu/drm/nouveau/nv04_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ nv04_display_create(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct dcb_table *dcb = &dev_priv->vbios.dcb;
struct drm_connector *connector, *ct;
struct drm_encoder *encoder;
struct drm_crtc *crtc;
int i, ret;
Expand Down Expand Up @@ -132,19 +133,23 @@ nv04_display_create(struct drm_device *dev)
for (i = 0; i < dcb->entries; i++) {
struct dcb_entry *dcbent = &dcb->entry[i];

connector = nouveau_connector_create(dev, dcbent->connector);
if (IS_ERR(connector))
continue;

switch (dcbent->type) {
case OUTPUT_ANALOG:
ret = nv04_dac_create(dev, dcbent);
ret = nv04_dac_create(connector, dcbent);
break;
case OUTPUT_LVDS:
case OUTPUT_TMDS:
ret = nv04_dfp_create(dev, dcbent);
ret = nv04_dfp_create(connector, dcbent);
break;
case OUTPUT_TV:
if (dcbent->location == DCB_LOC_ON_CHIP)
ret = nv17_tv_create(dev, dcbent);
ret = nv17_tv_create(connector, dcbent);
else
ret = nv04_tv_create(dev, dcbent);
ret = nv04_tv_create(connector, dcbent);
break;
default:
NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
Expand All @@ -155,8 +160,14 @@ nv04_display_create(struct drm_device *dev)
continue;
}

for (i = 0; i < dcb->connector.entries; i++)
nouveau_connector_create(dev, &dcb->connector.entry[i]);
list_for_each_entry_safe(connector, ct,
&dev->mode_config.connector_list, head) {
if (!connector->encoder_ids[0]) {
NV_WARN(dev, "%s has no encoders, removing\n",
drm_get_connector_name(connector));
connector->funcs->destroy(connector);
}
}

/* Save previous state */
NVLockVgaCrtcs(dev, false);
Expand Down
8 changes: 6 additions & 2 deletions drivers/gpu/drm/nouveau/nv04_tv.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,12 @@ static void nv04_tv_destroy(struct drm_encoder *encoder)
kfree(nv_encoder);
}

int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
int
nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
{
struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;
struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct i2c_adapter *adap;
struct drm_encoder_funcs *funcs = NULL;
Expand Down Expand Up @@ -266,7 +268,7 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)

was_locked = NVLockVgaCrtcs(dev, false);

ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), adap,
&nv04_tv_encoder_info[type].board_info);

NVLockVgaCrtcs(dev, was_locked);
Expand Down Expand Up @@ -294,7 +296,9 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)

/* Set the slave encoder configuration */
sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params);
sfuncs->create_resources(encoder, connector);

drm_mode_connector_attach_encoder(connector, encoder);
return 0;

fail:
Expand Down
6 changes: 5 additions & 1 deletion drivers/gpu/drm/nouveau/nv17_tv.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,8 +744,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = {
.destroy = nv17_tv_destroy,
};

int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
int
nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
{
struct drm_device *dev = connector->dev;
struct drm_encoder *encoder;
struct nv17_tv_encoder *tv_enc = NULL;

Expand Down Expand Up @@ -774,5 +776,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;

nv17_tv_create_resources(encoder, connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}
9 changes: 4 additions & 5 deletions drivers/gpu/drm/nouveau/nv50_dac.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,11 @@ static const struct drm_encoder_funcs nv50_dac_encoder_funcs = {
};

int
nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry)
nv50_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
{
struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder;

NV_DEBUG_KMS(dev, "\n");
NV_INFO(dev, "Detected a DAC output\n");

nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
if (!nv_encoder)
return -ENOMEM;
Expand All @@ -293,12 +290,14 @@ nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry)

nv_encoder->disconnect = nv50_dac_disconnect;

drm_encoder_init(dev, encoder, &nv50_dac_encoder_funcs,
drm_encoder_init(connector->dev, encoder, &nv50_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC);
drm_encoder_helper_add(encoder, &nv50_dac_helper_funcs);

encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0;

drm_mode_connector_attach_encoder(connector, encoder);
return 0;
}

Loading

0 comments on commit 8f1a608

Please sign in to comment.