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
main
Dave Airlie 2007-04-23 11:42:29 +10:00
parent 0f3c5148f0
commit ceb44021ad
3 changed files with 43 additions and 4 deletions

View File

@ -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) { 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) 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); 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); ret = (*output->funcs->get_modes)(output);
if (ret) { if (ret) {
/* move the modes over to the main mode list */ drm_mode_output_list_update(output);
drm_mode_list_concat(&output->probed_modes,
&output->modes);
} }
if (maxX && maxY) if (maxX && maxY)

View File

@ -59,6 +59,7 @@ enum drm_mode_status {
MODE_ONE_HEIGHT, /* only one height is supported */ MODE_ONE_HEIGHT, /* only one height is supported */
MODE_ONE_SIZE, /* only one resolution is supported */ MODE_ONE_SIZE, /* only one resolution is supported */
MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */ MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */
MODE_UNVERIFIED = -3, /* mode needs to reverified */
MODE_BAD = -2, /* unspecified reason */ MODE_BAD = -2, /* unspecified reason */
MODE_ERROR = -1 /* error condition */ MODE_ERROR = -1 /* error condition */
}; };

View File

@ -517,3 +517,42 @@ void drm_mode_sort(struct list_head *mode_list)
{ {
list_sort(mode_list, drm_mode_compare); 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);
}
}
}