diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0745-drm-amd-dal-Relocate-dcs-to-core.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0745-drm-amd-dal-Relocate-dcs-to-core.patch | 2876 |
1 files changed, 2876 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0745-drm-amd-dal-Relocate-dcs-to-core.patch b/common/recipes-kernel/linux/files/0745-drm-amd-dal-Relocate-dcs-to-core.patch new file mode 100644 index 00000000..676b4d66 --- /dev/null +++ b/common/recipes-kernel/linux/files/0745-drm-amd-dal-Relocate-dcs-to-core.patch @@ -0,0 +1,2876 @@ +From c342d6c1517ab16a7ac2c2e1211249339d8b6929 Mon Sep 17 00:00:00 2001 +From: Chris Park <Chris.Park@amd.com> +Date: Wed, 27 Jan 2016 16:14:24 -0500 +Subject: [PATCH 0745/1110] drm/amd/dal: Relocate dcs to core + +Ddc service and I2caux helper moved to dc_link_ddc. + +Signed-off-by: Chris Park <Chris.Park@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +--- + drivers/gpu/drm/amd/dal/dc/Makefile | 4 +- + drivers/gpu/drm/amd/dal/dc/core/dc.c | 2 +- + drivers/gpu/drm/amd/dal/dc/core/dc_link.c | 2 +- + drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c | 1151 ++++++++++++++++++++ + drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c | 2 +- + drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c | 2 +- + drivers/gpu/drm/amd/dal/dc/dcs/Makefile | 10 - + drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c | 159 --- + drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h | 60 - + drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c | 1036 ------------------ + drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h | 49 - + drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h | 151 +++ + .../drm/amd/dal/include/ddc_service_interface.h | 100 -- + 13 files changed, 1308 insertions(+), 1420 deletions(-) + create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/Makefile + delete mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h + create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h + delete mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_interface.h + +diff --git a/drivers/gpu/drm/amd/dal/dc/Makefile b/drivers/gpu/drm/amd/dal/dc/Makefile +index 4396203..aed26ee 100644 +--- a/drivers/gpu/drm/amd/dal/dc/Makefile ++++ b/drivers/gpu/drm/amd/dal/dc/Makefile +@@ -3,7 +3,7 @@ + # + + DC_LIBS = adapter asic_capability audio basics bios calcs \ +-dcs gpio gpu i2caux irq virtual ++gpio gpu i2caux irq virtual + + ifdef CONFIG_DRM_AMD_DAL_DCE11_0 + DC_LIBS += dce110 +@@ -18,7 +18,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/dc/,$(DC_LIBS)) + include $(AMD_DC) + + DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_target.o dc_sink.o dc_stream.o \ +-dc_hw_sequencer.o dc_surface.o dc_link_hwss.o dc_link_dp.o ++dc_hw_sequencer.o dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o + + AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) + +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c +index b3c919c..770a66c 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c +@@ -45,7 +45,7 @@ + #include "link_hwss.h" + #include "link_encoder.h" + +-#include "dcs/ddc_service.h" ++#include "dc_link_ddc.h" + + /******************************************************************************* + * Private structures +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c +index c81f4a2..71653fa 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c +@@ -30,9 +30,9 @@ + #include "adapter_service_interface.h" + #include "grph_object_id.h" + #include "gpio_service_interface.h" +-#include "ddc_service_interface.h" + #include "core_status.h" + #include "dc_link_dp.h" ++#include "dc_link_ddc.h" + #include "link_hwss.h" + #include "stream_encoder.h" + #include "link_encoder.h" +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c +new file mode 100644 +index 0000000..60fc743 +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c +@@ -0,0 +1,1151 @@ ++/* ++ * Copyright 2012-15 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#include "dc_services.h" ++ ++#include "include/adapter_service_interface.h" ++#include "include/ddc_service_types.h" ++#include "include/grph_object_id.h" ++#include "include/dpcd_defs.h" ++#include "include/logger_interface.h" ++#include "include/vector.h" ++ ++#include "dc_link_ddc.h" ++ ++#define AUX_POWER_UP_WA_DELAY 500 ++#define I2C_OVER_AUX_DEFER_WA_DELAY 70 ++ ++/* CV smart dongle slave address for retrieving supported HDTV modes*/ ++#define CV_SMART_DONGLE_ADDRESS 0x20 ++/* DVI-HDMI dongle slave address for retrieving dongle signature*/ ++#define DVI_HDMI_DONGLE_ADDRESS 0x68 ++static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G"; ++struct dvi_hdmi_dongle_signature_data { ++ int8_t vendor[3];/* "AMD" */ ++ uint8_t version[2]; ++ uint8_t size; ++ int8_t id[11];/* "6140063500G"*/ ++}; ++/* DP-HDMI dongle slave address for retrieving dongle signature*/ ++#define DP_HDMI_DONGLE_ADDRESS 0x40 ++static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR"; ++#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04 ++ ++struct dp_hdmi_dongle_signature_data { ++ int8_t id[15];/* "DP-HDMI ADAPTOR"*/ ++ uint8_t eot;/* end of transmition '\x4' */ ++}; ++ ++/* Address range from 0x00 to 0x1F.*/ ++#define DP_ADAPTOR_TYPE2_SIZE 0x20 ++#define DP_ADAPTOR_TYPE2_REG_ID 0x10 ++#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D ++/* Identifies adaptor as Dual-mode adaptor */ ++#define DP_ADAPTOR_TYPE2_ID 0xA0 ++/* MHz*/ ++#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 ++/* MHz*/ ++#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 ++/* kHZ*/ ++#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 ++/* kHZ*/ ++#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 ++ ++#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW ++ ++enum edid_read_result { ++ EDID_READ_RESULT_EDID_MATCH = 0, ++ EDID_READ_RESULT_EDID_MISMATCH, ++ EDID_READ_RESULT_CHECKSUM_READ_ERR, ++ EDID_READ_RESULT_VENDOR_READ_ERR ++}; ++ ++/* SCDC Address defines (HDMI 2.0)*/ ++#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 ++#define HDMI_SCDC_ADDRESS 0x54 ++#define HDMI_SCDC_SINK_VERSION 0x01 ++#define HDMI_SCDC_SOURCE_VERSION 0x02 ++#define HDMI_SCDC_UPDATE_0 0x10 ++#define HDMI_SCDC_TMDS_CONFIG 0x20 ++#define HDMI_SCDC_SCRAMBLER_STATUS 0x21 ++#define HDMI_SCDC_CONFIG_0 0x30 ++#define HDMI_SCDC_STATUS_FLAGS 0x40 ++#define HDMI_SCDC_ERR_DETECT 0x50 ++#define HDMI_SCDC_TEST_CONFIG 0xC0 ++ ++ ++union hdmi_scdc_update_read_data { ++ uint8_t byte[2]; ++ struct { ++ uint8_t STATUS_UPDATE:1; ++ uint8_t CED_UPDATE:1; ++ uint8_t RR_TEST:1; ++ uint8_t RESERVED:5; ++ uint8_t RESERVED2:8; ++ } fields; ++}; ++ ++union hdmi_scdc_status_flags_data { ++ uint8_t byte[2]; ++ struct { ++ uint8_t CLOCK_DETECTED:1; ++ uint8_t CH0_LOCKED:1; ++ uint8_t CH1_LOCKED:1; ++ uint8_t CH2_LOCKED:1; ++ uint8_t RESERVED:4; ++ uint8_t RESERVED2:8; ++ } fields; ++}; ++ ++union hdmi_scdc_ced_data { ++ uint8_t byte[7]; ++ struct { ++ uint8_t CH0_8LOW:8; ++ uint8_t CH0_7HIGH:7; ++ uint8_t CH0_VALID:1; ++ uint8_t CH1_8LOW:8; ++ uint8_t CH1_7HIGH:7; ++ uint8_t CH1_VALID:1; ++ uint8_t CH2_8LOW:8; ++ uint8_t CH2_7HIGH:7; ++ uint8_t CH2_VALID:1; ++ uint8_t CHECKSUM:8; ++ } fields; ++}; ++ ++union hdmi_scdc_test_config_Data { ++ uint8_t byte; ++ struct { ++ uint8_t TEST_READ_REQUEST_DELAY:7; ++ uint8_t TEST_READ_REQUEST: 1; ++ } fields; ++}; ++ ++ ++ ++union ddc_wa { ++ struct { ++ uint32_t DP_SKIP_POWER_OFF:1; ++ uint32_t DP_AUX_POWER_UP_WA_DELAY:1; ++ } bits; ++ uint32_t raw; ++}; ++ ++struct ddc_flags { ++ uint8_t EDID_QUERY_DONE_ONCE:1; ++ uint8_t IS_INTERNAL_DISPLAY:1; ++ uint8_t FORCE_READ_REPEATED_START:1; ++ uint8_t EDID_STRESS_READ:1; ++ ++}; ++ ++struct ddc_service { ++ struct ddc *ddc_pin; ++ struct ddc_flags flags; ++ union ddc_wa wa; ++ enum ddc_transaction_type transaction_type; ++ enum display_dongle_type dongle_type; ++ struct dp_receiver_id_info dp_receiver_id_info; ++ struct adapter_service *as; ++ struct dc_context *ctx; ++ ++ uint32_t address; ++ uint32_t edid_buf_len; ++ uint8_t edid_buf[MAX_EDID_BUFFER_SIZE]; ++}; ++ ++struct i2c_payloads { ++ struct vector payloads; ++}; ++ ++struct aux_payloads { ++ struct vector payloads; ++}; ++ ++struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) ++{ ++ struct i2c_payloads *payloads; ++ ++ payloads = dc_service_alloc(ctx, sizeof(struct i2c_payloads)); ++ ++ if (!payloads) ++ return NULL; ++ ++ if (dal_vector_construct( ++ &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) ++ return payloads; ++ ++ dc_service_free(ctx, payloads); ++ return NULL; ++ ++} ++ ++struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) ++{ ++ return (struct i2c_payload *)p->payloads.container; ++} ++ ++uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) ++{ ++ return p->payloads.count; ++} ++ ++void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) ++{ ++ if (!p || !*p) ++ return; ++ dal_vector_destruct(&(*p)->payloads); ++ dc_service_free((*p)->payloads.ctx, *p); ++ *p = NULL; ++ ++} ++ ++struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) ++{ ++ struct aux_payloads *payloads; ++ ++ payloads = dc_service_alloc(ctx, sizeof(struct aux_payloads)); ++ ++ if (!payloads) ++ return NULL; ++ ++ if (dal_vector_construct( ++ &payloads->payloads, ctx, count, sizeof(struct aux_payloads))) ++ return payloads; ++ ++ dc_service_free(ctx, payloads); ++ return NULL; ++} ++ ++struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) ++{ ++ return (struct aux_payload *)p->payloads.container; ++} ++ ++uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) ++{ ++ return p->payloads.count; ++} ++ ++ ++void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) ++{ ++ if (!p || !*p) ++ return; ++ ++ dal_vector_destruct(&(*p)->payloads); ++ dc_service_free((*p)->payloads.ctx, *p); ++ *p = NULL; ++} ++ ++#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) ++ ++void dal_ddc_i2c_payloads_add( ++ struct i2c_payloads *payloads, ++ uint32_t address, ++ uint32_t len, ++ uint8_t *data, ++ bool write) ++{ ++ uint32_t payload_size = EDID_SEGMENT_SIZE; ++ uint32_t pos; ++ ++ for (pos = 0; pos < len; pos += payload_size) { ++ struct i2c_payload payload = { ++ .write = write, ++ .address = address, ++ .length = DDC_MIN(payload_size, len - pos), ++ .data = data + pos }; ++ dal_vector_append(&payloads->payloads, &payload); ++ } ++ ++} ++ ++void dal_ddc_aux_payloads_add( ++ struct aux_payloads *payloads, ++ uint32_t address, ++ uint32_t len, ++ uint8_t *data, ++ bool write) ++{ ++ uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE; ++ uint32_t pos; ++ ++ for (pos = 0; pos < len; pos += payload_size) { ++ struct aux_payload payload = { ++ .i2c_over_aux = true, ++ .write = write, ++ .address = address, ++ .length = DDC_MIN(payload_size, len - pos), ++ .data = data + pos }; ++ dal_vector_append(&payloads->payloads, &payload); ++ } ++} ++ ++ ++static bool construct( ++ struct ddc_service *ddc_service, ++ struct ddc_service_init_data *init_data) ++{ ++ enum connector_id connector_id = ++ dal_graphics_object_id_get_connector_id(init_data->id); ++ ++ ddc_service->ctx = init_data->ctx; ++ ddc_service->as = init_data->as; ++ ddc_service->ddc_pin = dal_adapter_service_obtain_ddc( ++ init_data->as, init_data->id); ++ ++ ddc_service->flags.EDID_QUERY_DONE_ONCE = false; ++ ++ ddc_service->flags.FORCE_READ_REPEATED_START = ++ dal_adapter_service_is_feature_supported( ++ FEATURE_DDC_READ_FORCE_REPEATED_START); ++ ++ ddc_service->flags.EDID_STRESS_READ = ++ dal_adapter_service_is_feature_supported( ++ FEATURE_EDID_STRESS_READ); ++ ++ ++ ddc_service->flags.IS_INTERNAL_DISPLAY = ++ connector_id == CONNECTOR_ID_EDP || ++ connector_id == CONNECTOR_ID_LVDS; ++ ++ ddc_service->wa.raw = 0; ++ return true; ++} ++ ++struct ddc_service *dal_ddc_service_create( ++ struct ddc_service_init_data *init_data) ++{ ++ struct ddc_service *ddc_service; ++ ++ ddc_service = dc_service_alloc(init_data->ctx, sizeof(struct ddc_service)); ++ ++ if (!ddc_service) ++ return NULL; ++ ++ if (construct(ddc_service, init_data)) ++ return ddc_service; ++ ++ dc_service_free(init_data->ctx, ddc_service); ++ return NULL; ++} ++ ++static void destruct(struct ddc_service *ddc) ++{ ++ if (ddc->ddc_pin) ++ dal_adapter_service_release_ddc(ddc->as, ddc->ddc_pin); ++} ++ ++void dal_ddc_service_destroy(struct ddc_service **ddc) ++{ ++ if (!ddc || !*ddc) { ++ BREAK_TO_DEBUGGER(); ++ return; ++ } ++ destruct(*ddc); ++ dc_service_free((*ddc)->ctx, *ddc); ++ *ddc = NULL; ++} ++ ++enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc) ++{ ++ return DDC_SERVICE_TYPE_CONNECTOR; ++} ++ ++void dal_ddc_service_set_transaction_type( ++ struct ddc_service *ddc, ++ enum ddc_transaction_type type) ++{ ++ ddc->transaction_type = type; ++} ++ ++bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc) ++{ ++ switch (ddc->transaction_type) { ++ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: ++ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: ++ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER: ++ return true; ++ default: ++ break; ++ } ++ return false; ++} ++ ++void ddc_service_set_dongle_type(struct ddc_service *ddc, ++ enum display_dongle_type dongle_type) ++{ ++ ddc->dongle_type = dongle_type; ++} ++ ++static uint32_t defer_delay_converter_wa( ++ struct ddc_service *ddc, ++ uint32_t defer_delay) ++{ ++ struct dp_receiver_id_info dp_rec_info = {0}; ++ ++ if (dal_ddc_service_get_dp_receiver_id_info(ddc, &dp_rec_info) && ++ (dp_rec_info.branch_id == DP_BRANCH_DEVICE_ID_4) && ++ !dal_strncmp(dp_rec_info.branch_name, ++ DP_DVI_CONVERTER_ID_4, ++ sizeof(dp_rec_info.branch_name))) ++ return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ? ++ defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY; ++ ++ return defer_delay; ++ ++} ++ ++#define DP_TRANSLATOR_DELAY 5 ++ ++static uint32_t get_defer_delay(struct ddc_service *ddc) ++{ ++ uint32_t defer_delay = 0; ++ ++ switch (ddc->transaction_type) { ++ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: ++ if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) || ++ (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) || ++ (DISPLAY_DONGLE_DP_HDMI_CONVERTER == ++ ddc->dongle_type)) { ++ ++ defer_delay = DP_TRANSLATOR_DELAY; ++ ++ defer_delay = ++ defer_delay_converter_wa(ddc, defer_delay); ++ ++ } else /*sink has a delay different from an Active Converter*/ ++ defer_delay = 0; ++ break; ++ case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: ++ defer_delay = DP_TRANSLATOR_DELAY; ++ break; ++ default: ++ break; ++ } ++ return defer_delay; ++} ++ ++static bool i2c_read( ++ struct ddc_service *ddc, ++ uint32_t address, ++ uint8_t *buffer, ++ uint32_t len) ++{ ++ uint8_t offs_data = 0; ++ struct i2c_payload payloads[2] = { ++ { ++ .write = true, ++ .address = address, ++ .length = 1, ++ .data = &offs_data }, ++ { ++ .write = false, ++ .address = address, ++ .length = len, ++ .data = buffer } }; ++ ++ struct i2c_command command = { ++ .payloads = payloads, ++ .number_of_payloads = 2, ++ .engine = DDC_I2C_COMMAND_ENGINE, ++ .speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) }; ++ ++ return dal_i2caux_submit_i2c_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &command); ++} ++ ++static uint8_t aux_read_edid_block( ++ struct ddc_service *ddc, ++ uint8_t address, ++ uint8_t index, ++ uint8_t *buf) ++{ ++ struct aux_command cmd = { ++ .payloads = NULL, ++ .number_of_payloads = 0, ++ .defer_delay = get_defer_delay(ddc), ++ .max_defer_write_retry = 0 }; ++ ++ uint8_t retrieved = 0; ++ uint8_t base_offset = ++ (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; ++ uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; ++ ++ for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; ++ retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { ++ ++ uint8_t offset = base_offset + retrieved; ++ ++ struct aux_payload payloads[3] = { ++ { ++ .i2c_over_aux = true, ++ .write = true, ++ .address = DDC_EDID_SEGMENT_ADDRESS, ++ .length = 1, ++ .data = &segment }, ++ { ++ .i2c_over_aux = true, ++ .write = true, ++ .address = address, ++ .length = 1, ++ .data = &offset }, ++ { ++ .i2c_over_aux = true, ++ .write = false, ++ .address = address, ++ .length = DEFAULT_AUX_MAX_DATA_SIZE, ++ .data = &buf[retrieved] } }; ++ ++ if (segment == 0) { ++ cmd.payloads = &payloads[1]; ++ cmd.number_of_payloads = 2; ++ } else { ++ cmd.payloads = payloads; ++ cmd.number_of_payloads = 3; ++ } ++ ++ if (!dal_i2caux_submit_aux_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &cmd)) ++ /* cannot read, break*/ ++ break; ++ } ++ ++ /* Reset segment to 0. Needed by some panels */ ++ if (0 != segment) { ++ struct aux_payload payloads[1] = { { ++ .i2c_over_aux = true, ++ .write = true, ++ .address = DDC_EDID_SEGMENT_ADDRESS, ++ .length = 1, ++ .data = &segment } }; ++ bool result = false; ++ ++ segment = 0; ++ ++ cmd.number_of_payloads = ARRAY_SIZE(payloads); ++ cmd.payloads = payloads; ++ ++ result = dal_i2caux_submit_aux_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &cmd); ++ ++ if (false == result) ++ dal_logger_write( ++ ddc->ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, ++ "%s: Writing of EDID Segment (0x30) failed!\n", ++ __func__); ++ } ++ ++ return retrieved; ++} ++ ++static uint8_t i2c_read_edid_block( ++ struct ddc_service *ddc, ++ uint8_t address, ++ uint8_t index, ++ uint8_t *buf) ++{ ++ bool ret = false; ++ uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * ++ DDC_EDID_BLOCK_SIZE; ++ uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; ++ ++ struct i2c_command cmd = { ++ .payloads = NULL, ++ .number_of_payloads = 0, ++ .engine = DDC_I2C_COMMAND_ENGINE, ++ .speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) }; ++ ++ struct i2c_payload payloads[3] = { ++ { ++ .write = true, ++ .address = DDC_EDID_SEGMENT_ADDRESS, ++ .length = 1, ++ .data = &segment }, ++ { ++ .write = true, ++ .address = address, ++ .length = 1, ++ .data = &offset }, ++ { ++ .write = false, ++ .address = address, ++ .length = DDC_EDID_BLOCK_SIZE, ++ .data = buf } }; ++/* ++ * Some I2C engines don't handle stop/start between write-offset and read-data ++ * commands properly. For those displays, we have to force the newer E-DDC ++ * behavior of repeated-start which can be enabled by runtime parameter. */ ++/* Originally implemented for OnLive using NXP receiver chip */ ++ ++ if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { ++ /* base block, use use DDC2B, submit as 2 commands */ ++ cmd.payloads = &payloads[1]; ++ cmd.number_of_payloads = 1; ++ ++ if (dal_i2caux_submit_i2c_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &cmd)) { ++ ++ cmd.payloads = &payloads[2]; ++ cmd.number_of_payloads = 1; ++ ++ ret = dal_i2caux_submit_i2c_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &cmd); ++ } ++ ++ } else { ++ /* ++ * extension block use E-DDC, submit as 1 command ++ * or if repeated-start is forced by runtime parameter ++ */ ++ if (segment != 0) { ++ /* include segment offset in command*/ ++ cmd.payloads = payloads; ++ cmd.number_of_payloads = 3; ++ } else { ++ /* we are reading first segment, ++ * segment offset is not required */ ++ cmd.payloads = &payloads[1]; ++ cmd.number_of_payloads = 2; ++ } ++ ++ ret = dal_i2caux_submit_i2c_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &cmd); ++ } ++ ++ return ret ? DDC_EDID_BLOCK_SIZE : 0; ++} ++ ++static uint32_t query_edid_block( ++ struct ddc_service *ddc, ++ uint8_t address, ++ uint8_t index, ++ uint8_t *buf, ++ uint32_t size) ++{ ++ uint32_t size_retrieved = 0; ++ ++ if (size < DDC_EDID_BLOCK_SIZE) ++ return 0; ++ ++ if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { ++ ++ ASSERT(index < 2); ++ size_retrieved = ++ aux_read_edid_block(ddc, address, index, buf); ++ } else { ++ size_retrieved = ++ i2c_read_edid_block(ddc, address, index, buf); ++ } ++ ++ return size_retrieved; ++} ++ ++#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 ++#define DDC_TEST_ACK_ADDRESS 0x260 ++#define DDC_DPCD_EDID_TEST_ACK 0x04 ++#define DDC_DPCD_EDID_TEST_MASK 0x04 ++#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 ++ ++/* AG TODO GO throug DM callback here like for DPCD */ ++ ++static void write_dp_edid_checksum( ++ struct ddc_service *ddc, ++ uint8_t checksum) ++{ ++ uint8_t dpcd_data; ++ ++ dal_ddc_service_read_dpcd_data( ++ ddc, ++ DDC_DPCD_TEST_REQUEST_ADDRESS, ++ &dpcd_data, ++ 1); ++ ++ if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) { ++ ++ dal_ddc_service_write_dpcd_data( ++ ddc, ++ DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS, ++ &checksum, ++ 1); ++ ++ dpcd_data = DDC_DPCD_EDID_TEST_ACK; ++ ++ dal_ddc_service_write_dpcd_data( ++ ddc, ++ DDC_TEST_ACK_ADDRESS, ++ &dpcd_data, ++ 1); ++ } ++} ++ ++uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc) ++{ ++ uint32_t bytes_read = 0; ++ uint32_t ext_cnt = 0; ++ ++ uint8_t address; ++ uint32_t i; ++ ++ for (address = DDC_EDID_ADDRESS_START; ++ address <= DDC_EDID_ADDRESS_END; ++address) { ++ ++ bytes_read = query_edid_block( ++ ddc, ++ address, ++ 0, ++ ddc->edid_buf, ++ sizeof(ddc->edid_buf) - bytes_read); ++ ++ if (bytes_read != DDC_EDID_BLOCK_SIZE) ++ continue; ++ ++ /* get the number of ext blocks*/ ++ ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET]; ++ ++ /* EDID 2.0, need to read 1 more block because EDID2.0 is ++ * 256 byte in size*/ ++ if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] == ++ DDC_EDID_20_SIGNATURE) ++ ext_cnt = 1; ++ ++ for (i = 0; i < ext_cnt; i++) { ++ /* read additional ext blocks accordingly */ ++ bytes_read += query_edid_block( ++ ddc, ++ address, ++ i+1, ++ &ddc->edid_buf[bytes_read], ++ sizeof(ddc->edid_buf) - bytes_read); ++ } ++ ++ /*this is special code path for DP compliance*/ ++ if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type) ++ write_dp_edid_checksum( ++ ddc, ++ ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) + ++ DDC_EDID1X_CHECKSUM_OFFSET]); ++ ++ /*remembers the address where we fetch the EDID from ++ * for later signature check use */ ++ ddc->address = address; ++ ++ break;/* already read edid, done*/ ++ } ++ ++ ddc->edid_buf_len = bytes_read; ++ return bytes_read; ++} ++ ++uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc) ++{ ++ return ddc->edid_buf_len; ++} ++ ++void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf) ++{ ++ dc_service_memmove(edid_buf, ++ ddc->edid_buf, ddc->edid_buf_len); ++} ++ ++void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( ++ struct ddc_service *ddc, ++ struct display_sink_capability *sink_cap) ++{ ++ uint8_t i; ++ bool is_valid_hdmi_signature; ++ enum display_dongle_type *dongle = &sink_cap->dongle_type; ++ uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE]; ++ bool is_type2_dongle = false; ++ struct dp_hdmi_dongle_signature_data *dongle_signature; ++ ++ /* Assume we have no valid DP passive dongle connected */ ++ *dongle = DISPLAY_DONGLE_NONE; ++ sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK; ++ ++ /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/ ++ if (!i2c_read( ++ ddc, ++ DP_HDMI_DONGLE_ADDRESS, ++ type2_dongle_buf, ++ sizeof(type2_dongle_buf))) { ++ dal_logger_write(ddc->ctx->logger, ++ LOG_MAJOR_DCS, ++ LOG_MINOR_DCS_DONGLE_DETECTION, ++ "Detected DP-DVI dongle.\n"); ++ *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; ++ sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; ++ return; ++ } ++ ++ /* Check if Type 2 dongle.*/ ++ if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID) ++ is_type2_dongle = true; ++ ++ dongle_signature = ++ (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf; ++ ++ is_valid_hdmi_signature = true; ++ ++ /* Check EOT */ ++ if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) { ++ is_valid_hdmi_signature = false; ++ } ++ ++ /* Check signature */ ++ for (i = 0; i < sizeof(dongle_signature->id); ++i) { ++ /* If its not the right signature, ++ * skip mismatch in subversion byte.*/ ++ if (dongle_signature->id[i] != ++ dp_hdmi_dongle_signature_str[i] && i != 3) { ++ ++ if (is_type2_dongle) { ++ is_valid_hdmi_signature = false; ++ break; ++ } ++ ++ } ++ } ++ ++ if (is_type2_dongle) { ++ uint32_t max_tmds_clk = ++ type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK]; ++ ++ max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2; ++ ++ if (0 == max_tmds_clk || ++ max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK || ++ max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) { ++ dal_logger_write(ddc->ctx->logger, ++ LOG_MAJOR_DCS, ++ LOG_MINOR_DCS_DONGLE_DETECTION, ++ "Invalid Maximum TMDS clock"); ++ *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; ++ } else { ++ if (is_valid_hdmi_signature == true) { ++ *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; ++ dal_logger_write(ddc->ctx->logger, ++ LOG_MAJOR_DCS, ++ LOG_MINOR_DCS_DONGLE_DETECTION, ++ "Detected Type 2 DP-HDMI Maximum TMDS " ++ "clock, max TMDS clock: %d MHz", ++ max_tmds_clk); ++ } else { ++ *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; ++ dal_logger_write(ddc->ctx->logger, ++ LOG_MAJOR_DCS, ++ LOG_MINOR_DCS_DONGLE_DETECTION, ++ "Detected Type 2 DP-HDMI (no valid HDMI" ++ " signature) Maximum TMDS clock, max " ++ "TMDS clock: %d MHz", ++ max_tmds_clk); ++ } ++ ++ /* Multiply by 1000 to convert to kHz. */ ++ sink_cap->max_hdmi_pixel_clock = ++ max_tmds_clk * 1000; ++ } ++ ++ } else { ++ if (is_valid_hdmi_signature == true) { ++ dal_logger_write(ddc->ctx->logger, ++ LOG_MAJOR_DCS, ++ LOG_MINOR_DCS_DONGLE_DETECTION, ++ "Detected Type 1 DP-HDMI dongle.\n"); ++ *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; ++ } else { ++ dal_logger_write(ddc->ctx->logger, ++ LOG_MAJOR_DCS, ++ LOG_MINOR_DCS_DONGLE_DETECTION, ++ "Detected Type 1 DP-HDMI dongle (no valid HDMI " ++ "signature).\n"); ++ ++ *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; ++ } ++ } ++ ++ return; ++} ++ ++enum { ++ DP_SINK_CAP_SIZE = ++ DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1 ++}; ++ ++bool dal_ddc_service_query_ddc_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ uint8_t *write_buf, ++ uint32_t write_size, ++ uint8_t *read_buf, ++ uint32_t read_size) ++{ ++ bool ret; ++ uint32_t payload_size = ++ dal_ddc_service_is_in_aux_transaction_mode(ddc) ? ++ DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE; ++ ++ uint32_t write_payloads = ++ (write_size + payload_size - 1) / payload_size; ++ ++ uint32_t read_payloads = ++ (read_size + payload_size - 1) / payload_size; ++ ++ uint32_t payloads_num = write_payloads + read_payloads; ++ ++ if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE) ++ return false; ++ ++ /*TODO: len of payload data for i2c and aux is uint8!!!!, ++ * but we want to read 256 over i2c!!!!*/ ++ if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { ++ ++ struct aux_payloads *payloads = ++ dal_ddc_aux_payloads_create(ddc->ctx, payloads_num); ++ ++ struct aux_command command = { ++ .payloads = dal_ddc_aux_payloads_get(payloads), ++ .number_of_payloads = 0, ++ .defer_delay = get_defer_delay(ddc), ++ .max_defer_write_retry = 0 }; ++ ++ dal_ddc_aux_payloads_add( ++ payloads, address, write_size, write_buf, true); ++ ++ dal_ddc_aux_payloads_add( ++ payloads, address, read_size, read_buf, false); ++ ++ command.number_of_payloads = ++ dal_ddc_aux_payloads_get_count(payloads); ++ ++ ret = dal_i2caux_submit_aux_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &command); ++ ++ dal_ddc_aux_payloads_destroy(&payloads); ++ ++ } else { ++ struct i2c_payloads *payloads = ++ dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num); ++ ++ struct i2c_command command = { ++ .payloads = dal_ddc_i2c_payloads_get(payloads), ++ .number_of_payloads = 0, ++ .engine = DDC_I2C_COMMAND_ENGINE, ++ .speed = ++ dal_adapter_service_get_sw_i2c_speed(ddc->as) }; ++ ++ dal_ddc_i2c_payloads_add( ++ payloads, address, write_size, write_buf, true); ++ ++ dal_ddc_i2c_payloads_add( ++ payloads, address, read_size, read_buf, false); ++ ++ command.number_of_payloads = ++ dal_ddc_i2c_payloads_get_count(payloads); ++ ++ ret = dal_i2caux_submit_i2c_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &command); ++ ++ dal_ddc_i2c_payloads_destroy(&payloads); ++ } ++ ++ return ret; ++} ++ ++bool dal_ddc_service_get_dp_receiver_id_info( ++ struct ddc_service *ddc, ++ struct dp_receiver_id_info *info) ++{ ++ if (!info) ++ return false; ++ ++ *info = ddc->dp_receiver_id_info; ++ return true; ++} ++ ++enum ddc_result dal_ddc_service_read_dpcd_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ uint8_t *data, ++ uint32_t len) ++{ ++ struct aux_payload read_payload = { ++ .i2c_over_aux = false, ++ .write = false, ++ .address = address, ++ .length = len, ++ .data = data, ++ }; ++ struct aux_command command = { ++ .payloads = &read_payload, ++ .number_of_payloads = 1, ++ .defer_delay = 0, ++ .max_defer_write_retry = 0, ++ }; ++ ++ if (len > DEFAULT_AUX_MAX_DATA_SIZE) { ++ BREAK_TO_DEBUGGER(); ++ return DDC_RESULT_FAILED_INVALID_OPERATION; ++ } ++ ++ if (dal_i2caux_submit_aux_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &command)) ++ return DDC_RESULT_SUCESSFULL; ++ ++ return DDC_RESULT_FAILED_OPERATION; ++} ++ ++enum ddc_result dal_ddc_service_write_dpcd_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ const uint8_t *data, ++ uint32_t len) ++{ ++ struct aux_payload write_payload = { ++ .i2c_over_aux = false, ++ .write = true, ++ .address = address, ++ .length = len, ++ .data = (uint8_t *)data, ++ }; ++ struct aux_command command = { ++ .payloads = &write_payload, ++ .number_of_payloads = 1, ++ .defer_delay = 0, ++ .max_defer_write_retry = 0, ++ }; ++ ++ if (len > DEFAULT_AUX_MAX_DATA_SIZE) { ++ BREAK_TO_DEBUGGER(); ++ return DDC_RESULT_FAILED_INVALID_OPERATION; ++ } ++ ++ if (dal_i2caux_submit_aux_command( ++ dal_adapter_service_get_i2caux(ddc->as), ++ ddc->ddc_pin, ++ &command)) ++ return DDC_RESULT_SUCESSFULL; ++ ++ return DDC_RESULT_FAILED_OPERATION; ++} ++ ++/*test only function*/ ++void dal_ddc_service_set_ddc_pin( ++ struct ddc_service *ddc_service, ++ struct ddc *ddc) ++{ ++ ddc_service->ddc_pin = ddc; ++} ++ ++struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service) ++{ ++ return ddc_service->ddc_pin; ++} ++ ++ ++void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service) ++{ ++ dc_service_memset(&ddc_service->dp_receiver_id_info, ++ 0, sizeof(struct dp_receiver_id_info)); ++} ++ ++void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service, ++ uint32_t pix_clk, ++ bool lte_340_scramble) ++{ ++ bool over_340_mhz = pix_clk > 340000 ? 1 : 0; ++ uint8_t slave_address = HDMI_SCDC_ADDRESS; ++ uint8_t offset = HDMI_SCDC_SINK_VERSION; ++ uint8_t sink_version = 0; ++ uint8_t write_buffer[2] = {0}; ++ /*Lower than 340 Scramble bit from SCDC caps*/ ++ ++ dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, ++ sizeof(offset), &sink_version, sizeof(sink_version)); ++ if (sink_version == 1) { ++ /*Source Version = 1*/ ++ write_buffer[0] = HDMI_SCDC_SOURCE_VERSION; ++ write_buffer[1] = 1; ++ dal_ddc_service_query_ddc_data(ddc_service, slave_address, ++ write_buffer, sizeof(write_buffer), NULL, 0); ++ /*Read Request from SCDC caps*/ ++ } ++ write_buffer[0] = HDMI_SCDC_TMDS_CONFIG; ++ ++ if (over_340_mhz) { ++ write_buffer[1] = 3; ++ } else if (lte_340_scramble) { ++ write_buffer[1] = 1; ++ } else { ++ write_buffer[1] = 0; ++ } ++ dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer, ++ sizeof(write_buffer), NULL, 0); ++} ++ ++void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service) ++{ ++ uint8_t slave_address = HDMI_SCDC_ADDRESS; ++ uint8_t offset = HDMI_SCDC_TMDS_CONFIG; ++ uint8_t tmds_config = 0; ++ ++ dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, ++ sizeof(offset), &tmds_config, sizeof(tmds_config)); ++ if (tmds_config & 0x1) { ++ union hdmi_scdc_status_flags_data status_data = { {0} }; ++ uint8_t scramble_status = 0; ++ ++ offset = HDMI_SCDC_SCRAMBLER_STATUS; ++ dal_ddc_service_query_ddc_data(ddc_service, slave_address, ++ &offset, sizeof(offset), &scramble_status, ++ sizeof(scramble_status)); ++ offset = HDMI_SCDC_STATUS_FLAGS; ++ dal_ddc_service_query_ddc_data(ddc_service, slave_address, ++ &offset, sizeof(offset), status_data.byte, ++ sizeof(status_data.byte)); ++ } ++} ++ +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c +index c4cbede..96ba910 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c +@@ -5,7 +5,7 @@ + #include "dc_helpers.h" + #include "inc/core_types.h" + #include "link_hwss.h" +-#include "ddc_service_interface.h" ++#include "dc_link_ddc.h" + #include "core_status.h" + #include "dpcd_defs.h" + +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c +index 2ed9eb8..656ec71 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c +@@ -7,7 +7,7 @@ + #include "include/i2caux_interface.h" + #include "link_hwss.h" + #include "hw_sequencer.h" +-#include "include/ddc_service_interface.h" ++#include "dc_link_ddc.h" + #include "dc_helpers.h" + #include "dce110/dce110_link_encoder.h" + #include "dce110/dce110_stream_encoder.h" +diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/Makefile b/drivers/gpu/drm/amd/dal/dc/dcs/Makefile +deleted file mode 100644 +index a266942..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/dcs/Makefile ++++ /dev/null +@@ -1,10 +0,0 @@ +-# +-# Makefile for the 'gpu' sub-component of DAL. +-# It provides the control and status of HW adapter resources, +-# that are global for the ASIC and sharable between pipes. +- +-DCS = ddc_service.o ddc_i2caux_helper.o +- +-AMD_DAL_DCS = $(addprefix $(AMDDALPATH)/dc/dcs/,$(DCS)) +- +-AMD_DAL_FILES += $(AMD_DAL_DCS) +diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c +deleted file mode 100644 +index 0af4df6..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.c ++++ /dev/null +@@ -1,159 +0,0 @@ +-/* +- * Copyright 2012-15 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- * Authors: AMD +- * +- */ +- +-#include "dc_services.h" +-#include "ddc_i2caux_helper.h" +-#include "include/ddc_service_types.h" +-#include "include/vector.h" +- +-struct i2c_payloads { +- struct vector payloads; +-}; +- +-struct aux_payloads { +- struct vector payloads; +-}; +- +-struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count) +-{ +- struct i2c_payloads *payloads; +- +- payloads = dc_service_alloc(ctx, sizeof(struct i2c_payloads)); +- +- if (!payloads) +- return NULL; +- +- if (dal_vector_construct( +- &payloads->payloads, ctx, count, sizeof(struct i2c_payload))) +- return payloads; +- +- dc_service_free(ctx, payloads); +- return NULL; +- +-} +- +-struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p) +-{ +- return (struct i2c_payload *)p->payloads.container; +-} +- +-uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) +-{ +- return p->payloads.count; +-} +- +-void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p) +-{ +- if (!p || !*p) +- return; +- dal_vector_destruct(&(*p)->payloads); +- dc_service_free((*p)->payloads.ctx, *p); +- *p = NULL; +- +-} +- +-struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count) +-{ +- struct aux_payloads *payloads; +- +- payloads = dc_service_alloc(ctx, sizeof(struct aux_payloads)); +- +- if (!payloads) +- return NULL; +- +- if (dal_vector_construct( +- &payloads->payloads, ctx, count, sizeof(struct aux_payloads))) +- return payloads; +- +- dc_service_free(ctx, payloads); +- return NULL; +-} +- +-struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p) +-{ +- return (struct aux_payload *)p->payloads.container; +-} +- +-uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p) +-{ +- return p->payloads.count; +-} +- +- +-void dal_ddc_aux_payloads_destroy(struct aux_payloads **p) +-{ +- if (!p || !*p) +- return; +- +- dal_vector_destruct(&(*p)->payloads); +- dc_service_free((*p)->payloads.ctx, *p); +- *p = NULL; +-} +- +-#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) +- +-void dal_ddc_i2c_payloads_add( +- struct i2c_payloads *payloads, +- uint32_t address, +- uint32_t len, +- uint8_t *data, +- bool write) +-{ +- uint32_t payload_size = EDID_SEGMENT_SIZE; +- uint32_t pos; +- +- for (pos = 0; pos < len; pos += payload_size) { +- struct i2c_payload payload = { +- .write = write, +- .address = address, +- .length = DDC_MIN(payload_size, len - pos), +- .data = data + pos }; +- dal_vector_append(&payloads->payloads, &payload); +- } +- +-} +- +-void dal_ddc_aux_payloads_add( +- struct aux_payloads *payloads, +- uint32_t address, +- uint32_t len, +- uint8_t *data, +- bool write) +-{ +- uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE; +- uint32_t pos; +- +- for (pos = 0; pos < len; pos += payload_size) { +- struct aux_payload payload = { +- .i2c_over_aux = true, +- .write = write, +- .address = address, +- .length = DDC_MIN(payload_size, len - pos), +- .data = data + pos }; +- dal_vector_append(&payloads->payloads, &payload); +- } +-} +- +- +diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h +deleted file mode 100644 +index bb628cd..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_i2caux_helper.h ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* +- * Copyright 2012-15 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- * Authors: AMD +- * +- */ +- +-#ifndef __DAL_I2CAUX_HELPER_H__ +-#define __DAL_I2CAUX_HELPER_H__ +- +-#include "include/i2caux_interface.h" +- +-#define EDID_SEGMENT_SIZE 256 +- +-struct i2c_payloads; +-struct aux_payloads; +- +-struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count); +-struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p); +-uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p); +-void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p); +- +-struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count); +-struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p); +-uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p); +-void dal_ddc_aux_payloads_destroy(struct aux_payloads **p); +- +-void dal_ddc_i2c_payloads_add( +- struct i2c_payloads *payloads, +- uint32_t address, +- uint32_t len, +- uint8_t *data, +- bool write); +- +-void dal_ddc_aux_payloads_add( +- struct aux_payloads *payloads, +- uint32_t address, +- uint32_t len, +- uint8_t *data, +- bool write); +- +-#endif /* __DAL_I2CAUX_HELPER_H__ */ +diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c +deleted file mode 100644 +index bbab51c..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.c ++++ /dev/null +@@ -1,1036 +0,0 @@ +-/* +- * Copyright 2012-15 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- * Authors: AMD +- * +- */ +- +-#include "dc_services.h" +- +-#include "include/adapter_service_interface.h" +-#include "include/i2caux_interface.h" +-#include "include/ddc_service_interface.h" +-#include "include/ddc_service_types.h" +-#include "include/grph_object_id.h" +-#include "include/dpcd_defs.h" +-#include "include/logger_interface.h" +-#include "ddc_i2caux_helper.h" +-#include "ddc_service.h" +- +-#define AUX_POWER_UP_WA_DELAY 500 +-#define I2C_OVER_AUX_DEFER_WA_DELAY 70 +- +-/* CV smart dongle slave address for retrieving supported HDTV modes*/ +-#define CV_SMART_DONGLE_ADDRESS 0x20 +-/* DVI-HDMI dongle slave address for retrieving dongle signature*/ +-#define DVI_HDMI_DONGLE_ADDRESS 0x68 +-static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G"; +-struct dvi_hdmi_dongle_signature_data { +- int8_t vendor[3];/* "AMD" */ +- uint8_t version[2]; +- uint8_t size; +- int8_t id[11];/* "6140063500G"*/ +-}; +-/* DP-HDMI dongle slave address for retrieving dongle signature*/ +-#define DP_HDMI_DONGLE_ADDRESS 0x40 +-static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR"; +-#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04 +- +-struct dp_hdmi_dongle_signature_data { +- int8_t id[15];/* "DP-HDMI ADAPTOR"*/ +- uint8_t eot;/* end of transmition '\x4' */ +-}; +- +-/* Address range from 0x00 to 0x1F.*/ +-#define DP_ADAPTOR_TYPE2_SIZE 0x20 +-#define DP_ADAPTOR_TYPE2_REG_ID 0x10 +-#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D +-/* Identifies adaptor as Dual-mode adaptor */ +-#define DP_ADAPTOR_TYPE2_ID 0xA0 +-/* MHz*/ +-#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600 +-/* MHz*/ +-#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25 +-/* kHZ*/ +-#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 +-/* kHZ*/ +-#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 +- +-#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW +- +-enum edid_read_result { +- EDID_READ_RESULT_EDID_MATCH = 0, +- EDID_READ_RESULT_EDID_MISMATCH, +- EDID_READ_RESULT_CHECKSUM_READ_ERR, +- EDID_READ_RESULT_VENDOR_READ_ERR +-}; +- +-/* SCDC Address defines (HDMI 2.0)*/ +-#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3 +-#define HDMI_SCDC_ADDRESS 0x54 +-#define HDMI_SCDC_SINK_VERSION 0x01 +-#define HDMI_SCDC_SOURCE_VERSION 0x02 +-#define HDMI_SCDC_UPDATE_0 0x10 +-#define HDMI_SCDC_TMDS_CONFIG 0x20 +-#define HDMI_SCDC_SCRAMBLER_STATUS 0x21 +-#define HDMI_SCDC_CONFIG_0 0x30 +-#define HDMI_SCDC_STATUS_FLAGS 0x40 +-#define HDMI_SCDC_ERR_DETECT 0x50 +-#define HDMI_SCDC_TEST_CONFIG 0xC0 +- +- +-union hdmi_scdc_update_read_data +-{ +- uint8_t byte[2]; +- struct +- { +- uint8_t STATUS_UPDATE:1; +- uint8_t CED_UPDATE:1; +- uint8_t RR_TEST:1; +- uint8_t RESERVED:5; +- uint8_t RESERVED2:8; +- } fields; +-}; +- +-union hdmi_scdc_status_flags_data +-{ +- uint8_t byte[2]; +- struct +- { +- uint8_t CLOCK_DETECTED:1; +- uint8_t CH0_LOCKED:1; +- uint8_t CH1_LOCKED:1; +- uint8_t CH2_LOCKED:1; +- uint8_t RESERVED:4; +- uint8_t RESERVED2:8; +- } fields; +-}; +- +-union hdmi_scdc_ced_data +-{ +- uint8_t byte[7]; +- struct +- { +- uint8_t CH0_8LOW:8; +- uint8_t CH0_7HIGH:7; +- uint8_t CH0_VALID:1; +- uint8_t CH1_8LOW:8; +- uint8_t CH1_7HIGH:7; +- uint8_t CH1_VALID:1; +- uint8_t CH2_8LOW:8; +- uint8_t CH2_7HIGH:7; +- uint8_t CH2_VALID:1; +- uint8_t CHECKSUM:8; +- } fields; +-}; +- +-union hdmi_scdc_test_config_Data +-{ +- uint8_t byte; +- struct +- { +- uint8_t TEST_READ_REQUEST_DELAY:7; +- uint8_t TEST_READ_REQUEST: 1; +- } fields; +-}; +- +- +- +-union ddc_wa { +- struct { +- uint32_t DP_SKIP_POWER_OFF:1; +- uint32_t DP_AUX_POWER_UP_WA_DELAY:1; +- } bits; +- uint32_t raw; +-}; +- +-struct ddc_flags { +- uint8_t EDID_QUERY_DONE_ONCE:1; +- uint8_t IS_INTERNAL_DISPLAY:1; +- uint8_t FORCE_READ_REPEATED_START:1; +- uint8_t EDID_STRESS_READ:1; +- +-}; +- +-struct ddc_service { +- struct ddc *ddc_pin; +- struct ddc_flags flags; +- union ddc_wa wa; +- enum ddc_transaction_type transaction_type; +- enum display_dongle_type dongle_type; +- struct dp_receiver_id_info dp_receiver_id_info; +- struct adapter_service *as; +- struct dc_context *ctx; +- +- uint32_t address; +- uint32_t edid_buf_len; +- uint8_t edid_buf[MAX_EDID_BUFFER_SIZE]; +-}; +- +-static bool construct( +- struct ddc_service *ddc_service, +- struct ddc_service_init_data *init_data) +-{ +- enum connector_id connector_id = +- dal_graphics_object_id_get_connector_id(init_data->id); +- +- ddc_service->ctx = init_data->ctx; +- ddc_service->as = init_data->as; +- ddc_service->ddc_pin = dal_adapter_service_obtain_ddc( +- init_data->as, init_data->id); +- +- ddc_service->flags.EDID_QUERY_DONE_ONCE = false; +- +- ddc_service->flags.FORCE_READ_REPEATED_START = +- dal_adapter_service_is_feature_supported( +- FEATURE_DDC_READ_FORCE_REPEATED_START); +- +- ddc_service->flags.EDID_STRESS_READ = +- dal_adapter_service_is_feature_supported( +- FEATURE_EDID_STRESS_READ); +- +- +- ddc_service->flags.IS_INTERNAL_DISPLAY = +- connector_id == CONNECTOR_ID_EDP || +- connector_id == CONNECTOR_ID_LVDS; +- +- ddc_service->wa.raw = 0; +- return true; +-} +- +-struct ddc_service *dal_ddc_service_create( +- struct ddc_service_init_data *init_data) +-{ +- struct ddc_service *ddc_service; +- +- ddc_service = dc_service_alloc(init_data->ctx, sizeof(struct ddc_service)); +- +- if (!ddc_service) +- return NULL; +- +- if (construct(ddc_service, init_data)) +- return ddc_service; +- +- dc_service_free(init_data->ctx, ddc_service); +- return NULL; +-} +- +-static void destruct(struct ddc_service *ddc) +-{ +- if (ddc->ddc_pin) +- dal_adapter_service_release_ddc(ddc->as, ddc->ddc_pin); +-} +- +-void dal_ddc_service_destroy(struct ddc_service **ddc) +-{ +- if (!ddc || !*ddc) { +- BREAK_TO_DEBUGGER(); +- return; +- } +- destruct(*ddc); +- dc_service_free((*ddc)->ctx, *ddc); +- *ddc = NULL; +-} +- +-enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc) +-{ +- return DDC_SERVICE_TYPE_CONNECTOR; +-} +- +-void dal_ddc_service_set_transaction_type( +- struct ddc_service *ddc, +- enum ddc_transaction_type type) +-{ +- ddc->transaction_type = type; +-} +- +-bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc) +-{ +- switch (ddc->transaction_type) { +- case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: +- case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: +- case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER: +- return true; +- default: +- break; +- } +- return false; +-} +- +-void ddc_service_set_dongle_type(struct ddc_service *ddc, +- enum display_dongle_type dongle_type) +-{ +- ddc->dongle_type = dongle_type; +-} +- +-static uint32_t defer_delay_converter_wa( +- struct ddc_service *ddc, +- uint32_t defer_delay) +-{ +- struct dp_receiver_id_info dp_rec_info = {0}; +- +- if (dal_ddc_service_get_dp_receiver_id_info(ddc, &dp_rec_info) && +- (dp_rec_info.branch_id == DP_BRANCH_DEVICE_ID_4) && +- !dal_strncmp(dp_rec_info.branch_name, +- DP_DVI_CONVERTER_ID_4, +- sizeof(dp_rec_info.branch_name))) +- return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ? +- defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY; +- +- return defer_delay; +- +-} +- +-#define DP_TRANSLATOR_DELAY 5 +- +-static uint32_t get_defer_delay(struct ddc_service *ddc) +-{ +- uint32_t defer_delay = 0; +- +- switch (ddc->transaction_type) { +- case DDC_TRANSACTION_TYPE_I2C_OVER_AUX: +- if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) || +- (DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) || +- (DISPLAY_DONGLE_DP_HDMI_CONVERTER == +- ddc->dongle_type)) { +- +- defer_delay = DP_TRANSLATOR_DELAY; +- +- defer_delay = +- defer_delay_converter_wa(ddc, defer_delay); +- +- } else /*sink has a delay different from an Active Converter*/ +- defer_delay = 0; +- break; +- case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER: +- defer_delay = DP_TRANSLATOR_DELAY; +- break; +- default: +- break; +- } +- return defer_delay; +-} +- +-static bool i2c_read( +- struct ddc_service *ddc, +- uint32_t address, +- uint8_t *buffer, +- uint32_t len) +-{ +- uint8_t offs_data = 0; +- struct i2c_payload payloads[2] = { +- { +- .write = true, +- .address = address, +- .length = 1, +- .data = &offs_data }, +- { +- .write = false, +- .address = address, +- .length = len, +- .data = buffer } }; +- +- struct i2c_command command = { +- .payloads = payloads, +- .number_of_payloads = 2, +- .engine = DDC_I2C_COMMAND_ENGINE, +- .speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) }; +- +- return dal_i2caux_submit_i2c_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &command); +-} +- +-static uint8_t aux_read_edid_block( +- struct ddc_service *ddc, +- uint8_t address, +- uint8_t index, +- uint8_t *buf) +-{ +- struct aux_command cmd = { +- .payloads = NULL, +- .number_of_payloads = 0, +- .defer_delay = get_defer_delay(ddc), +- .max_defer_write_retry = 0 }; +- +- uint8_t retrieved = 0; +- uint8_t base_offset = +- (index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE; +- uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; +- +- for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE; +- retrieved += DEFAULT_AUX_MAX_DATA_SIZE) { +- +- uint8_t offset = base_offset + retrieved; +- +- struct aux_payload payloads[3] = { +- { +- .i2c_over_aux = true, +- .write = true, +- .address = DDC_EDID_SEGMENT_ADDRESS, +- .length = 1, +- .data = &segment }, +- { +- .i2c_over_aux = true, +- .write = true, +- .address = address, +- .length = 1, +- .data = &offset }, +- { +- .i2c_over_aux = true, +- .write = false, +- .address = address, +- .length = DEFAULT_AUX_MAX_DATA_SIZE, +- .data = &buf[retrieved] } }; +- +- if (segment == 0) { +- cmd.payloads = &payloads[1]; +- cmd.number_of_payloads = 2; +- } else { +- cmd.payloads = payloads; +- cmd.number_of_payloads = 3; +- } +- +- if (!dal_i2caux_submit_aux_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &cmd)) +- /* cannot read, break*/ +- break; +- } +- +- /* Reset segment to 0. Needed by some panels */ +- if (0 != segment) { +- struct aux_payload payloads[1] = { { +- .i2c_over_aux = true, +- .write = true, +- .address = DDC_EDID_SEGMENT_ADDRESS, +- .length = 1, +- .data = &segment } }; +- bool result = false; +- +- segment = 0; +- +- cmd.number_of_payloads = ARRAY_SIZE(payloads); +- cmd.payloads = payloads; +- +- result = dal_i2caux_submit_aux_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &cmd); +- +- if (false == result) +- dal_logger_write( +- ddc->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, +- "%s: Writing of EDID Segment (0x30) failed!\n", +- __func__); +- } +- +- return retrieved; +-} +- +-static uint8_t i2c_read_edid_block( +- struct ddc_service *ddc, +- uint8_t address, +- uint8_t index, +- uint8_t *buf) +-{ +- bool ret = false; +- uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) * +- DDC_EDID_BLOCK_SIZE; +- uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT; +- +- struct i2c_command cmd = { +- .payloads = NULL, +- .number_of_payloads = 0, +- .engine = DDC_I2C_COMMAND_ENGINE, +- .speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) }; +- +- struct i2c_payload payloads[3] = { +- { +- .write = true, +- .address = DDC_EDID_SEGMENT_ADDRESS, +- .length = 1, +- .data = &segment }, +- { +- .write = true, +- .address = address, +- .length = 1, +- .data = &offset }, +- { +- .write = false, +- .address = address, +- .length = DDC_EDID_BLOCK_SIZE, +- .data = buf } }; +-/* +- * Some I2C engines don't handle stop/start between write-offset and read-data +- * commands properly. For those displays, we have to force the newer E-DDC +- * behavior of repeated-start which can be enabled by runtime parameter. */ +-/* Originally implemented for OnLive using NXP receiver chip */ +- +- if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) { +- /* base block, use use DDC2B, submit as 2 commands */ +- cmd.payloads = &payloads[1]; +- cmd.number_of_payloads = 1; +- +- if (dal_i2caux_submit_i2c_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &cmd)) { +- +- cmd.payloads = &payloads[2]; +- cmd.number_of_payloads = 1; +- +- ret = dal_i2caux_submit_i2c_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &cmd); +- } +- +- } else { +- /* +- * extension block use E-DDC, submit as 1 command +- * or if repeated-start is forced by runtime parameter +- */ +- if (segment != 0) { +- /* include segment offset in command*/ +- cmd.payloads = payloads; +- cmd.number_of_payloads = 3; +- } else { +- /* we are reading first segment, +- * segment offset is not required */ +- cmd.payloads = &payloads[1]; +- cmd.number_of_payloads = 2; +- } +- +- ret = dal_i2caux_submit_i2c_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &cmd); +- } +- +- return ret ? DDC_EDID_BLOCK_SIZE : 0; +-} +- +-static uint32_t query_edid_block( +- struct ddc_service *ddc, +- uint8_t address, +- uint8_t index, +- uint8_t *buf, +- uint32_t size) +-{ +- uint32_t size_retrieved = 0; +- +- if (size < DDC_EDID_BLOCK_SIZE) +- return 0; +- +- if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { +- +- ASSERT(index < 2); +- size_retrieved = +- aux_read_edid_block(ddc, address, index, buf); +- } else { +- size_retrieved = +- i2c_read_edid_block(ddc, address, index, buf); +- } +- +- return size_retrieved; +-} +- +-#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261 +-#define DDC_TEST_ACK_ADDRESS 0x260 +-#define DDC_DPCD_EDID_TEST_ACK 0x04 +-#define DDC_DPCD_EDID_TEST_MASK 0x04 +-#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218 +- +-/* AG TODO GO throug DM callback here like for DPCD */ +- +-static void write_dp_edid_checksum( +- struct ddc_service *ddc, +- uint8_t checksum) +-{ +- uint8_t dpcd_data; +- +- dal_ddc_service_read_dpcd_data( +- ddc, +- DDC_DPCD_TEST_REQUEST_ADDRESS, +- &dpcd_data, +- 1); +- +- if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) { +- +- dal_ddc_service_write_dpcd_data( +- ddc, +- DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS, +- &checksum, +- 1); +- +- dpcd_data = DDC_DPCD_EDID_TEST_ACK; +- +- dal_ddc_service_write_dpcd_data( +- ddc, +- DDC_TEST_ACK_ADDRESS, +- &dpcd_data, +- 1); +- } +-} +- +-uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc) +-{ +- uint32_t bytes_read = 0; +- uint32_t ext_cnt = 0; +- +- uint8_t address; +- uint32_t i; +- +- for (address = DDC_EDID_ADDRESS_START; +- address <= DDC_EDID_ADDRESS_END; ++address) { +- +- bytes_read = query_edid_block( +- ddc, +- address, +- 0, +- ddc->edid_buf, +- sizeof(ddc->edid_buf) - bytes_read); +- +- if (bytes_read != DDC_EDID_BLOCK_SIZE) +- continue; +- +- /* get the number of ext blocks*/ +- ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET]; +- +- /* EDID 2.0, need to read 1 more block because EDID2.0 is +- * 256 byte in size*/ +- if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] == +- DDC_EDID_20_SIGNATURE) +- ext_cnt = 1; +- +- for (i = 0; i < ext_cnt; i++) { +- /* read additional ext blocks accordingly */ +- bytes_read += query_edid_block( +- ddc, +- address, +- i+1, +- &ddc->edid_buf[bytes_read], +- sizeof(ddc->edid_buf) - bytes_read); +- } +- +- /*this is special code path for DP compliance*/ +- if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type) +- write_dp_edid_checksum( +- ddc, +- ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) + +- DDC_EDID1X_CHECKSUM_OFFSET]); +- +- /*remembers the address where we fetch the EDID from +- * for later signature check use */ +- ddc->address = address; +- +- break;/* already read edid, done*/ +- } +- +- ddc->edid_buf_len = bytes_read; +- return bytes_read; +-} +- +-uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc) +-{ +- return ddc->edid_buf_len; +-} +- +-void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf) +-{ +- dc_service_memmove(edid_buf, +- ddc->edid_buf, ddc->edid_buf_len); +-} +- +-void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( +- struct ddc_service *ddc, +- struct display_sink_capability *sink_cap) +-{ +- uint8_t i; +- bool is_valid_hdmi_signature; +- enum display_dongle_type *dongle = &sink_cap->dongle_type; +- uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE]; +- bool is_type2_dongle = false; +- struct dp_hdmi_dongle_signature_data *dongle_signature; +- +- /* Assume we have no valid DP passive dongle connected */ +- *dongle = DISPLAY_DONGLE_NONE; +- sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK; +- +- /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/ +- if (!i2c_read( +- ddc, +- DP_HDMI_DONGLE_ADDRESS, +- type2_dongle_buf, +- sizeof(type2_dongle_buf))) { +- dal_logger_write(ddc->ctx->logger, +- LOG_MAJOR_DCS, +- LOG_MINOR_DCS_DONGLE_DETECTION, +- "Detected DP-DVI dongle.\n"); +- *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; +- sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; +- return; +- } +- +- /* Check if Type 2 dongle.*/ +- if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID) +- is_type2_dongle = true; +- +- dongle_signature = +- (struct dp_hdmi_dongle_signature_data *)type2_dongle_buf; +- +- is_valid_hdmi_signature = true; +- +- /* Check EOT */ +- if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) { +- is_valid_hdmi_signature = false; +- } +- +- /* Check signature */ +- for (i = 0; i < sizeof(dongle_signature->id); ++i) { +- /* If its not the right signature, +- * skip mismatch in subversion byte.*/ +- if (dongle_signature->id[i] != +- dp_hdmi_dongle_signature_str[i] && i != 3) { +- +- if (is_type2_dongle) { +- is_valid_hdmi_signature = false; +- break; +- } +- +- } +- } +- +- if (is_type2_dongle) { +- uint32_t max_tmds_clk = +- type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK]; +- +- max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2; +- +- if (0 == max_tmds_clk || +- max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK || +- max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) { +- dal_logger_write(ddc->ctx->logger, +- LOG_MAJOR_DCS, +- LOG_MINOR_DCS_DONGLE_DETECTION, +- "Invalid Maximum TMDS clock"); +- *dongle = DISPLAY_DONGLE_DP_DVI_DONGLE; +- } else { +- if (is_valid_hdmi_signature == true) { +- *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; +- dal_logger_write(ddc->ctx->logger, +- LOG_MAJOR_DCS, +- LOG_MINOR_DCS_DONGLE_DETECTION, +- "Detected Type 2 DP-HDMI Maximum TMDS " +- "clock, max TMDS clock: %d MHz", +- max_tmds_clk); +- } else { +- *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; +- dal_logger_write(ddc->ctx->logger, +- LOG_MAJOR_DCS, +- LOG_MINOR_DCS_DONGLE_DETECTION, +- "Detected Type 2 DP-HDMI (no valid HDMI" +- " signature) Maximum TMDS clock, max " +- "TMDS clock: %d MHz", +- max_tmds_clk); +- } +- +- /* Multiply by 1000 to convert to kHz. */ +- sink_cap->max_hdmi_pixel_clock = +- max_tmds_clk * 1000; +- } +- +- } else { +- if (is_valid_hdmi_signature == true) { +- dal_logger_write(ddc->ctx->logger, +- LOG_MAJOR_DCS, +- LOG_MINOR_DCS_DONGLE_DETECTION, +- "Detected Type 1 DP-HDMI dongle.\n"); +- *dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE; +- } +- else { +- dal_logger_write(ddc->ctx->logger, +- LOG_MAJOR_DCS, +- LOG_MINOR_DCS_DONGLE_DETECTION, +- "Detected Type 1 DP-HDMI dongle (no valid HDMI " +- "signature).\n"); +- +- *dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE; +- } +- } +- +- return; +-} +- +-enum { +- DP_SINK_CAP_SIZE = +- DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1 +-}; +- +-bool dal_ddc_service_query_ddc_data( +- struct ddc_service *ddc, +- uint32_t address, +- uint8_t *write_buf, +- uint32_t write_size, +- uint8_t *read_buf, +- uint32_t read_size) +-{ +- bool ret; +- uint32_t payload_size = +- dal_ddc_service_is_in_aux_transaction_mode(ddc) ? +- DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE; +- +- uint32_t write_payloads = +- (write_size + payload_size - 1) / payload_size; +- +- uint32_t read_payloads = +- (read_size + payload_size - 1) / payload_size; +- +- uint32_t payloads_num = write_payloads + read_payloads; +- +- if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE) +- return false; +- +- /*TODO: len of payload data for i2c and aux is uint8!!!!, +- * but we want to read 256 over i2c!!!!*/ +- if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) { +- +- struct aux_payloads *payloads = +- dal_ddc_aux_payloads_create(ddc->ctx, payloads_num); +- +- struct aux_command command = { +- .payloads = dal_ddc_aux_payloads_get(payloads), +- .number_of_payloads = 0, +- .defer_delay = get_defer_delay(ddc), +- .max_defer_write_retry = 0 }; +- +- dal_ddc_aux_payloads_add( +- payloads, address, write_size, write_buf, true); +- +- dal_ddc_aux_payloads_add( +- payloads, address, read_size, read_buf, false); +- +- command.number_of_payloads = +- dal_ddc_aux_payloads_get_count(payloads); +- +- ret = dal_i2caux_submit_aux_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &command); +- +- dal_ddc_aux_payloads_destroy(&payloads); +- +- } else { +- struct i2c_payloads *payloads = +- dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num); +- +- struct i2c_command command = { +- .payloads = dal_ddc_i2c_payloads_get(payloads), +- .number_of_payloads = 0, +- .engine = DDC_I2C_COMMAND_ENGINE, +- .speed = +- dal_adapter_service_get_sw_i2c_speed(ddc->as) }; +- +- dal_ddc_i2c_payloads_add( +- payloads, address, write_size, write_buf, true); +- +- dal_ddc_i2c_payloads_add( +- payloads, address, read_size, read_buf, false); +- +- command.number_of_payloads = +- dal_ddc_i2c_payloads_get_count(payloads); +- +- ret = dal_i2caux_submit_i2c_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &command); +- +- dal_ddc_i2c_payloads_destroy(&payloads); +- } +- +- return ret; +-} +- +-bool dal_ddc_service_get_dp_receiver_id_info( +- struct ddc_service *ddc, +- struct dp_receiver_id_info *info) +-{ +- if (!info) +- return false; +- +- *info = ddc->dp_receiver_id_info; +- return true; +-} +- +-enum ddc_result dal_ddc_service_read_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- uint8_t *data, +- uint32_t len) +-{ +- struct aux_payload read_payload = { +- .i2c_over_aux = false, +- .write = false, +- .address = address, +- .length = len, +- .data = data, +- }; +- struct aux_command command = { +- .payloads = &read_payload, +- .number_of_payloads = 1, +- .defer_delay = 0, +- .max_defer_write_retry = 0, +- }; +- +- if (len > DEFAULT_AUX_MAX_DATA_SIZE) { +- BREAK_TO_DEBUGGER(); +- return DDC_RESULT_FAILED_INVALID_OPERATION; +- } +- +- if (dal_i2caux_submit_aux_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &command)) +- return DDC_RESULT_SUCESSFULL; +- +- return DDC_RESULT_FAILED_OPERATION; +-} +- +-enum ddc_result dal_ddc_service_write_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- const uint8_t *data, +- uint32_t len) +-{ +- struct aux_payload write_payload = { +- .i2c_over_aux = false, +- .write = true, +- .address = address, +- .length = len, +- .data = (uint8_t *)data, +- }; +- struct aux_command command = { +- .payloads = &write_payload, +- .number_of_payloads = 1, +- .defer_delay = 0, +- .max_defer_write_retry = 0, +- }; +- +- if (len > DEFAULT_AUX_MAX_DATA_SIZE) { +- BREAK_TO_DEBUGGER(); +- return DDC_RESULT_FAILED_INVALID_OPERATION; +- } +- +- if (dal_i2caux_submit_aux_command( +- dal_adapter_service_get_i2caux(ddc->as), +- ddc->ddc_pin, +- &command)) +- return DDC_RESULT_SUCESSFULL; +- +- return DDC_RESULT_FAILED_OPERATION; +-} +- +-/*test only function*/ +-void dal_ddc_service_set_ddc_pin( +- struct ddc_service *ddc_service, +- struct ddc *ddc) +-{ +- ddc_service->ddc_pin = ddc; +-} +- +-struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service) +-{ +- return ddc_service->ddc_pin; +-} +- +- +-void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service) +-{ +- dc_service_memset(&ddc_service->dp_receiver_id_info, +- 0, sizeof(struct dp_receiver_id_info)); +-} +- +-void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service, +- uint32_t pix_clk, +- bool lte_340_scramble) +-{ +- bool over_340_mhz = pix_clk > 340000 ? 1 : 0; +- uint8_t slave_address = HDMI_SCDC_ADDRESS; +- uint8_t offset = HDMI_SCDC_SINK_VERSION; +- uint8_t sink_version = 0; +- uint8_t write_buffer[2] = {0}; +- /*Lower than 340 Scramble bit from SCDC caps*/ +- +- dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, +- sizeof(offset), &sink_version, sizeof(sink_version)); +- if (sink_version == 1) { +- /*Source Version = 1*/ +- write_buffer[0] = HDMI_SCDC_SOURCE_VERSION; +- write_buffer[1] = 1; +- dal_ddc_service_query_ddc_data(ddc_service, slave_address, +- write_buffer, sizeof(write_buffer), NULL, 0); +- /*Read Request from SCDC caps*/ +- } +- write_buffer[0] = HDMI_SCDC_TMDS_CONFIG; +- +- if (over_340_mhz) +- { +- write_buffer[1] = 3; +- } +- else if (lte_340_scramble) +- { +- write_buffer[1] = 1; +- } +- else +- { +- write_buffer[1] = 0; +- } +- dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer, +- sizeof(write_buffer), NULL, 0); +-} +- +-void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service) +-{ +- uint8_t slave_address = HDMI_SCDC_ADDRESS; +- uint8_t offset = HDMI_SCDC_TMDS_CONFIG; +- uint8_t tmds_config = 0; +- +- dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset, +- sizeof(offset), &tmds_config, sizeof(tmds_config)); +- if (tmds_config & 0x1){ +- union hdmi_scdc_status_flags_data status_data = {{0}}; +- uint8_t scramble_status = 0; +- +- offset = HDMI_SCDC_SCRAMBLER_STATUS; +- dal_ddc_service_query_ddc_data(ddc_service, slave_address, +- &offset, sizeof(offset),&scramble_status, +- sizeof(scramble_status)); +- offset = HDMI_SCDC_STATUS_FLAGS; +- dal_ddc_service_query_ddc_data(ddc_service, slave_address, +- &offset, sizeof(offset),status_data.byte, +- sizeof(status_data.byte)); +- } +-} +diff --git a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h b/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h +deleted file mode 100644 +index 3bf2a9e..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/dcs/ddc_service.h ++++ /dev/null +@@ -1,49 +0,0 @@ +-/* +- * Copyright 2012-15 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- * Authors: AMD +- * +- */ +- +-#ifndef __DAL_DDC_SERVICE_H__ +-#define __DAL_DDC_SERVICE_H__ +- +-#include "include/ddc_service_types.h" +- +-void dal_ddc_service_set_ddc_pin( +- struct ddc_service *ddc_service, +- struct ddc *ddc); +- +-struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); +-void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service); +- +-enum ddc_result dal_ddc_service_read_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- uint8_t *data, +- uint32_t len); +-enum ddc_result dal_ddc_service_write_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- const uint8_t *data, +- uint32_t len); +- +-#endif /* __DAL_DDC_SERVICE_H__ */ +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h +new file mode 100644 +index 0000000..18104d6 +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h +@@ -0,0 +1,151 @@ ++/* ++ * Copyright 2012-15 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: AMD ++ * ++ */ ++ ++#ifndef __DAL_DDC_SERVICE_H__ ++#define __DAL_DDC_SERVICE_H__ ++ ++#include "include/ddc_service_types.h" ++#include "include/i2caux_interface.h" ++ ++#define EDID_SEGMENT_SIZE 256 ++ ++struct ddc_service; ++struct adapter_service; ++struct graphics_object_id; ++enum ddc_result; ++struct av_sync_data; ++struct dp_receiver_id_info; ++ ++struct i2c_payloads; ++struct aux_payloads; ++ ++struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count); ++struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p); ++uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p); ++void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p); ++ ++struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count); ++struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p); ++uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p); ++void dal_ddc_aux_payloads_destroy(struct aux_payloads **p); ++ ++void dal_ddc_i2c_payloads_add( ++ struct i2c_payloads *payloads, ++ uint32_t address, ++ uint32_t len, ++ uint8_t *data, ++ bool write); ++ ++void dal_ddc_aux_payloads_add( ++ struct aux_payloads *payloads, ++ uint32_t address, ++ uint32_t len, ++ uint8_t *data, ++ bool write); ++ ++struct ddc_service_init_data { ++ struct adapter_service *as; ++ struct graphics_object_id id; ++ struct dc_context *ctx; ++}; ++ ++struct ddc_service *dal_ddc_service_create( ++ struct ddc_service_init_data *ddc_init_data); ++ ++void dal_ddc_service_destroy(struct ddc_service **ddc); ++ ++enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc); ++ ++void dal_ddc_service_set_transaction_type( ++ struct ddc_service *ddc, ++ enum ddc_transaction_type type); ++ ++bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); ++ ++uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); ++ ++uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); ++ ++void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); ++ ++void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( ++ struct ddc_service *ddc, ++ struct display_sink_capability *sink_cap); ++ ++bool dal_ddc_service_query_ddc_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ uint8_t *write_buf, ++ uint32_t write_size, ++ uint8_t *read_buf, ++ uint32_t read_size); ++ ++bool dal_ddc_service_get_dp_receiver_id_info( ++ struct ddc_service *ddc, ++ struct dp_receiver_id_info *info); ++ ++enum ddc_result dal_ddc_service_read_dpcd_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ uint8_t *data, ++ uint32_t len); ++ ++enum ddc_result dal_ddc_service_write_dpcd_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ const uint8_t *data, ++ uint32_t len); ++ ++void dal_ddc_service_write_scdc_data( ++ struct ddc_service *ddc_service, ++ uint32_t pix_clk, ++ bool lte_340_scramble); ++ ++void dal_ddc_service_read_scdc_data( ++ struct ddc_service *ddc_service); ++ ++void ddc_service_set_dongle_type(struct ddc_service *ddc, ++ enum display_dongle_type dongle_type); ++ ++void dal_ddc_service_set_ddc_pin( ++ struct ddc_service *ddc_service, ++ struct ddc *ddc); ++ ++struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service); ++void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service); ++ ++enum ddc_result dal_ddc_service_read_dpcd_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ uint8_t *data, ++ uint32_t len); ++enum ddc_result dal_ddc_service_write_dpcd_data( ++ struct ddc_service *ddc, ++ uint32_t address, ++ const uint8_t *data, ++ uint32_t len); ++ ++#endif /* __DAL_DDC_SERVICE_H__ */ ++ +diff --git a/drivers/gpu/drm/amd/dal/include/ddc_service_interface.h b/drivers/gpu/drm/amd/dal/include/ddc_service_interface.h +deleted file mode 100644 +index ca3e6ce..0000000 +--- a/drivers/gpu/drm/amd/dal/include/ddc_service_interface.h ++++ /dev/null +@@ -1,100 +0,0 @@ +-/* +- * Copyright 2012-15 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- * Authors: AMD +- * +- */ +-#ifndef __DAL_DDC_SERVICE_INTERFACE_H__ +-#define __DAL_DDC_SERVICE_INTERFACE_H__ +- +-#include "ddc_service_types.h" +- +-struct ddc_service; +-struct adapter_service; +-struct graphics_object_id; +-enum ddc_result; +-struct av_sync_data; +-struct dp_receiver_id_info; +- +-struct ddc_service_init_data { +- struct adapter_service *as; +- struct graphics_object_id id; +- struct dc_context *ctx; +-}; +-struct ddc_service *dal_ddc_service_create( +- struct ddc_service_init_data *ddc_init_data); +- +-void dal_ddc_service_destroy(struct ddc_service **ddc); +- +-enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc); +- +-void dal_ddc_service_set_transaction_type( +- struct ddc_service *ddc, +- enum ddc_transaction_type type); +- +-bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc); +- +-uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc); +- +-uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc); +- +-void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf); +- +-void dal_ddc_service_i2c_query_dp_dual_mode_adaptor( +- struct ddc_service *ddc, +- struct display_sink_capability *sink_cap); +- +-bool dal_ddc_service_query_ddc_data( +- struct ddc_service *ddc, +- uint32_t address, +- uint8_t *write_buf, +- uint32_t write_size, +- uint8_t *read_buf, +- uint32_t read_size); +- +-bool dal_ddc_service_get_dp_receiver_id_info( +- struct ddc_service *ddc, +- struct dp_receiver_id_info *info); +- +-enum ddc_result dal_ddc_service_read_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- uint8_t *data, +- uint32_t len); +- +-enum ddc_result dal_ddc_service_write_dpcd_data( +- struct ddc_service *ddc, +- uint32_t address, +- const uint8_t *data, +- uint32_t len); +- +-void dal_ddc_service_write_scdc_data( +- struct ddc_service *ddc_service, +- uint32_t pix_clk, +- bool lte_340_scramble); +- +-void dal_ddc_service_read_scdc_data( +- struct ddc_service *ddc_service); +- +-void ddc_service_set_dongle_type(struct ddc_service *ddc, +- enum display_dongle_type dongle_type); +- +-#endif /* __DAL_DDC_SERVICE_INTERFACE_H__ */ +-- +2.7.4 + |