drm/amd/display: Update link encoder object creation.
authorJimmy Kizito <Jimmy.Kizito@amd.com>
Tue, 5 Jan 2021 15:17:05 +0000 (10:17 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 6 Oct 2021 19:50:50 +0000 (15:50 -0400)
[Why & How]
USB4 endpoints are dynamically mapped. We create additional link
encoders for USB4 use when DC is created and destroy them when DC
is destructed

Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Wayne Lin <Wayne.Lin@amd.com>
Acked-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Jimmy Kizito <Jimmy.Kizito@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/resource.h

index b113e7e..e762fce 100644 (file)
@@ -296,6 +296,75 @@ failed_alloc:
        return false;
 }
 
+/* Create additional DIG link encoder objects if fewer than the platform
+ * supports were created during link construction. This can happen if the
+ * number of physical connectors is less than the number of DIGs.
+ */
+static bool create_link_encoders(struct dc *dc)
+{
+       bool res = true;
+       unsigned int num_usb4_dpia = dc->res_pool->res_cap->num_usb4_dpia;
+       unsigned int num_dig_link_enc = dc->res_pool->res_cap->num_dig_link_enc;
+       int i;
+
+       /* A platform without USB4 DPIA endpoints has a fixed mapping between DIG
+        * link encoders and physical display endpoints and does not require
+        * additional link encoder objects.
+        */
+       if (num_usb4_dpia == 0)
+               return res;
+
+       /* Create as many link encoder objects as the platform supports. DPIA
+        * endpoints can be programmably mapped to any DIG.
+        */
+       if (num_dig_link_enc > dc->res_pool->dig_link_enc_count) {
+               for (i = 0; i < num_dig_link_enc; i++) {
+                       struct link_encoder *link_enc = dc->res_pool->link_encoders[i];
+
+                       if (!link_enc && dc->res_pool->funcs->link_enc_create_minimal) {
+                               link_enc = dc->res_pool->funcs->link_enc_create_minimal(dc->ctx,
+                                               (enum engine_id)(ENGINE_ID_DIGA + i));
+                               if (link_enc) {
+                                       dc->res_pool->link_encoders[i] = link_enc;
+                                       dc->res_pool->dig_link_enc_count++;
+                               } else {
+                                       res = false;
+                               }
+                       }
+               }
+       }
+
+       return res;
+}
+
+/* Destroy any additional DIG link encoder objects created by
+ * create_link_encoders().
+ * NB: Must only be called after destroy_links().
+ */
+static void destroy_link_encoders(struct dc *dc)
+{
+       unsigned int num_usb4_dpia = dc->res_pool->res_cap->num_usb4_dpia;
+       unsigned int num_dig_link_enc = dc->res_pool->res_cap->num_dig_link_enc;
+       int i;
+
+       /* A platform without USB4 DPIA endpoints has a fixed mapping between DIG
+        * link encoders and physical display endpoints and does not require
+        * additional link encoder objects.
+        */
+       if (num_usb4_dpia == 0)
+               return;
+
+       for (i = 0; i < num_dig_link_enc; i++) {
+               struct link_encoder *link_enc = dc->res_pool->link_encoders[i];
+
+               if (link_enc) {
+                       link_enc->funcs->destroy(&link_enc);
+                       dc->res_pool->link_encoders[i] = NULL;
+                       dc->res_pool->dig_link_enc_count--;
+               }
+       }
+}
+
 static struct dc_perf_trace *dc_perf_trace_create(void)
 {
        return kzalloc(sizeof(struct dc_perf_trace), GFP_KERNEL);
@@ -729,6 +798,8 @@ static void dc_destruct(struct dc *dc)
 
        destroy_links(dc);
 
+       destroy_link_encoders(dc);
+
        if (dc->clk_mgr) {
                dc_destroy_clk_mgr(dc->clk_mgr);
                dc->clk_mgr = NULL;
@@ -933,6 +1004,12 @@ static bool dc_construct(struct dc *dc,
        if (!create_links(dc, init_params->num_virtual_links))
                goto fail;
 
+       /* Create additional DIG link encoder objects if fewer than the platform
+        * supports were created during link construction.
+        */
+       if (!create_link_encoders(dc))
+               goto fail;
+
        /* Initialise DIG link encoder resource tracking variables. */
        link_enc_cfg_init(dc, dc->current_state);
 
index 0fea258..ed09af2 100644 (file)
@@ -245,6 +245,8 @@ struct resource_pool {
         * entries in link_encoders array.
         */
        unsigned int dig_link_enc_count;
+       /* Number of USB4 DPIA (DisplayPort Input Adapter) link objects created.*/
+       unsigned int usb4_dpia_count;
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        unsigned int hpo_dp_stream_enc_count;
index 3fbda9d..372c089 100644 (file)
@@ -49,6 +49,7 @@ struct resource_caps {
        int num_vmid;
        int num_dsc;
        unsigned int num_dig_link_enc; // Total number of DIGs (digital encoders) in DIO (Display Input/Output).
+       unsigned int num_usb4_dpia; // Total number of USB4 DPIA (DisplayPort Input Adapters).
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        int num_hpo_dp_stream_encoder;
        int num_hpo_dp_link_encoder;