From ceb44021ad7755721acc3c0307c54009b666442e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 23 Apr 2007 11:42:29 +1000 Subject: drm: make mode numbers no change by comparing probed modes The mode list sets all the output modes to UNVERIFIED, then probes a new list, If a mode is on the new list and not on the old, it adds it to the old, if a mode is on the new list and old, it just updates the status to the new mode status. If a mode is on the old list and not on the new, prune invalid modes should remove all UNVERIFIED modes --- linux-core/drm_crtc.c | 7 +++---- linux-core/drm_crtc.h | 1 + linux-core/drm_modes.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index f95facce..16cf62a7 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -286,8 +286,9 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) list_for_each_entry(output, &dev->mode_config.output_list, head) { + /* set all modes to the unverified state */ list_for_each_entry_safe(mode, t, &output->modes, head) - drm_mode_remove(output, mode); + mode->status = MODE_UNVERIFIED; output->status = (*output->funcs->detect)(output); @@ -300,9 +301,7 @@ void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY) ret = (*output->funcs->get_modes)(output); if (ret) { - /* move the modes over to the main mode list */ - drm_mode_list_concat(&output->probed_modes, - &output->modes); + drm_mode_output_list_update(output); } if (maxX && maxY) diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 149bc31f..a15ce0cf 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -59,6 +59,7 @@ enum drm_mode_status { MODE_ONE_HEIGHT, /* only one height is supported */ MODE_ONE_SIZE, /* only one resolution is supported */ MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */ + MODE_UNVERIFIED = -3, /* mode needs to reverified */ MODE_BAD = -2, /* unspecified reason */ MODE_ERROR = -1 /* error condition */ }; diff --git a/linux-core/drm_modes.c b/linux-core/drm_modes.c index 54c25137..3293f91d 100644 --- a/linux-core/drm_modes.c +++ b/linux-core/drm_modes.c @@ -517,3 +517,42 @@ void drm_mode_sort(struct list_head *mode_list) { list_sort(mode_list, drm_mode_compare); } + + +/** + * drm_mode_output_list_update - update the mode list for the output + * @output: the output to update + * + * LOCKING: + * Caller must hold a lock protecting @mode_list. + * + * This moves the modes from the @output probed_modes list + * to the actual mode list. It compares the probed mode against the current + * list and only adds different modes. All modes unverified after this point + * will be removed by the prune invalid modes. + */ +void drm_mode_output_list_update(struct drm_output *output) +{ + struct drm_display_mode *mode, *t; + struct drm_display_mode *pmode, *pt; + int found_it; + list_for_each_entry_safe(pmode, pt, &output->probed_modes, + head) { + found_it = 0; + /* go through current modes checking for the new probed mode */ + list_for_each_entry(mode, &output->modes, head) { + if (drm_mode_equal(pmode, mode)) { + found_it = 1; + /* if equal delete the probed mode */ + mode->status = pmode->status; + list_del(&pmode->head); + kfree(pmode); + break; + } + } + + if (!found_it) { + list_move_tail(&pmode->head, &output->modes); + } + } +} -- cgit v1.2.3