OSDN Git Service

drm/modesetting: add best encoder finding for modesetting
authorDave Airlie <airlied@redhat.com>
Mon, 2 Jun 2008 01:44:35 +0000 (11:44 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 2 Jun 2008 01:44:35 +0000 (11:44 +1000)
This asks the driver to suggest the best encoder for the connector
during the pick crtcs stage.

Need to also do this during mode setting stages

linux-core/drm_crtc.c
linux-core/drm_crtc.h
linux-core/drm_crtc_helper.c
linux-core/drm_crtc_helper.h
linux-core/intel_crt.c
linux-core/intel_display.c
linux-core/intel_drv.h
linux-core/intel_dvo.c
linux-core/intel_lvds.c
linux-core/intel_sdvo.c
linux-core/intel_tv.c

index 74e526b..73c7f2a 100644 (file)
@@ -2042,16 +2042,13 @@ out:
 }
 
 int drm_mode_connector_attach_encoder(struct drm_connector *connector,
-                                  struct drm_encoder *encoder)
+                                     struct drm_encoder *encoder)
 {
        int i;
 
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
                if (connector->encoder_ids[i] == 0) {
                        connector->encoder_ids[i] = encoder->id;
-                       /* pick the first added encoder as the current */
-                       if (i == 0)
-                               connector->encoder = encoder;
                        return 0;
                }
        }
index 6dbc88a..390ab2d 100644 (file)
@@ -624,7 +624,7 @@ extern bool drm_create_tv_properties(struct drm_device *dev, int num_formats,
 extern char *drm_get_encoder_name(struct drm_encoder *encoder);
 
 extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
-                                         struct drm_encoder *encoder);
+                                            struct drm_encoder *encoder);
 extern void drm_mode_connector_detach_encoder(struct drm_connector *connector,
                                           struct drm_encoder *encoder);
 
index f1a7270..a4168f6 100644 (file)
@@ -208,10 +208,17 @@ static void drm_pick_crtcs (struct drm_device *dev)
        struct drm_encoder *encoder, *encoder_equal;
        struct drm_crtc   *crtc;
        struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
+       struct drm_connector_helper_funcs *connector_funcs;
        int found;
 
+       /* clean out all the encoder/crtc combos */
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               encoder->crtc = NULL;
+       }
+       
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               connector->encoder->crtc = NULL;
+               connector_funcs = connector->helper_private;
+               connector->encoder = NULL;
 
                /* Don't hook up connectors that are disconnected ??
                 *
@@ -249,7 +256,11 @@ static void drm_pick_crtcs (struct drm_device *dev)
                        }
                }
 
-               encoder = connector->encoder;
+               encoder = connector_funcs->best_encoder(connector);
+               if (!encoder)
+                       continue;
+
+               connector->encoder = encoder;
 
                c = -1;
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -259,12 +270,12 @@ static void drm_pick_crtcs (struct drm_device *dev)
                        if ((encoder->possible_crtcs & (1 << c)) == 0)
                                continue;
        
-                       list_for_each_entry(connector_equal, &dev->mode_config.connector_list, head) {
-                               if (connector->id == connector_equal->id)
+                       list_for_each_entry(encoder_equal, &dev->mode_config.encoder_list, head) {
+                               if (encoder->id == encoder_equal->id)
                                        continue;
 
                                /* Find out if crtc has been assigned before */
-                               if (connector_equal->encoder->crtc == crtc)
+                               if (encoder_equal->crtc == crtc)
                                        assigned = 1;
                        }
 
@@ -281,6 +292,9 @@ static void drm_pick_crtcs (struct drm_device *dev)
 
                                encoder_equal = connector_equal->encoder;
 
