summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2007-04-23 11:42:29 +1000
committerDave Airlie <airlied@linux.ie>2007-04-23 11:42:29 +1000
commitceb44021ad7755721acc3c0307c54009b666442e (patch)
tree15ec54103ff26a46060145b51ad89dfdeb60dc7f
parent0f3c5148f02bd98411095fdc8059207fa17b4a7d (diff)
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
-rw-r--r--linux-core/drm_crtc.c7
-rw-r--r--linux-core/drm_crtc.h1
-rw-r--r--linux-core/drm_modes.c39
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);
+ }
+ }
+}