drm/connector: Allow max possible encoders to attach to a connector
authorJosé Roberto de Souza <jose.souza@intel.com>
Fri, 13 Sep 2019 23:28:57 +0000 (16:28 -0700)
committerManasi Navare <manasi.d.navare@intel.com>
Mon, 16 Sep 2019 22:13:53 +0000 (15:13 -0700)
Currently we restrict the number of encoders that can be linked to
a connector to 3, increase it to match the maximum number of encoders
that can be initialized(32).

To more effiently do that lets switch from an array of encoder ids to
bitmask.

v2: Fixing missed return on amdgpu_dm_connector_to_encoder()

Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: dri-devel@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org
Cc: nouveau@lists.freedesktop.org
Cc: amd-gfx@lists.freedesktop.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190913232857.389834-2-jose.souza@intel.com
12 files changed:
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/dce_virtual.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/nouveau/dispnv04/disp.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/radeon/radeon_connectors.c
include/drm/drm_connector.h

index ece55c8fa67333267f75dd41baaa70a3906e287b..d8729285f7310f510858a971559388b21f65a6a7 100644 (file)
@@ -217,11 +217,10 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
        struct drm_encoder *encoder;
        const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
        bool connected;
-       int i;
 
        best_encoder = connector_funcs->best_encoder(connector);
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if ((encoder == best_encoder) && (status == connector_status_connected))
                        connected = true;
                else
@@ -236,9 +235,8 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
                               int encoder_type)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->encoder_type == encoder_type)
                        return encoder;
        }
