/* Update crtc values up front so the driver can rely on them for mode *setting.
*/
drm_mode_copy(&crtc->mode, mode);
crtc->x = x;
crtc->y = y;
/* Pass our mode to the connectors and the CRTC to give them a chance to *adjustitaccordingtolimitationsorconnectorproperties,andalso *achancetorejectthemodeentirely.
*/
drm_for_each_encoder(encoder, dev) {
if (encoder->crtc != crtc) continue;
encoder_funcs = encoder->helper_private; if (!encoder_funcs) continue;
/* Prepare the encoders and CRTCs before setting the mode. */
drm_for_each_encoder(encoder, dev) {
if (encoder->crtc != crtc) continue;
encoder_funcs = encoder->helper_private; if (!encoder_funcs) continue;
/* Disable the encoders as the first thing we do. */ if (encoder_funcs->prepare)
encoder_funcs->prepare(encoder);
}
drm_crtc_prepare_encoders(dev);
crtc_funcs->prepare(crtc);
/* Set up the DPLL and any encoders state that needs to adjust or depend *ontheDPLL.
*/
ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); if (!ret) goto done;
drm_for_each_encoder(encoder, dev) {
if (encoder->crtc != crtc) continue;
encoder_funcs = encoder->helper_private; if (!encoder_funcs) continue;
drm_dbg_kms(dev, "[ENCODER:%d:%s] set [MODE:%s]\n",
encoder->base.id, encoder->name, mode->name); if (encoder_funcs->mode_set)
encoder_funcs->mode_set(encoder, mode, adjusted_mode);
}
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
crtc_funcs->commit(crtc);
drm_for_each_encoder(encoder, dev) {
if (encoder->crtc != crtc) continue;
encoder_funcs = encoder->helper_private; if (!encoder_funcs) continue;
if (encoder_funcs->commit)
encoder_funcs->commit(encoder);
}
/* Calculate and store various constants which *arelaterneededbyvblankandswap-completion *timestamping.Theyarederivedfromtruehwmode.
*/
drm_calc_timestamping_constants(crtc, &crtc->hwmode);
/* Decouple all encoders and their attached connectors from this crtc */
drm_for_each_encoder(encoder, dev) { struct drm_connector_list_iter conn_iter;
if (encoder->crtc != crtc) continue;
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder != encoder) continue;
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */ if (set->crtc->primary->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ if (set->crtc->primary->fb == NULL) {
drm_dbg_kms(dev, "[CRTC:%d:%s] no fb, full mode set\n",
set->crtc->base.id, set->crtc->name);
mode_changed = true;
} elseif (set->fb->format != set->crtc->primary->fb->format) {
mode_changed = true;
} else
fb_changed = true;
}
if (!drm_mode_equal(set->mode, &set->crtc->mode)) {
drm_dbg_kms(dev, "[CRTC:%d:%s] modes are different, full mode set:\n",
set->crtc->base.id, set->crtc->name);
drm_dbg_kms(dev, DRM_MODE_FMT "\n", DRM_MODE_ARG(&set->crtc->mode));
drm_dbg_kms(dev, DRM_MODE_FMT "\n", DRM_MODE_ARG(set->mode));
mode_changed = true;
}
/* take a reference on all unbound connectors in set, reuse the *alreadytakenreferenceforboundconnectors
*/ for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro]->encoder) continue;
drm_connector_get(set->connectors[ro]);
}
/* a) traverse passed in connector list and get encoders for them */
count = 0;
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) { conststruct drm_connector_helper_funcs *connector_funcs =
connector->helper_private;
new_encoder = connector->encoder; for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro] == connector) { if (connector_funcs->best_encoder)
new_encoder = connector_funcs->best_encoder(connector); else
new_encoder = drm_connector_get_single_encoder(connector);
/* if we can't get an encoder for a connector
we are setting now - then fail */ if (new_encoder == NULL) /* don't break so fail path works correct */
fail = 1;
if (connector->dpms != DRM_MODE_DPMS_ON) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] DPMS not on, full mode switch\n",
connector->base.id, connector->name);
mode_changed = true;
}
break;
}
}
if (new_encoder != connector->encoder) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] encoder changed, full mode switch\n",
connector->base.id, connector->name);
mode_changed = true; /* If the encoder is reused for another connector, then *theappropriatecrtcwillbesetlater.
*/ if (connector->encoder)
connector->encoder->crtc = NULL;
connector->encoder = new_encoder;
}
}
drm_connector_list_iter_end(&conn_iter);
for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro] == connector)
new_crtc = set->crtc;
}
/* Make sure the new CRTC will work with the encoder */ if (new_crtc &&
!drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
ret = -EINVAL;
drm_connector_list_iter_end(&conn_iter); goto fail;
} if (new_crtc != connector->encoder->crtc) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] CRTC changed, full mode switch\n",
connector->base.id, connector->name);
mode_changed = true;
connector->encoder->crtc = new_crtc;
} if (new_crtc) {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] to [CRTC:%d:%s]\n",
connector->base.id, connector->name,
new_crtc->base.id, new_crtc->name);
} else {
drm_dbg_kms(dev, "[CONNECTOR:%d:%s] to [NOCRTC]\n",
connector->base.id, connector->name);
}
}
drm_connector_list_iter_end(&conn_iter);
/* mode_set_base is not a required function */ if (fb_changed && !crtc_funcs->mode_set_base)
mode_changed = true;
if (mode_changed) { if (drm_helper_crtc_in_use(set->crtc)) {
drm_dbg_kms(dev, "[CRTC:%d:%s] attempting to set mode from userspace: " DRM_MODE_FMT "\n",
set->crtc->base.id, set->crtc->name, DRM_MODE_ARG(set->mode));
set->crtc->primary->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
set->x, set->y,
save_set.fb)) {
drm_err(dev, "[CRTC:%d:%s] failed to set mode\n",
set->crtc->base.id, set->crtc->name);
set->crtc->primary->fb = save_set.fb;
ret = -EINVAL; goto fail;
}
drm_dbg_kms(dev, "[CRTC:%d:%s] Setting connector DPMS state to on\n",
set->crtc->base.id, set->crtc->name); for (i = 0; i < set->num_connectors; i++) {
drm_dbg_kms(dev, "\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
set->connectors[i]->name);
set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
}
}
__drm_helper_disable_unused_functions(dev);
} elseif (fb_changed) {
set->crtc->x = set->x;
set->crtc->y = set->y;
set->crtc->primary->fb = set->fb;
ret = crtc_funcs->mode_set_base(set->crtc,
set->x, set->y, save_set.fb); if (ret != 0) {
set->crtc->x = save_set.x;
set->crtc->y = save_set.y;
set->crtc->primary->fb = save_set.fb; goto fail;
}
}
/* after fail drop reference on all unbound connectors in set, let *boundconnectorskeeptheirreference
*/ for (ro = 0; ro < set->num_connectors; ro++) { if (set->connectors[ro]->encoder) continue;
drm_connector_put(set->connectors[ro]);
}
/* Try to restore the config */ if (mode_changed &&
!drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
save_set.y, save_set.fb))
drm_err(dev, "failed to restore config after modeset failure\n");
if (encoder)
encoder_dpms = drm_helper_choose_encoder_dpms(encoder);
/* from off to on, do crtc then encoder */ if (mode < old_dpms) { if (crtc) { conststruct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
if (crtc_funcs->dpms)
(*crtc_funcs->dpms) (crtc,
drm_helper_choose_crtc_dpms(crtc));
} if (encoder)
drm_helper_encoder_dpms(encoder, encoder_dpms);
}
/* from on to off, do encoder then crtc */ if (mode > old_dpms) { if (encoder)
drm_helper_encoder_dpms(encoder, encoder_dpms); if (crtc) { conststruct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
if (crtc_funcs->dpms)
(*crtc_funcs->dpms) (crtc,
drm_helper_choose_crtc_dpms(crtc));
}
}
crtc_funcs = crtc->helper_private; if (crtc_funcs->dpms)
(*crtc_funcs->dpms) (crtc,
drm_helper_choose_crtc_dpms(crtc));
}
}
/* disable the unused connectors while restoring the modesetting */
__drm_helper_disable_unused_functions(dev);
drm_modeset_unlock_all(dev);
}
EXPORT_SYMBOL(drm_helper_resume_force_mode);
/** *drm_helper_force_disable_all-ForciblyturnoffallenabledCRTCs *@dev:DRMdevicewhoseCRTCstoturnoff * *Driversmaywanttocallthisonunloadtoensurethatalldisplaysare *unlitandtheGPUisinaconsistent,lowpowerstate.Takesmodesetlocks. * *Note:Thisshouldonlybeusedbynon-atomiclegacydrivers.Foranatomic *versionlookatdrm_atomic_helper_shutdown(). * *Returns: *Zeroonsuccess,errorcodeonfailure.
*/ int drm_helper_force_disable_all(struct drm_device *dev)
{ struct drm_crtc *crtc; int ret = 0;
drm_modeset_lock_all(dev);
drm_for_each_crtc(crtc, dev) if (crtc->enabled) { struct drm_mode_set set = {
.crtc = crtc,
};
ret = drm_mode_set_config_internal(&set); if (ret) goto out;
}
out:
drm_modeset_unlock_all(dev); return ret;
}
EXPORT_SYMBOL(drm_helper_force_disable_all);
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.