]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Add concept of analog encoders (v2)
authorTimur Kristóf <timur.kristof@gmail.com>
Fri, 26 Sep 2025 18:01:50 +0000 (20:01 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 28 Oct 2025 14:09:03 +0000 (10:09 -0400)
Add a num_analog_stream_encoders field to indicate how many
analog stream encoders are present. When analog stream encoders
are present, create them.

Additionally, add an analog_engine field to link encoders and
search for supported analog encoders in the BIOS for each link.
When connecting an RGB signal, search for analog stream encoders.

The actual DCE analog link and stream encoder is going to be
added in a subsequent commit.

v2:
Add check to see if an analog engine is really supported.

Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
drivers/gpu/drm/amd/display/dc/inc/resource.h
drivers/gpu/drm/amd/display/dc/link/link_factory.c
drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c

index 89fe72820f6a1e21e8196d2a94ad9d22f36ae538..dc0c4065a92cb20cd1e390d883bc2eaa6cdd1a73 100644 (file)
@@ -446,6 +446,14 @@ bool resource_construct(
                                DC_ERR("DC: failed to create stream_encoder!\n");
                        pool->stream_enc_count++;
                }
+
+               for (i = 0; i < caps->num_analog_stream_encoder; i++) {
+                       pool->stream_enc[caps->num_stream_encoder + i] =
+                               create_funcs->create_stream_encoder(ENGINE_ID_DACA + i, ctx);
+                       if (pool->stream_enc[caps->num_stream_encoder + i] == NULL)
+                               DC_ERR("DC: failed to create analog stream_encoder %d!\n", i);
+                       pool->stream_enc_count++;
+               }
        }
 
        pool->hpo_dp_stream_enc_count = 0;
index 08c16ba52a51f0fc1505aab0556d4982a53d1c23..df512920a9fabe43d80257755a7a6b63a1135be1 100644 (file)
@@ -47,6 +47,7 @@ struct encoder_init_data {
        enum hpd_source_id hpd_source;
        /* TODO: in DAL2, here was pointer to EventManagerInterface */
        struct graphics_object_id encoder;
+       enum engine_id analog_engine;
        struct dc_context *ctx;
        enum transmitter transmitter;
 };
@@ -83,6 +84,7 @@ struct link_encoder {
        struct graphics_object_id connector;
        uint32_t output_signals;
        enum engine_id preferred_engine;
+       enum engine_id analog_engine;
        struct encoder_feature_support features;
        enum transmitter transmitter;
        enum hpd_source_id hpd_source;
index 4e26a16a8743f994447718f32722db8f39db3619..79746d931471a879b98e2aa9aa2585b170750fee 100644 (file)
@@ -49,6 +49,7 @@ struct resource_caps {
        int num_video_plane;
        int num_audio;
        int num_stream_encoder;
+       int num_analog_stream_encoder;
        int num_pll;
        int num_dwb;
        int num_ddc;
index 8899797f64a9c73f0cf3933725ae8edf2ac6e5bc..ebc3798e7d25de639e82a4fb79861953968992a1 100644 (file)
@@ -451,6 +451,32 @@ static enum channel_id get_ddc_line(struct dc_link *link)
        return channel;
 }
 
+static enum engine_id find_analog_engine(struct dc_link *link)
+{
+       struct dc_bios *bp = link->ctx->dc_bios;
+       struct graphics_object_id encoder = {0};
+       enum bp_result bp_result = BP_RESULT_OK;
+       int i;
+
+       for (i = 0; i < 3; i++) {
+               bp_result = bp->funcs->get_src_obj(bp, link->link_id, i, &encoder);
+
+               if (bp_result != BP_RESULT_OK)
+                       return ENGINE_ID_UNKNOWN;
+
+               switch (encoder.id) {
+               case ENCODER_ID_INTERNAL_DAC1:
+               case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+                       return ENGINE_ID_DACA;
+               case ENCODER_ID_INTERNAL_DAC2:
+               case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+                       return ENGINE_ID_DACB;
+               }
+       }
+
+       return ENGINE_ID_UNKNOWN;
+}
+
 static bool transmitter_supported(const enum transmitter transmitter)
 {
        return transmitter != TRANSMITTER_UNKNOWN &&
@@ -459,6 +485,12 @@ static bool transmitter_supported(const enum transmitter transmitter)
                transmitter != TRANSMITTER_TRAVIS_LCD;
 }
 
+static bool analog_engine_supported(const enum engine_id engine_id)
+{
+       return engine_id == ENGINE_ID_DACA ||
+               engine_id == ENGINE_ID_DACB;
+}
+
 static bool construct_phy(struct dc_link *link,
                              const struct link_init_data *init_params)
 {
@@ -495,8 +527,10 @@ static bool construct_phy(struct dc_link *link,
         */
        bp_funcs->get_src_obj(bios, link->link_id, 0, &enc_init_data.encoder);
        enc_init_data.transmitter = translate_encoder_to_transmitter(enc_init_data.encoder);
+       enc_init_data.analog_engine = find_analog_engine(link);
 
-       if (!transmitter_supported(enc_init_data.transmitter)) {
+       if (!transmitter_supported(enc_init_data.transmitter) &&
+               !analog_engine_supported(enc_init_data.analog_engine)) {
                DC_LOG_WARNING("link_id %d has unsupported encoder\n", link->link_id.id);
                return false;
        }
index 550466de1a6607432ac530313bb5c9eb1f346c77..7573f5130ea97643c6c6cfb75a9d8d6361b958c0 100644 (file)
@@ -954,6 +954,10 @@ struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link(
        int i;
        int j = -1;
        struct dc_link *link = stream->link;
+       enum engine_id preferred_engine = link->link_enc->preferred_engine;
+
+       if (dc_is_rgb_signal(stream->signal))
+               preferred_engine = link->link_enc->analog_engine;
 
        for (i = 0; i < pool->stream_enc_count; i++) {
                if (!res_ctx->is_stream_enc_acquired[i] &&
@@ -962,8 +966,7 @@ struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link(
                         * in daisy chain use case
                         */
                        j = i;
-                       if (pool->stream_enc[i]->id ==
-                                       link->link_enc->preferred_engine)
+                       if (pool->stream_enc[i]->id == preferred_engine)
                                return pool->stream_enc[i];
                }
        }