+                               if (!encoder_equal)
+                                       continue;
+
                                list_for_each_entry(modes, &connector->modes, head) {
                                        list_for_each_entry(modes_equal, &connector_equal->modes, head) {
                                                if (drm_mode_equal (modes, modes_equal)) {
@@ -301,8 +315,8 @@ clone:
                                continue;
 
                        /* Found a CRTC to attach to, do it ! */
-                       connector->encoder->crtc = crtc;
-                       connector->encoder->crtc->desired_mode = des_mode;
+                       encoder->crtc = crtc;
+                       encoder->crtc->desired_mode = des_mode;
                        connector->initial_x = 0;
                        connector->initial_y = 0;
                        DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->mode_id, des_mode->name);
index 80cb4b4..3a3a4d4 100644 (file)
@@ -60,6 +60,7 @@ struct drm_connector_helper_funcs {
        int (*get_modes)(struct drm_connector *connector);
        int (*mode_valid)(struct drm_connector *connector,
                          struct drm_display_mode *mode);
+       struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
 };
        
 extern void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
index 21a1e7d..bf7c449 100644 (file)
@@ -245,6 +245,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = {
 static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
        .mode_valid = intel_crt_mode_valid,
        .get_modes = intel_crt_get_modes,
+       .best_encoder = intel_best_encoder,
 };     
 
 void intel_crt_enc_destroy(struct drm_encoder *encoder)
index bbaa19d..e23b397 100644 (file)
@@ -1489,3 +1489,14 @@ void intel_modeset_cleanup(struct drm_device *dev)
 {
        drm_mode_config_cleanup(dev);
 }
+
+
+/* current intel driver doesn't take advantage of encoders
+   always give back the encoder for the connector
+*/
+struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+
+       return &intel_output->enc;
+}
index 0a5e350..24287e3 100644 (file)
@@ -85,6 +85,9 @@ extern void intel_lvds_init(struct drm_device *dev);
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
 extern void intel_encoder_commit (struct drm_encoder *encoder);
+
+extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
+
 extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
                                                    struct drm_crtc *crtc);
 extern void intel_wait_for_vblank(struct drm_device *dev);
@@ -98,7 +101,6 @@ extern void intel_release_load_detect_pipe(struct intel_output *intel_output,
 extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB);
 extern int intel_sdvo_supports_hotplug(struct drm_connector *connector);
 extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable);
-
 extern int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_connector *connector);
 extern int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
 extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);
index e895d5b..b061b1c 100644 (file)
@@ -342,6 +342,7 @@ static const struct drm_connector_funcs intel_dvo_connector_funcs = {
 static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
        .mode_valid = intel_dvo_mode_valid,
        .get_modes = intel_dvo_get_modes,
+       .best_encoder = intel_best_encoder,
 };
 
 void intel_dvo_enc_destroy(struct drm_encoder *encoder)
@@ -479,6 +480,7 @@ void intel_dvo_init(struct drm_device *dev)
                drm_encoder_init(dev, &intel_output->enc, &intel_dvo_enc_funcs, encoder_type);
                drm_encoder_helper_add(&intel_output->enc, &intel_dvo_helper_funcs);
 
+               drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
                if (dvo->type == INTEL_DVO_CHIP_LVDS) {
                        /* For our LVDS chipsets, we should hopefully be able
                         * to dig the fixed panel mode out of the BIOS data.
index cbe8b53..f2fe461 100644 (file)
@@ -345,6 +345,7 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
        .get_modes = intel_lvds_get_modes,
        .mode_valid = intel_lvds_mode_valid,
+       .best_encoder = intel_best_encoder,
 };     
 
 static const struct drm_connector_funcs intel_lvds_connector_funcs = {
@@ -398,6 +399,7 @@ void intel_lvds_init(struct drm_device *dev)
        drm_encoder_init(dev, &intel_output->enc, &intel_lvds_enc_funcs,
                         DRM_MODE_ENCODER_LVDS);
 
+       drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        intel_output->type = INTEL_OUTPUT_LVDS;
 
        drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
index d3ca2a2..9ae0d56 100644 (file)
@@ -990,6 +990,7 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
 static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = {
        .get_modes = intel_sdvo_get_modes,
        .mode_valid = intel_sdvo_mode_valid,
+       .best_encoder = intel_best_encoder,
 };
 
 void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
@@ -1114,6 +1115,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
        drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
        connector->connector_type = connector_type;
 
+       drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        drm_sysfs_connector_add(connector);
 
        /* Set the input timing to the screen. Assume always input 0. */
index c3b5c09..e45cfa3 100644 (file)
@@ -1617,6 +1617,7 @@ static const struct drm_connector_funcs intel_tv_connector_funcs = {
 static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
        .mode_valid = intel_tv_mode_valid,
        .get_modes = intel_tv_get_modes,
+       .best_encoder = intel_best_encoder,
 };
 
 void intel_tv_enc_destroy(struct drm_encoder *encoder)
@@ -1683,6 +1684,7 @@ intel_tv_init(struct drm_device *dev)
        drm_encoder_init(dev, &intel_output->enc, &intel_tv_enc_funcs,
                         DRM_MODE_ENCODER_TVDAC);
 
+       drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        tv_priv = (struct intel_tv_priv *)(intel_output + 1);
        intel_output->type = INTEL_OUTPUT_TVOUT;
        intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));