/* * Copyright 2009 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Ben Skeggs
*/
for (int i = 0; i < ARRAY_SIZE(rates); i++) { if (rates[i] <= max_rate) {
outp->dp.rate[outp->dp.rate_nr].dpcd = -1;
outp->dp.rate[outp->dp.rate_nr].rate = rates[i];
outp->dp.rate_nr++;
}
}
if (WARN_ON(!outp->dp.rate_nr)) goto out;
}
ret = nvif_outp_dp_rates(&outp->outp, outp->dp.rate, outp->dp.rate_nr); if (ret) goto out;
for (int i = 0; i < outp->dp.rate_nr; i++) {
u32 link_bw = outp->dp.rate[i].rate;
if (link_bw > outp->dp.link_bw)
outp->dp.link_bw = link_bw;
}
ret = drm_dp_read_desc(aux, &outp->dp.desc, drm_dp_is_branch(dpcd)); if (ret < 0) goto out;
if (nouveau_mst) {
mstm = outp->dp.mstm; if (mstm)
mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd) == DRM_DP_MST;
}
if (nouveau_dp_has_sink_count(connector, outp)) {
ret = drm_dp_read_sink_count(aux); if (ret < 0) goto out;
outp->dp.sink_count = ret;
/* * Dongle connected, but no display. Don't bother reading * downstream port info
*/ if (!outp->dp.sink_count) return connector_status_disconnected;
}
ret = drm_dp_read_downstream_info(aux, dpcd,
outp->dp.downstream_ports); if (ret < 0) goto out;
status = connector_status_connected;
out: if (status != connector_status_connected) { /* Clear any cached info */
outp->dp.sink_count = 0;
} return status;
}
/* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we * haven't probed them once before.
*/ if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { if (connector->status == connector_status_connected) return NOUVEAU_DP_SST; elseif (connector->status == connector_status_disconnected) return NOUVEAU_DP_NONE;
}
// Ensure that the aux bus is enabled for probing
drm_dp_dpcd_set_powered(&nv_connector->aux, true);
mutex_lock(&nv_encoder->dp.hpd_irq_lock); if (mstm) { /* If we're not ready to handle MST state changes yet, just * report the last status of the connector. We'll reprobe it * once we've resumed.
*/ if (mstm->suspended) { if (mstm->is_mst)
ret = NOUVEAU_DP_MST; elseif (connector->status ==
connector_status_connected)
ret = NOUVEAU_DP_SST;
if (mstm && mstm->can_mst) {
ret = nv50_mstm_detect(nv_encoder); if (ret == 1) {
ret = NOUVEAU_DP_MST; goto out;
} elseif (ret != 0) {
nvif_outp_dp_aux_pwr(&nv_encoder->outp, false); goto out;
}
}
ret = NOUVEAU_DP_SST;
out: if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST)
nv50_mstm_remove(mstm);
/* GSP doesn't like when we try to do aux transactions on a port it considers disconnected, * and since we don't really have a usecase for that anyway - just disable the aux bus here * if we've decided the connector is disconnected
*/ if (ret == NOUVEAU_DP_NONE)
drm_dp_dpcd_set_powered(&nv_connector->aux, false);
/* TODO: * - Validate against the DP caps advertised by the GPU (we don't check these * yet)
*/ enum drm_mode_status
nv50_dp_mode_valid(struct nouveau_encoder *outp, conststruct drm_display_mode *mode, unsigned *out_clock)
{ constunsignedint min_clock = 25000; unsignedint max_rate, mode_rate, ds_max_dotclock, clock = mode->clock; /* Check with the minmum bpc always, so we can advertise better modes. * In particlar not doing this causes modes to be dropped on HDR * displays as we might check with a bpc of 16 even.
*/ const u8 bpp = 6 * 3;
if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace) return MODE_NO_INTERLACE;
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
clock *= 2;
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.