Both patches look good to me.

The series is Reviewed-by: Mikita Lipski <mikita.lip...@amd.com>

Thanks,
Mikita

On 2020-04-01 5:00 p.m., Bhawanpreet Lakha wrote:
[Why]
Query the hdcp caps of a link, it is useful and can be reported to the user

[How]
Create a query function and call it during link detect

Signed-off-by: Bhawanpreet Lakha <bhawanpreet.la...@amd.com>
---
  drivers/gpu/drm/amd/display/dc/core/dc_link.c | 56 ++++++++++++
  drivers/gpu/drm/amd/display/dc/dc.h           | 41 +++++++++
  drivers/gpu/drm/amd/display/dc/dc_link.h      |  3 +
  .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c    | 89 +++++++++++++++++++
  .../gpu/drm/amd/display/include/hdcp_types.h  |  7 ++
  5 files changed, 196 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index a93997ff0419..49c63e27dfe9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -514,6 +514,50 @@ static void link_disconnect_remap(struct dc_sink 
*prev_sink, struct dc_link *lin
        link->local_sink = prev_sink;
  }
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+static void query_hdcp_capability(enum signal_type signal, struct dc_link 
*link)
+{
+       struct hdcp_protection_message msg22;
+       struct hdcp_protection_message msg14;
+
+       memset(&msg22, 0, sizeof(struct hdcp_protection_message));
+       memset(&msg14, 0, sizeof(struct hdcp_protection_message));
+       memset(link->hdcp_caps.rx_caps.raw, 0,
+               sizeof(link->hdcp_caps.rx_caps.raw));
+
+       if ((link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
+                       link->ddc->transaction_type ==
+                       DDC_TRANSACTION_TYPE_I2C_OVER_AUX) ||
+                       link->connector_signal == SIGNAL_TYPE_EDP) {
+               msg22.data = link->hdcp_caps.rx_caps.raw;
+               msg22.length = sizeof(link->hdcp_caps.rx_caps.raw);
+               msg22.msg_id = HDCP_MESSAGE_ID_RX_CAPS;
+       } else {
+               msg22.data = &link->hdcp_caps.rx_caps.fields.version;
+               msg22.length = sizeof(link->hdcp_caps.rx_caps.fields.version);
+               msg22.msg_id = HDCP_MESSAGE_ID_HDCP2VERSION;
+       }
+       msg22.version = HDCP_VERSION_22;
+       msg22.link = HDCP_LINK_PRIMARY;
+       msg22.max_retries = 5;
+       dc_process_hdcp_msg(signal, link, &msg22);
+
+       if (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == 
SIGNAL_TYPE_DISPLAY_PORT_MST) {
+               enum hdcp_message_status status = HDCP_MESSAGE_UNSUPPORTED;
+
+               msg14.data = &link->hdcp_caps.bcaps.raw;
+               msg14.length = sizeof(link->hdcp_caps.bcaps.raw);
+               msg14.msg_id = HDCP_MESSAGE_ID_READ_BCAPS;
+               msg14.version = HDCP_VERSION_14;
+               msg14.link = HDCP_LINK_PRIMARY;
+               msg14.max_retries = 5;
+
+               status = dc_process_hdcp_msg(signal, link, &msg14);
+       }
+
+}
+#endif
+
  static void read_current_link_settings_on_detect(struct dc_link *link)
  {
        union lane_count_set lane_count_set = { {0} };
@@ -606,6 +650,12 @@ static bool detect_dp(struct dc_link *link,
                        dal_ddc_service_set_transaction_type(link->ddc,
                                                             
sink_caps->transaction_type);
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+                       /* In case of fallback to SST when topology discovery 
below fails
+                        * HDCP caps will be querried again later by the upper 
layer (caller
+                        * of this function). */
+                       query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, 
link);
+#endif
                        /*
                         * This call will initiate MST topology discovery. Which
                         * will detect MST ports and add new DRM connector DRM
@@ -975,6 +1025,9 @@ static bool dc_link_detect_helper(struct dc_link *link,
                         * TODO debug why Dell 2413 doesn't like
                         *  two link trainings
                         */
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+                       query_hdcp_capability(sink->sink_signal, link);
+#endif
// verify link cap for SST non-seamless boot
                        if (!perform_dp_seamless_boot)
@@ -988,6 +1041,9 @@ static bool dc_link_detect_helper(struct dc_link *link,
                                sink = prev_sink;
                                prev_sink = NULL;
                        }
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+                       query_hdcp_capability(sink->sink_signal, link);
+#endif
                }
/* HDMI-DVI Dongle */
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 92123b0d1196..9235d04c32dc 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -29,6 +29,9 @@
  #include "dc_types.h"
  #include "grph_object_defs.h"
  #include "logger_types.h"
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+#include "hdcp_types.h"
+#endif
  #include "gpio_types.h"
  #include "link_service_types.h"
  #include "grph_object_ctrl_defs.h"
@@ -1004,6 +1007,35 @@ union dpcd_sink_ext_caps {
        uint8_t raw;
  };
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+union hdcp_rx_caps {
+       struct {
+               uint8_t version;
+               uint8_t reserved;
+               struct {
+                       uint8_t repeater        : 1;
+                       uint8_t hdcp_capable    : 1;
+                       uint8_t reserved        : 6;
+               } byte0;
+       } fields;
+       uint8_t raw[3];
+};
+
+union hdcp_bcaps {
+       struct {
+               uint8_t HDCP_CAPABLE:1;
+               uint8_t REPEATER:1;
+               uint8_t RESERVED:6;
+       } bits;
+       uint8_t raw;
+};
+
+struct hdcp_caps {
+       union hdcp_rx_caps rx_caps;
+       union hdcp_bcaps bcaps;
+};
+#endif
+
  #include "dc_link.h"
