]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/gpu/drm/drm_crtc_helper.c
drm: initial KMS config fixes
[linux-2.6-omap-h63xx.git] / drivers / gpu / drm / drm_crtc_helper.c
index d8a982b71296520fd0344e9670e1f88b4b342b7d..e490e69db21e053e5b9f13a117d3591361873ca8 100644 (file)
@@ -36,7 +36,7 @@
 /*
  * Detailed mode info for 800x600@60Hz
  */
-static struct drm_display_mode std_mode[] = {
+static struct drm_display_mode std_modes[] = {
        { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840,
                   968, 1056, 0, 600, 601, 605, 628, 0,
                   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
@@ -60,15 +60,18 @@ static struct drm_display_mode std_mode[] = {
  * changes have occurred.
  *
  * FIXME: take into account monitor limits
+ *
+ * RETURNS:
+ * Number of modes found on @connector.
  */
-void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
-                                            uint32_t maxX, uint32_t maxY)
+int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
+                                           uint32_t maxX, uint32_t maxY)
 {
        struct drm_device *dev = connector->dev;
        struct drm_display_mode *mode, *t;
        struct drm_connector_helper_funcs *connector_funcs =
                connector->helper_private;
-       int ret;
+       int count = 0;
 
        DRM_DEBUG("%s\n", drm_get_connector_name(connector));
        /* set all modes to the unverified state */
@@ -81,14 +84,14 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
                DRM_DEBUG("%s is disconnected\n",
                          drm_get_connector_name(connector));
                /* TODO set EDID to NULL */
-               return;
+               return 0;
        }
 
-       ret = (*connector_funcs->get_modes)(connector);
+       count = (*connector_funcs->get_modes)(connector);
+       if (!count)
+               return 0;
 
-       if (ret) {
-               drm_mode_connector_list_update(connector);
-       }
+       drm_mode_connector_list_update(connector);
 
        if (maxX && maxY)
                drm_mode_validate_size(dev, &connector->modes, maxX,
@@ -102,25 +105,8 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 
        drm_mode_prune_invalid(dev, &connector->modes, true);
 
-       if (list_empty(&connector->modes)) {
-               struct drm_display_mode *stdmode;
-
-               DRM_DEBUG("No valid modes on %s\n",
-                         drm_get_connector_name(connector));
-
-               /* Should we do this here ???
-                * When no valid EDID modes are available we end up
-                * here and bailed in the past, now we add a standard
-                * 640x480@60Hz mode and carry on.
-                */
-               stdmode = drm_mode_duplicate(dev, &std_mode[0]);
-               drm_mode_probed_add(connector, stdmode);
-               drm_mode_list_concat(&connector->probed_modes,
-                                    &connector->modes);
-
-               DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
-                         drm_get_connector_name(connector));
-       }
+       if (list_empty(&connector->modes))
+               return 0;
 
        drm_mode_sort(&connector->modes);
 
@@ -131,20 +117,58 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
                drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
                drm_mode_debug_printmodeline(mode);
        }
+
+       return count;
 }
 EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
 
-void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
+int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
                                      uint32_t maxY)
 {
        struct drm_connector *connector;
+       int count = 0;
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               drm_helper_probe_single_connector_modes(connector, maxX, maxY);
+               count += drm_helper_probe_single_connector_modes(connector,
+                                                                maxX, maxY);
        }
+
+       return count;
 }
 EXPORT_SYMBOL(drm_helper_probe_connector_modes);
 
+static void drm_helper_add_std_modes(struct drm_device *dev,
+                                    struct drm_connector *connector)
+{
+       struct drm_display_mode *mode, *t;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
+               struct drm_display_mode *stdmode;
+
+               /*
+                * When no valid EDID modes are available we end up
+                * here and bailed in the past, now we add some standard
+                * modes and move on.
+                */
+               stdmode = drm_mode_duplicate(dev, &std_modes[i]);
+               drm_mode_probed_add(connector, stdmode);
+               drm_mode_list_concat(&connector->probed_modes,
+                                    &connector->modes);
+
+               DRM_DEBUG("Adding mode %s to %s\n", stdmode->name,
+                         drm_get_connector_name(connector));
+       }
+       drm_mode_sort(&connector->modes);
+
+       DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector));
+       list_for_each_entry_safe(mode, t, &connector->modes, head) {
+               mode->vrefresh = drm_mode_vrefresh(mode);
+
+               drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+               drm_mode_debug_printmodeline(mode);
+       }
+}
 
 /**
  * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
@@ -237,6 +261,8 @@ static void drm_enable_connectors(struct drm_device *dev, bool *enabled)
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                enabled[i] = drm_connector_enabled(connector, true);
+               DRM_DEBUG("connector %d enabled? %s\n", connector->base.id,
+                         enabled[i] ? "yes" : "no");
                any_enabled |= enabled[i];
                i++;
        }
@@ -265,11 +291,17 @@ static bool drm_target_preferred(struct drm_device *dev,
                        continue;
                }
 
+               DRM_DEBUG("looking for preferred mode on connector %d\n",
+                         connector->base.id);
+
                modes[i] = drm_has_preferred_mode(connector, width, height);
-               if (!modes[i]) {
+               /* No preferred modes, pick one off the list */
+               if (!modes[i] && !list_empty(&connector->modes)) {
                        list_for_each_entry(modes[i], &connector->modes, head)
                                break;
                }
+               DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name :
+                         "none");
                i++;
        }
        return true;
@@ -369,6 +401,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
        int width, height;
        int i, ret;
 
+       DRM_DEBUG("\n");
+
        width = dev->mode_config.max_width;
        height = dev->mode_config.max_height;
 
@@ -390,6 +424,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
        if (!ret)
                DRM_ERROR("Unable to find initial modes\n");
 
+       DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height);
+
        drm_pick_crtcs(dev, crtcs, modes, 0, width, height);
 
        i = 0;
@@ -403,6 +439,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
                }
 
                if (mode && crtc) {
+                       DRM_DEBUG("desired mode %s set on crtc %d\n",
+                                 mode->name, crtc->base.id);
                        crtc->desired_mode = mode;
                        connector->encoder->crtc = crtc;
                } else
@@ -764,10 +802,31 @@ bool drm_helper_plugged_event(struct drm_device *dev)
  */
 bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
 {
-       int ret = false;
+       struct drm_connector *connector;
+       int count = 0;
 
-       drm_helper_plugged_event(dev);
-       return ret;
+       count = drm_helper_probe_connector_modes(dev,
+                                                dev->mode_config.max_width,
+                                                dev->mode_config.max_height);
+
+       /*
+        * None of the available connectors had any modes, so add some
+        * and try to light them up anyway
+        */
+       if (!count) {
+               DRM_ERROR("connectors have no modes, using standard modes\n");
+               list_for_each_entry(connector,
+                                   &dev->mode_config.connector_list,
+                                   head)
+                       drm_helper_add_std_modes(dev, connector);
+       }
+
+       drm_setup_crtcs(dev);
+
+       /* alert the driver fb layer */
+       dev->mode_config.funcs->fb_changed(dev);
+
+       return 0;
 }
 EXPORT_SYMBOL(drm_helper_initial_config);