diff options
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 90 |
1 files changed, 61 insertions, 29 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index cd74a0953..20775c052 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -553,10 +553,10 @@ EXPORT_SYMBOL(drm_gtf_mode_complex); * drivers/video/fbmon.c * * Standard GTF parameters: - * M = 600 - * C = 40 - * K = 128 - * J = 20 + * M = 600 + * C = 40 + * K = 128 + * J = 20 * * Returns: * The modeline based on the GTF algorithm stored in a drm_display_mode object. @@ -708,7 +708,8 @@ void drm_mode_set_name(struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_set_name); -/** drm_mode_hsync - get the hsync of a mode +/** + * drm_mode_hsync - get the hsync of a mode * @mode: mode * * Returns: @@ -917,13 +918,30 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ } else if (mode1->clock != mode2->clock) return false; + return drm_mode_equal_no_clocks(mode1, mode2); +} +EXPORT_SYMBOL(drm_mode_equal); + +/** + * drm_mode_equal_no_clocks - test modes for equality + * @mode1: first mode + * @mode2: second mode + * + * Check to see if @mode1 and @mode2 are equivalent, but + * don't check the pixel clocks. + * + * Returns: + * True if the modes are equal, false otherwise. + */ +bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) +{ if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) != (mode2->flags & DRM_MODE_FLAG_3D_MASK)) return false; return drm_mode_equal_no_clocks_no_stereo(mode1, mode2); } -EXPORT_SYMBOL(drm_mode_equal); +EXPORT_SYMBOL(drm_mode_equal_no_clocks); /** * drm_mode_equal_no_clocks_no_stereo - test modes for equality @@ -1056,7 +1074,7 @@ static const char * const drm_mode_status_names[] = { MODE_STATUS(ONE_SIZE), MODE_STATUS(NO_REDUCED), MODE_STATUS(NO_STEREO), - MODE_STATUS(UNVERIFIED), + MODE_STATUS(STALE), MODE_STATUS(BAD), MODE_STATUS(ERROR), }; @@ -1154,7 +1172,6 @@ EXPORT_SYMBOL(drm_mode_sort); /** * drm_mode_connector_list_update - update the mode list for the connector * @connector: the connector to update - * @merge_type_bits: whether to merge or overwrite type bits * * This moves the modes from the @connector probed_modes list * to the actual mode list. It compares the probed mode against the current @@ -1163,33 +1180,48 @@ EXPORT_SYMBOL(drm_mode_sort); * This is just a helper functions doesn't validate any modes itself and also * doesn't prune any invalid modes. Callers need to do that themselves. */ -void drm_mode_connector_list_update(struct drm_connector *connector, - bool merge_type_bits) +void drm_mode_connector_list_update(struct drm_connector *connector) { - struct drm_display_mode *mode; struct drm_display_mode *pmode, *pt; - int found_it; WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex)); - list_for_each_entry_safe(pmode, pt, &connector->probed_modes, - head) { - found_it = 0; + list_for_each_entry_safe(pmode, pt, &connector->probed_modes, head) { + struct drm_display_mode *mode; + bool found_it = false; + /* go through current modes checking for the new probed mode */ list_for_each_entry(mode, &connector->modes, head) { - if (drm_mode_equal(pmode, mode)) { - found_it = 1; - /* if equal delete the probed mode */ - mode->status = pmode->status; - /* Merge type bits together */ - if (merge_type_bits) - mode->type |= pmode->type; - else - mode->type = pmode->type; - list_del(&pmode->head); - drm_mode_destroy(connector->dev, pmode); - break; + if (!drm_mode_equal(pmode, mode)) + continue; + + found_it = true; + + /* + * If the old matching mode is stale (ie. left over + * from a previous probe) just replace it outright. + * Otherwise just merge the type bits between all + * equal probed modes. + * + * If two probed modes are considered equal, pick the + * actual timings from the one that's marked as + * preferred (in case the match isn't 100%). If + * multiple or zero preferred modes are present, favor + * the mode added to the probed_modes list first. + */ + if (mode->status == MODE_STALE) { + drm_mode_copy(mode, pmode); + } else if ((mode->type & DRM_MODE_TYPE_PREFERRED) == 0 && + (pmode->type & DRM_MODE_TYPE_PREFERRED) != 0) { + pmode->type |= mode->type; + drm_mode_copy(mode, pmode); + } else { + mode->type |= pmode->type; } + + list_del(&pmode->head); + drm_mode_destroy(connector->dev, pmode); + break; } if (!found_it) { @@ -1212,7 +1244,7 @@ EXPORT_SYMBOL(drm_mode_connector_list_update); * This uses the same parameters as the fb modedb.c, except for an extra * force-enable, force-enable-digital and force-disable bit at the end: * - * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd] + * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd] * * The intermediate drm_cmdline_mode structure is required to store additional * options from the command line modline like the force-enable/disable flag. @@ -1491,4 +1523,4 @@ int drm_mode_convert_umode(struct drm_display_mode *out, out: return ret; -}
\ No newline at end of file +} |