@@ -347,10 +345,9 @@ static struct drm_encoder *
 amdgpu_connector_best_single_encoder(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
-       int i;
 
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -1065,9 +1062,8 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
        /* find analog encoder */
        if (amdgpu_connector->dac_load_detect) {
                struct drm_encoder *encoder;
-               int i;
 
-               drm_connector_for_each_possible_encoder(connector, encoder, i) {
+               drm_connector_for_each_possible_encoder(connector, encoder) {
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
                            encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
                                continue;
@@ -1117,9 +1113,8 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector)
 {
        struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (amdgpu_connector->use_digital == true) {
                        if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
                                return encoder;
@@ -1134,7 +1129,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector)
 
        /* then check use digitial */
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -1271,9 +1266,8 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
 {
        struct drm_encoder *encoder;
        struct amdgpu_encoder *amdgpu_encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                amdgpu_encoder = to_amdgpu_encoder(encoder);
 
                switch (amdgpu_encoder->encoder_id) {
@@ -1292,10 +1286,9 @@ static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
        struct amdgpu_encoder *amdgpu_encoder;
-       int i;
        bool found = false;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                amdgpu_encoder = to_amdgpu_encoder(encoder);
                if (amdgpu_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
                        found = true;
index 3cc0a16649f96db3534d0b9641114adb11797a6a..3669438866618e16cd28e9b61791badb81beb4eb 100644 (file)
@@ -260,15 +260,14 @@ static struct drm_encoder *
 dce_virtual_encoder(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
                        return encoder;
        }
 
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
index cb7cfa9b34f27a789d178e5aeea5c95118c40c50..760af668f6786bc27602a6982c556b4a3d5e60bd 100644 (file)
@@ -4792,7 +4792,13 @@ static int to_drm_connector_type(enum signal_type st)
 
 static struct drm_encoder *amdgpu_dm_connector_to_encoder(struct drm_connector *connector)
 {
-       return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+       struct drm_encoder *encoder;
+
+       /* There is only one encoder per connector */
+       drm_connector_for_each_possible_encoder(connector, encoder)
+               return encoder;
+
+       return NULL;
 }
 
 static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
index 56d36779d21321f0e4c74d1606b6952bdee392a9..417724b3576e557678144c68181c7cd185780440 100644 (file)
@@ -415,9 +415,8 @@ static bool connector_has_possible_crtc(struct drm_connector *connector,
                                        struct drm_crtc *crtc)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->possible_crtcs & drm_crtc_mask(crtc))
                        return true;
        }
index 4c766624b20d31e8b827313b887728cc797c8051..43896c711b505914c7afadf396932127e524c03c 100644 (file)
@@ -365,8 +365,6 @@ EXPORT_SYMBOL(drm_connector_attach_edid_property);
 int drm_connector_attach_encoder(struct drm_connector *connector,
                                 struct drm_encoder *encoder)
 {
-       int i;
-
        /*
         * In the past, drivers have attempted to model the static association
         * of connector to encoder in simple connector/encoder devices using a
@@ -381,18 +379,15 @@ int drm_connector_attach_encoder(struct drm_connector *connector,
        if (WARN_ON(connector->encoder))
                return -EINVAL;
 
-       for (i = 0; i < ARRAY_SIZE(connector->encoder_ids); i++) {
-               if (connector->encoder_ids[i] == 0) {
-                       connector->encoder_ids[i] = encoder->base.id;
-                       return 0;
-               }
-       }
-       return -ENOMEM;
+       connector->possible_encoders |= drm_encoder_mask(encoder);
+
+       return 0;
 }
 EXPORT_SYMBOL(drm_connector_attach_encoder);
 
 /**
- * drm_connector_has_possible_encoder - check if the connector and encoder are assosicated with each other
+ * drm_connector_has_possible_encoder - check if the connector and encoder are
+ * associated with each other
  * @connector: the connector
  * @encoder: the encoder
  *
@@ -402,15 +397,7 @@ EXPORT_SYMBOL(drm_connector_attach_encoder);
 bool drm_connector_has_possible_encoder(struct drm_connector *connector,
                                        struct drm_encoder *encoder)
 {
-       struct drm_encoder *enc;
-       int i;
-
-       drm_connector_for_each_possible_encoder(connector, enc, i) {
-               if (enc == encoder)
-                       return true;
-       }
-
-       return false;
+       return connector->possible_encoders & drm_encoder_mask(encoder);
 }
 EXPORT_SYMBOL(drm_connector_has_possible_encoder);
 
@@ -2121,7 +2108,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        int encoders_count = 0;
        int ret = 0;
        int copied = 0;
-       int i;
        struct drm_mode_modeinfo u_mode;
        struct drm_mode_modeinfo __user *mode_ptr;
        uint32_t __user *encoder_ptr;
@@ -2136,14 +2122,13 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        if (!connector)
                return -ENOENT;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
-               encoders_count++;
+       encoders_count = hweight32(connector->possible_encoders);
 
        if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
                copied = 0;
                encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
 
-               drm_connector_for_each_possible_encoder(connector, encoder, i) {
+               drm_connector_for_each_possible_encoder(connector, encoder) {
                        if (put_user(encoder->base.id, encoder_ptr + copied)) {
                                ret = -EFAULT;
                                goto out;
index 77a996f69cda190ec534d2c7a1bbe10ae2eb6734..c3c8d4b70dbd313d6a8433758ad4d89168a2820d 100644 (file)
@@ -488,8 +488,13 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
 struct drm_encoder *
 drm_connector_get_single_encoder(struct drm_connector *connector)
 {
-       WARN_ON(connector->encoder_ids[1]);
-       return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
+       struct drm_encoder *encoder;
+
+       WARN_ON(hweight32(connector->possible_encoders) > 1);
+       drm_connector_for_each_possible_encoder(connector, encoder)
+               return encoder;
+
+       return NULL;
 }
 
 /**
index 351cbc40f0f8436486d89ac1c8cb0f56a8b56479..a7c87abe88d0b2230efba8b6972271cbf44c4838 100644 (file)
@@ -93,7 +93,6 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
        struct drm_device *dev = connector->dev;
        enum drm_mode_status ret = MODE_OK;
        struct drm_encoder *encoder;
-       int i;
 
        /* Step 1: Validate against connector */
        ret = drm_connector_mode_valid(connector, mode);
@@ -101,7 +100,7 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
                return ret;
 
        /* Step 2: Validate against encoders and crtcs */
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                struct drm_crtc *crtc;
 
                ret = drm_encoder_mode_valid(encoder, mode);
index 5713bacaee80ba94798baad570cf28f2089e283f..500ed0e4b0446f05e55bde538a556e44ec2784e0 100644 (file)
@@ -257,7 +257,7 @@ nv04_display_create(struct drm_device *dev)
 
        list_for_each_entry_safe(connector, ct,
                                 &dev->mode_config.connector_list, head) {
-               if (!connector->encoder_ids[0]) {
+               if (!connector->possible_encoders) {
                        NV_WARN(drm, "%s has no encoders, removing\n",
                                connector->name);
                        connector->funcs->destroy(connector);
index 8497768f1b4102ac76d7e5d45257aec2bb72a82b..d866cadd2ef313ed9dccb7d75b16c50622ff1b20 100644 (file)
@@ -2390,7 +2390,7 @@ nv50_display_create(struct drm_device *dev)
 
        /* cull any connectors we created that don't have an encoder */
        list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) {
-               if (connector->encoder_ids[0])
+               if (connector->possible_encoders)
                        continue;
 
                NV_WARN(drm, "%s has no encoders, removing\n",
index 8aa703347eb547d49cce7fcf9438336631cd2ada..54317bc31e3135564dd3eb5be6bd81c0219eff93 100644 (file)
@@ -366,9 +366,8 @@ find_encoder(struct drm_connector *connector, int type)
 {
        struct nouveau_encoder *nv_encoder;
        struct drm_encoder *enc;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, enc, i) {
+       drm_connector_for_each_possible_encoder(connector, enc) {
                nv_encoder = nouveau_encoder(enc);
 
                if (type == DCB_OUTPUT_ANY ||
@@ -415,10 +414,10 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
        struct drm_device *dev = connector->dev;
        struct nouveau_encoder *nv_encoder = NULL, *found = NULL;
        struct drm_encoder *encoder;
-       int i, ret;
+       int ret;
        bool switcheroo_ddc = false;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                nv_encoder = nouveau_encoder(encoder);
 
                switch (nv_encoder->dcb->type) {
index c60d1a44d22a2c7a09705e6fdb087f972652b55c..dcfbf8c742ad09c74b78de77c74c709af1d4ecac 100644 (file)
@@ -249,11 +249,10 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
        struct drm_encoder *encoder;
        const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
        bool connected;
-       int i;
 
        best_encoder = connector_funcs->best_encoder(connector);
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if ((encoder == best_encoder) && (status == connector_status_connected))
                        connected = true;
                else
@@ -269,9 +268,8 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
 static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
 {
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (encoder->encoder_type == encoder_type)
                        return encoder;
        }
@@ -380,10 +378,9 @@ static int radeon_ddc_get_modes(struct drm_connector *connector)
 static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
-       int i;
 
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -428,14 +425,13 @@ radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
 
        list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
                struct drm_encoder *enc;
-               int i;
 
                if (conflict == connector)
                        continue;
 
                radeon_conflict = to_radeon_connector(conflict);
 
-               drm_connector_for_each_possible_encoder(conflict, enc, i) {
+               drm_connector_for_each_possible_encoder(conflict, enc) {
                        /* if the IDs match */
                        if (enc == encoder) {
                                if (conflict->status != connector_status_connected)
@@ -1363,9 +1359,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
        /* find analog encoder */
        if (radeon_connector->dac_load_detect) {
-               int i;
-
-               drm_connector_for_each_possible_encoder(connector, encoder, i) {
+               drm_connector_for_each_possible_encoder(connector, encoder) {
                        if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
                            encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
                                continue;
@@ -1443,9 +1437,8 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                if (radeon_connector->use_digital == true) {
                        if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
                                return encoder;
@@ -1460,7 +1453,7 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
 
        /* then check use digitial */
        /* pick the first one */
-       drm_connector_for_each_possible_encoder(connector, encoder, i)
+       drm_connector_for_each_possible_encoder(connector, encoder)
                return encoder;
 
        return NULL;
@@ -1603,9 +1596,8 @@ u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
 {
        struct drm_encoder *encoder;
        struct radeon_encoder *radeon_encoder;
-       int i;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                radeon_encoder = to_radeon_encoder(encoder);
 
                switch (radeon_encoder->encoder_id) {
@@ -1624,10 +1616,9 @@ static bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
 {
        struct drm_encoder *encoder;
        struct radeon_encoder *radeon_encoder;
-       int i;
        bool found = false;
 
-       drm_connector_for_each_possible_encoder(connector, encoder, i) {
+       drm_connector_for_each_possible_encoder(connector, encoder) {
                radeon_encoder = to_radeon_encoder(encoder);
                if (radeon_encoder->caps & ATOM_ENCODER_CAP_RECORD_HBR2)
                        found = true;
index 681cb590f95211d3a3209f3f978561992ee75e00..c6e993e78dbd14d924f2e2e7de5fd2daa9d9e93e 100644 (file)
@@ -1288,12 +1288,12 @@ struct drm_connector {
        /** @override_edid: has the EDID been overwritten through debugfs for testing? */
        bool override_edid;
 
-#define DRM_CONNECTOR_MAX_ENCODER 3
        /**
-        * @encoder_ids: Valid encoders for this connector. Please only use
-        * drm_connector_for_each_possible_encoder() to enumerate these.
+        * @possible_encoders: Bit mask of encoders that can drive this
+        * connector, drm_encoder_index() determines the index into the bitfield
+        * and the bits are set with drm_connector_attach_encoder().
         */
-       uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
+       u32 possible_encoders;
 
        /**
         * @encoder: Currently bound encoder driving this connector, if any.
@@ -1608,13 +1608,9 @@ bool drm_connector_has_possible_encoder(struct drm_connector *connector,
  * drm_connector_for_each_possible_encoder - iterate connector's possible encoders
  * @connector: &struct drm_connector pointer
  * @encoder: &struct drm_encoder pointer used as cursor
- * @__i: int iteration cursor, for macro-internal use
  */
-#define drm_connector_for_each_possible_encoder(connector, encoder, __i) \
-       for ((__i) = 0; (__i) < ARRAY_SIZE((connector)->encoder_ids) && \
-                    (connector)->encoder_ids[(__i)] != 0; (__i)++) \
-               for_each_if((encoder) = \
-                           drm_encoder_find((connector)->dev, NULL, \
-                                            (connector)->encoder_ids[(__i)])) \
+#define drm_connector_for_each_possible_encoder(connector, encoder) \
+       drm_for_each_encoder_mask(encoder, (connector)->dev, \
+                                 (connector)->possible_encoders)
 
 #endif