NV50: remove edid when monitor is gone, improve fbcon, misc fixes
- This should avoid switching crtc's when going to fbcon.main
parent
c48cddc7ef
commit
e1cd21bcc8
|
@ -2046,6 +2046,13 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, str
|
|||
if (connector->edid_blob_ptr)
|
||||
drm_property_destroy_blob(dev, connector->edid_blob_ptr);
|
||||
|
||||
/* Delete edid, when there is none. */
|
||||
if (!edid) {
|
||||
connector->edid_blob_ptr = NULL;
|
||||
ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid);
|
||||
|
||||
ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, connector->edid_blob_ptr->base.id);
|
||||
|
|
|
@ -284,16 +284,21 @@ static int nv50_fbcon_set_par(struct fb_info *info)
|
|||
}
|
||||
mode_set.mode = drm_mode;
|
||||
|
||||
list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (crtc_used[crtc_count]) {
|
||||
crtc_count++;
|
||||
continue;
|
||||
/* choose crtc it already has, if possible */
|
||||
if (drm_connector->encoder) {
|
||||
struct drm_encoder *drm_encoder = drm_connector->encoder;
|
||||
|
||||
if (drm_encoder->crtc) {
|
||||
list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) {
|
||||
crtc_count++;
|
||||
|
||||
if (drm_crtc == drm_encoder->crtc) {
|
||||
if (!crtc_used[crtc_count]) /* still available? */
|
||||
mode_set.crtc = drm_crtc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* found a crtc */
|
||||
mode_set.crtc = drm_crtc;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* proceed as planned */
|
||||
|
@ -302,6 +307,29 @@ static int nv50_fbcon_set_par(struct fb_info *info)
|
|||
crtc_used[crtc_count] = true;
|
||||
}
|
||||
|
||||
if (!mode_set.crtc) {
|
||||
crtc_count = 0; /* reset */
|
||||
|
||||
/* choose a "random" crtc */
|
||||
list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (crtc_used[crtc_count]) {
|
||||
crtc_count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* found a crtc */
|
||||
mode_set.crtc = drm_crtc;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* proceed as planned */
|
||||
if (mode_set.crtc) {
|
||||
mode_set.crtc->funcs->set_config(&mode_set);
|
||||
crtc_used[crtc_count] = true;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(mode_set.connectors);
|
||||
}
|
||||
|
||||
|
|
|
@ -348,16 +348,11 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
|
|||
blank = true;
|
||||
}
|
||||
|
||||
if (!set->connectors && (modeset || switch_fb)) {
|
||||
if (!set->connectors && !blank) {
|
||||
DRM_ERROR("Sanity check failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!modeset && !switch_fb && !blank) {
|
||||
DRM_ERROR("There is nothing to do, bad input.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Basic variable setting */
|
||||
dev = set->crtc->dev;
|
||||
dev_priv = dev->dev_private;
|
||||
|
@ -369,7 +364,7 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
|
|||
*/
|
||||
|
||||
/* for switch_fb we verify if any important changes happened */
|
||||
if (modeset || switch_fb) {
|
||||
if (!blank) {
|
||||
/* Mode validation */
|
||||
hw_mode = nv50_kms_to_hw_mode(set->mode);
|
||||
|
||||
|
@ -388,6 +383,9 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
|
|||
}
|
||||
connector = to_nv50_connector(drm_connector);
|
||||
|
||||
/* This is to ensure it knows the connector subtype. */
|
||||
drm_connector->funcs->fill_modes(drm_connector, 0, 0);
|
||||
|
||||
output = connector->to_output(connector, nv50_kms_connector_is_digital(drm_connector));
|
||||
if (!output) {
|
||||
DRM_ERROR("No output\n");
|
||||
|
@ -409,6 +407,12 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
|
|||
}
|
||||
}
|
||||
|
||||
/* Now we verified if anything changed, fail if nothing has. */
|
||||
if (!modeset && !switch_fb && !blank) {
|
||||
DRM_ERROR("There is nothing to do, bad input.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Validation done, move on to cleaning of existing structures. */
|
||||
if (modeset) {
|
||||
/* find encoders that use this crtc. */
|
||||
|
@ -913,6 +917,7 @@ static enum drm_connector_status nv50_kms_connector_detect(struct drm_connector
|
|||
/* update our modes whenever there is reason to */
|
||||
if (old_status != drm_connector->status) {
|
||||
drm_connector->funcs->fill_modes(drm_connector, 0, 0);
|
||||
|
||||
/* notify fb of changes */
|
||||
dev->mode_config.funcs->fb_changed(dev);
|
||||
}
|
||||
|
@ -966,16 +971,16 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u
|
|||
|
||||
if (!connected) {
|
||||
NV50_DEBUG("%s is disconnected\n", drm_get_connector_name(drm_connector));
|
||||
/* TODO set EDID to NULL */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not all connnectors have an i2c channel. */
|
||||
if (connector->i2c_chan)
|
||||
if (connected && connector->i2c_chan)
|
||||
edid = (struct edid *) drm_do_probe_ddc_edid(&connector->i2c_chan->adapter);
|
||||
|
||||
/* This will remove edid if needed. */
|
||||
drm_mode_connector_update_edid_property(drm_connector, edid);
|
||||
|
||||
if (edid) {
|
||||
drm_mode_connector_update_edid_property(drm_connector, edid);
|
||||
rval = drm_add_edid_modes(drm_connector, edid);
|
||||
|
||||
/* 2 encoders per connector */
|
||||
|
@ -1026,6 +1031,10 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u
|
|||
|
||||
drm_mode_prune_invalid(dev, &drm_connector->modes, true);
|
||||
|
||||
/* pruning is done, so bail out. */
|
||||
if (!connected)
|
||||
return;
|
||||
|
||||
if (list_empty(&drm_connector->modes)) {
|
||||
struct drm_display_mode *stdmode;
|
||||
struct nouveau_hw_mode *hw_mode;
|
||||
|
|
Loading…
Reference in New Issue