diff options
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 83 |
1 files changed, 46 insertions, 37 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index ef6bd3656548..20775c05235a 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: @@ -1073,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), }; @@ -1171,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 @@ -1180,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) { @@ -1229,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. @@ -1247,7 +1262,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0; bool yres_specified = false, cvt = false, rb = false; bool interlace = false, margins = false, was_digit = false; - int i, err; + int i; enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; #ifdef CONFIG_FB @@ -1267,9 +1282,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, case '@': if (!refresh_specified && !bpp_specified && !yres_specified && !cvt && !rb && was_digit) { - err = kstrtouint(&name[i + 1], 10, &refresh); - if (err) - return false; + refresh = simple_strtol(&name[i+1], NULL, 10); refresh_specified = true; was_digit = false; } else @@ -1278,9 +1291,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, case '-': if (!bpp_specified && !yres_specified && !cvt && !rb && was_digit) { - err = kstrtouint(&name[i + 1], 10, &bpp); - if (err) - return false; + bpp = simple_strtol(&name[i+1], NULL, 10); bpp_specified = true; was_digit = false; } else @@ -1288,9 +1299,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, break; case 'x': if (!yres_specified && was_digit) { - err = kstrtouint(&name[i + 1], 10, &yres); - if (err) - return false; + yres = simple_strtol(&name[i+1], NULL, 10); yres_specified = true; was_digit = false; } else |