/*******************************************************************************
@@ -1107,6 +1139,15 @@ void dc_resume(struct dc *dc);
  unsigned int dc_get_current_backlight_pwm(struct dc *dc);
  unsigned int dc_get_target_backlight_pwm(struct dc *dc);
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+/*
+ * HDCP Interfaces
+ */
+enum hdcp_message_status dc_process_hdcp_msg(
+               enum signal_type signal,
+               struct dc_link *link,
+               struct hdcp_protection_message *message_info);
+#endif
  bool dc_is_dmcu_initialized(struct dc *dc);
enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h 
b/drivers/gpu/drm/amd/display/dc/dc_link.h
index 00ff5e98278c..0077f9dcd07c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
@@ -126,6 +126,9 @@ struct dc_link {
        uint32_t dongle_max_pix_clk;
        unsigned short chip_caps;
        unsigned int dpcd_sink_count;
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+       struct hdcp_caps hdcp_caps;
+#endif
        enum edp_revision edp_revision;
        bool psr_feature_enabled;
        bool psr_allow_active;
diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c 
b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
index 6f730b5bfe42..5e384a8a83dc 100644
--- a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
+++ b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
@@ -322,3 +322,92 @@ static const struct protection_properties dp_11_protection 
= {
        .process_transaction = dp_11_process_transaction
  };
+static const struct protection_properties *get_protection_properties_by_signal(
+       struct dc_link *link,
+       enum signal_type st,
+       enum hdcp_version version)
+{
+       switch (version) {
+       case HDCP_VERSION_14:
+               switch (st) {
+               case SIGNAL_TYPE_DVI_SINGLE_LINK:
+               case SIGNAL_TYPE_DVI_DUAL_LINK:
+               case SIGNAL_TYPE_HDMI_TYPE_A:
+                       return &hdmi_14_protection;
+               case SIGNAL_TYPE_DISPLAY_PORT:
+                       if (link &&
+                               (link->dpcd_caps.dongle_type == 
DISPLAY_DONGLE_DP_VGA_CONVERTER ||
+                               link->dpcd_caps.dongle_caps.dongle_type == 
DISPLAY_DONGLE_DP_VGA_CONVERTER)) {
+                               return &non_supported_protection;
+                       }
+                       return &dp_11_protection;
+               case SIGNAL_TYPE_DISPLAY_PORT_MST:
+               case SIGNAL_TYPE_EDP:
+                       return &dp_11_protection;
+               default:
+                       return &non_supported_protection;
+               }
+               break;
+       case HDCP_VERSION_22:
+               switch (st) {
+               case SIGNAL_TYPE_DVI_SINGLE_LINK:
+               case SIGNAL_TYPE_DVI_DUAL_LINK:
+               case SIGNAL_TYPE_HDMI_TYPE_A:
+                       return &hdmi_14_protection; //todo version2.2
+               case SIGNAL_TYPE_DISPLAY_PORT:
+               case SIGNAL_TYPE_DISPLAY_PORT_MST:
+               case SIGNAL_TYPE_EDP:
+                       return &dp_11_protection;  //todo version2.2
+               default:
+                       return &non_supported_protection;
+               }
+               break;
+       default:
+               return &non_supported_protection;
+       }
+}
+
+enum hdcp_message_status dc_process_hdcp_msg(
+       enum signal_type signal,
+       struct dc_link *link,
+       struct hdcp_protection_message *message_info)
+{
+       enum hdcp_message_status status = HDCP_MESSAGE_FAILURE;
+       uint32_t i = 0;
+
+       const struct protection_properties *protection_props;
+
+       if (!message_info)
+               return HDCP_MESSAGE_UNSUPPORTED;
+
+       if (message_info->msg_id < HDCP_MESSAGE_ID_READ_BKSV ||
+               message_info->msg_id >= HDCP_MESSAGE_ID_MAX)
+               return HDCP_MESSAGE_UNSUPPORTED;
+
+       protection_props =
+               get_protection_properties_by_signal(
+                       link,
+                       signal,
+                       message_info->version);
+
+       if (!protection_props->supported)
+               return HDCP_MESSAGE_UNSUPPORTED;
+
+       if (protection_props->process_transaction(
+               link,
+               message_info)) {
+               status = HDCP_MESSAGE_SUCCESS;
+       } else {
+               for (i = 0; i < message_info->max_retries; i++) {
+                       if (protection_props->process_transaction(
+                                               link,
+                                               message_info)) {
+                               status = HDCP_MESSAGE_SUCCESS;
+                               break;
+                       }
+               }
+       }
+
+       return status;
+}
+
diff --git a/drivers/gpu/drm/amd/display/include/hdcp_types.h 
b/drivers/gpu/drm/amd/display/include/hdcp_types.h
index f31e6befc8d6..42229b4effdc 100644
--- a/drivers/gpu/drm/amd/display/include/hdcp_types.h
+++ b/drivers/gpu/drm/amd/display/include/hdcp_types.h
@@ -83,6 +83,12 @@ enum hdcp_link {
        HDCP_LINK_SECONDARY
  };
+enum hdcp_message_status {
+       HDCP_MESSAGE_SUCCESS,
+       HDCP_MESSAGE_FAILURE,
+       HDCP_MESSAGE_UNSUPPORTED
+};
+
  struct hdcp_protection_message {
        enum hdcp_version version;
        /* relevant only for DVI */
@@ -91,6 +97,7 @@ struct hdcp_protection_message {
        uint32_t length;
        uint8_t max_retries;
        uint8_t *data;
+       enum hdcp_message_status status;
  };
#endif

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to