From 6463e29e299eb8d0b8657af6d8487fe3829691fe Mon Sep 17 00:00:00 2001 From: Jun Lei Date: Tue, 1 Dec 2015 10:04:47 -0500 Subject: [PATCH 0548/1110] drm/amd/dal: Refactor DCE11 to split HW agnostic code into separate /dce folder. [Use Case] To support new ASIC enablement on DAL3, we want to minimize code duplication to speed up the effort. Inside dce110_resource about half the code is not dce110 specific. For example, building avi_info_frame is the same for all DCEs, as is mapping most resources with the exception of clock source (e.g. we always assign first free controller, audio, etc.). Signed-off-by: Harry Wentland Acked-by: Harry Wentland --- drivers/gpu/drm/amd/dal/dc/Makefile | 2 +- .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 722 ++------------------- drivers/gpu/drm/amd/dal/dc/dce_base/Makefile | 23 + .../drm/amd/dal/dc/dce_base/dce_base_resource.c | 667 +++++++++++++++++++ .../drm/amd/dal/dc/dce_base/dce_base_resource.h | 37 ++ 5 files changed, 793 insertions(+), 658 deletions(-) create mode 100644 drivers/gpu/drm/amd/dal/dc/dce_base/Makefile create mode 100644 drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c create mode 100644 drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.h diff --git a/drivers/gpu/drm/amd/dal/dc/Makefile b/drivers/gpu/drm/amd/dal/dc/Makefile index 6926356..285e30d 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 connector \ -dcs gpio gpu i2caux irq +dcs gpio gpu i2caux irq dce_base ifdef CONFIG_DRM_AMD_DAL_DCE11_0 DC_LIBS += dce110 diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c index 37ffc0e..7e69dd5 100644 --- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c @@ -24,8 +24,13 @@ */ #include "dc_services.h" +#include "link_encoder_types.h" +#include "stream_encoder_types.h" + #include "resource.h" +#include "dce_base/dce_base_resource.h" #include "include/irq_service_interface.h" + #include "dce110/dce110_timing_generator.h" #include "dce110/dce110_link_encoder.h" #include "dce110/dce110_mem_input.h" @@ -33,8 +38,6 @@ #include "dce110/dce110_transform.h" #include "dce110/dce110_stream_encoder.h" #include "dce110/dce110_opp.h" -#include "link_encoder_types.h" -#include "stream_encoder_types.h" enum dce110_clk_src_array_id { DCE110_CLK_SRC_PLL0 = 0, @@ -47,437 +50,6 @@ enum dce110_clk_src_array_id { #define DCE110_MAX_DISPCLK 643000 #define DCE110_MAX_SCLK 626000 -static void set_vendor_info_packet(struct core_stream *stream, - struct hw_info_packet *info_packet) -{ - uint32_t length = 0; - bool hdmi_vic_mode = false; - uint8_t checksum = 0; - uint32_t i = 0; - enum dc_timing_3d_format format; - - ASSERT_CRITICAL(stream != NULL); - ASSERT_CRITICAL(info_packet != NULL); - - format = stream->public.timing.timing_3d_format; - - /* Can be different depending on packet content */ - length = 5; - - if (stream->public.timing.hdmi_vic != 0 - && stream->public.timing.h_total >= 3840 - && stream->public.timing.v_total >= 2160) - hdmi_vic_mode = true; - - /* According to HDMI 1.4a CTS, VSIF should be sent - * for both 3D stereo and HDMI VIC modes. - * For all other modes, there is no VSIF sent. */ - - if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) - return; - - /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ - info_packet->sb[1] = 0x03; - info_packet->sb[2] = 0x0C; - info_packet->sb[3] = 0x00; - - /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. - * The value for HDMI_Video_Format are: - * 0x0 (0b000) - No additional HDMI video format is presented in this - * packet - * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC - * parameter follows - * 0x2 (0b010) - 3D format indication present. 3D_Structure and - * potentially 3D_Ext_Data follows - * 0x3..0x7 (0b011..0b111) - reserved for future use */ - if (format != TIMING_3D_FORMAT_NONE) - info_packet->sb[4] = (2 << 5); - else if (hdmi_vic_mode) - info_packet->sb[4] = (1 << 5); - - /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): - * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. - * The value for 3D_Structure are: - * 0x0 - Frame Packing - * 0x1 - Field Alternative - * 0x2 - Line Alternative - * 0x3 - Side-by-Side (full) - * 0x4 - L + depth - * 0x5 - L + depth + graphics + graphics-depth - * 0x6 - Top-and-Bottom - * 0x7 - Reserved for future use - * 0x8 - Side-by-Side (Half) - * 0x9..0xE - Reserved for future use - * 0xF - Not used */ - switch (format) { - case TIMING_3D_FORMAT_HW_FRAME_PACKING: - case TIMING_3D_FORMAT_SW_FRAME_PACKING: - info_packet->sb[5] = (0x0 << 4); - break; - - case TIMING_3D_FORMAT_SIDE_BY_SIDE: - case TIMING_3D_FORMAT_SBS_SW_PACKED: - info_packet->sb[5] = (0x8 << 4); - length = 6; - break; - - case TIMING_3D_FORMAT_TOP_AND_BOTTOM: - case TIMING_3D_FORMAT_TB_SW_PACKED: - info_packet->sb[5] = (0x6 << 4); - break; - - default: - break; - } - - /*PB5: If PB4 is set to 0x1 (extended resolution format) - * fill PB5 with the correct HDMI VIC code */ - if (hdmi_vic_mode) - info_packet->sb[5] = stream->public.timing.hdmi_vic; - - /* Header */ - info_packet->hb0 = 0x81; /* VSIF packet type. */ - info_packet->hb1 = 0x01; /* Version */ - - /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ - info_packet->hb2 = (uint8_t) (length); - - /* Calculate checksum */ - checksum = 0; - checksum += info_packet->hb0; - checksum += info_packet->hb1; - checksum += info_packet->hb2; - - for (i = 1; i <= length; i++) - checksum += info_packet->sb[i]; - - info_packet->sb[0] = (uint8_t) (0x100 - checksum); - - info_packet->valid = true; -} - -static enum ds_color_space build_default_color_space( - struct core_stream *stream) -{ - enum ds_color_space color_space = - DS_COLOR_SPACE_SRGB_FULLRANGE; - struct dc_crtc_timing *timing = &stream->public.timing; - - switch (stream->signal) { - /* TODO: implement other signal color space setting */ - case SIGNAL_TYPE_DISPLAY_PORT: - case SIGNAL_TYPE_DISPLAY_PORT_MST: - case SIGNAL_TYPE_EDP: - break; - case SIGNAL_TYPE_HDMI_TYPE_A: - { - uint32_t pix_clk_khz; - - if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 && - timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) { - if (timing->timing_standard == - TIMING_STANDARD_CEA770 && - timing->timing_standard == - TIMING_STANDARD_CEA861) - color_space = DS_COLOR_SPACE_SRGB_FULLRANGE; - - pix_clk_khz = timing->pix_clk_khz / 10; - if (timing->h_addressable == 640 && - timing->v_addressable == 480 && - (pix_clk_khz == 2520 || pix_clk_khz == 2517)) - color_space = DS_COLOR_SPACE_SRGB_FULLRANGE; - } else { - if (timing->timing_standard == - TIMING_STANDARD_CEA770 || - timing->timing_standard == - TIMING_STANDARD_CEA861) { - - color_space = - (timing->pix_clk_khz > PIXEL_CLOCK) ? - DS_COLOR_SPACE_YCBCR709 : - DS_COLOR_SPACE_YCBCR601; - } - } - break; - } - default: - switch (timing->pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - case PIXEL_ENCODING_YCBCR444: - if (timing->pix_clk_khz > PIXEL_CLOCK) - color_space = DS_COLOR_SPACE_YCBCR709; - else - color_space = DS_COLOR_SPACE_YCBCR601; - break; - default: - break; - } - break; - } - return color_space; -} - -static void set_avi_info_frame(struct hw_info_packet *info_packet, - struct core_stream *stream) -{ - enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN; - struct info_frame info_frame = { {0} }; - uint32_t pixel_encoding = 0; - enum scanning_type scan_type = SCANNING_TYPE_NODATA; - enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; - bool itc = false; - uint8_t cn0_cn1 = 0; - uint8_t *check_sum = NULL; - uint8_t byte_index = 0; - - if (info_packet == NULL) - return; - - color_space = build_default_color_space(stream); - - /* Initialize header */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header. - info_frame_type = INFO_FRAME_AVI; - /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall - * not be used in HDMI 2.0 (Section 10.1) */ - info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = - INFO_FRAME_VERSION_2; - info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = - INFO_FRAME_SIZE_AVI; - - /* IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built - * according to HDMI 2.0 spec (Section 10.1) - * Add "case PixelEncoding_YCbCr420: pixelEncoding = 3; break;" - * when YCbCr 4:2:0 is supported by DAL hardware. */ - - switch (stream->public.timing.pixel_encoding) { - case PIXEL_ENCODING_YCBCR422: - pixel_encoding = 1; - break; - - case PIXEL_ENCODING_YCBCR444: - pixel_encoding = 2; - break; - - case PIXEL_ENCODING_RGB: - default: - pixel_encoding = 0; - } - - /* Y0_Y1_Y2 : The pixel encoding */ - /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ - info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = - pixel_encoding; - - - /* A0 = 1 Active Format Information valid */ - info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = - ACTIVE_FORMAT_VALID; - - /* B0, B1 = 3; Bar info data is valid */ - info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = - BAR_INFO_BOTH_VALID; - - info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = - PICTURE_SCALING_UNIFORM; - - /* S0, S1 : Underscan / Overscan */ - /* TODO: un-hardcode scan type */ - scan_type = SCANNING_TYPE_UNDERSCAN; - info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; - - /* C0, C1 : Colorimetry */ - if (color_space == DS_COLOR_SPACE_YCBCR709) - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_ITU709; - else if (color_space == DS_COLOR_SPACE_YCBCR601) - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_ITU601; - else - info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = - COLORIMETRY_NO_DATA; - - - /* TODO: un-hardcode aspect ratio */ - aspect = stream->public.timing.aspect_ratio; - - switch (aspect) { - case ASPECT_RATIO_4_3: - case ASPECT_RATIO_16_9: - info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; - break; - - case ASPECT_RATIO_NO_DATA: - case ASPECT_RATIO_64_27: - case ASPECT_RATIO_256_135: - default: - info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; - } - - /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ - info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = - ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; - - /* TODO: un-hardcode cn0_cn1 and itc */ - cn0_cn1 = 0; - itc = false; - - if (itc) { - info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; - info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = - cn0_cn1; - } - - /* TODO: un-hardcode q0_q1 */ - if (color_space == DS_COLOR_SPACE_SRGB_FULLRANGE) - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_FULL_RANGE; - else if (color_space == DS_COLOR_SPACE_SRGB_LIMITEDRANGE) - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_LIMITED_RANGE; - else - info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = - RGB_QUANTIZATION_DEFAULT_RANGE; - - /* TODO : We should handle YCC quantization, - * but we do not have matrix calculation */ - info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = - YYC_QUANTIZATION_LIMITED_RANGE; - - info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = - stream->public.timing.vic; - - /* pixel repetition - * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel - * repetition start from 1 */ - info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; - - /* Bar Info - * barTop: Line Number of End of Top Bar. - * barBottom: Line Number of Start of Bottom Bar. - * barLeft: Pixel Number of End of Left Bar. - * barRight: Pixel Number of Start of Right Bar. */ - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = - stream->public.timing.v_border_top; - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = - (stream->public.timing.v_border_top - - stream->public.timing.v_border_bottom + 1); - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = - stream->public.timing.h_border_left; - info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = - (stream->public.timing.h_total - - stream->public.timing.h_border_right + 1); - - /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ - check_sum = - &info_frame. - avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; - *check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI - + INFO_FRAME_VERSION_2; - - for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++) - *check_sum += info_frame.avi_info_packet.info_packet_hdmi. - packet_raw_data.sb[byte_index]; - - /* one byte complement */ - *check_sum = (uint8_t) (0x100 - *check_sum); - - /* Store in hw_path_mode */ - info_packet->hb0 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; - info_packet->hb1 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; - info_packet->hb2 = - info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; - - for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++) - info_packet->sb[byte_index] = info_frame.avi_info_packet. - info_packet_hdmi.packet_raw_data.sb[byte_index]; - - info_packet->valid = true; -} - -static void translate_info_frame(const struct hw_info_frame *hw_info_frame, - struct encoder_info_frame *encoder_info_frame) -{ - dc_service_memset( - encoder_info_frame, 0, sizeof(struct encoder_info_frame)); - - /* For gamut we recalc checksum */ - if (hw_info_frame->gamut_packet.valid) { - uint8_t chk_sum = 0; - uint8_t *ptr; - uint8_t i; - - dc_service_memmove( - &encoder_info_frame->gamut, - &hw_info_frame->gamut_packet, - sizeof(struct hw_info_packet)); - - /*start of the Gamut data. */ - ptr = &encoder_info_frame->gamut.sb[3]; - - for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++) - chk_sum += ptr[i]; - - encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum); - } - - if (hw_info_frame->avi_info_packet.valid) { - dc_service_memmove( - &encoder_info_frame->avi, - &hw_info_frame->avi_info_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->vendor_info_packet.valid) { - dc_service_memmove( - &encoder_info_frame->vendor, - &hw_info_frame->vendor_info_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->spd_packet.valid) { - dc_service_memmove( - &encoder_info_frame->spd, - &hw_info_frame->spd_packet, - sizeof(struct hw_info_packet)); - } - - if (hw_info_frame->vsc_packet.valid) { - dc_service_memmove( - &encoder_info_frame->vsc, - &hw_info_frame->vsc_packet, - sizeof(struct hw_info_packet)); - } -} - -static void build_info_frame(struct core_stream *stream) -{ - enum signal_type signal = SIGNAL_TYPE_NONE; - struct hw_info_frame info_frame = { { 0 } }; - - /* default all packets to invalid */ - info_frame.avi_info_packet.valid = false; - info_frame.gamut_packet.valid = false; - info_frame.vendor_info_packet.valid = false; - info_frame.spd_packet.valid = false; - info_frame.vsc_packet.valid = false; - - signal = stream->sink->public.sink_signal; - - /* HDMi and DP have different info packets*/ - if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { - set_avi_info_frame(&info_frame.avi_info_packet, - stream); - set_vendor_info_packet(stream, &info_frame.vendor_info_packet); - } - - translate_info_frame(&info_frame, - &stream->encoder_info_frame); -} - - bool dce110_construct_resource_pool( struct adapter_service *adapter_serv, struct dc *dc, @@ -744,99 +316,6 @@ void dce110_destruct_resource_pool(struct resource_pool *pool) } } -static void attach_stream_to_controller( - struct resource_context *res_ctx, - struct core_stream *stream) -{ - res_ctx->controller_ctx[stream->controller_idx].stream = stream; -} - -static bool assign_first_free_controller( - struct resource_context *res_ctx, - struct core_stream *stream) -{ - uint8_t i; - for (i = 0; i < res_ctx->pool.controller_count; i++) { - if (!res_ctx->controller_ctx[i].stream) { - stream->tg = res_ctx->pool.timing_generators[i]; - stream->mi = res_ctx->pool.mis[i]; - stream->ipp = res_ctx->pool.ipps[i]; - stream->xfm = res_ctx->pool.transforms[i]; - stream->opp = res_ctx->pool.opps[i]; - stream->controller_idx = i; - stream->dis_clk = res_ctx->pool.display_clock; - return true; - } - } - return false; -} - -static void set_stream_engine_in_use( - struct resource_context *res_ctx, - struct stream_encoder *stream_enc) -{ - int i; - - for (i = 0; i < res_ctx->pool.stream_enc_count; i++) { - if (res_ctx->pool.stream_enc[i] == stream_enc) - res_ctx->is_stream_enc_acquired[i] = true; - } -} - -static struct stream_encoder *find_first_free_match_stream_enc_for_link( - struct resource_context *res_ctx, - struct core_link *link) -{ - uint8_t i; - int8_t j = -1; - - for (i = 0; i < res_ctx->pool.stream_enc_count; i++) { - if (!res_ctx->is_stream_enc_acquired[i] && - res_ctx->pool.stream_enc[i]) { - /* Store first available for MST second display - * in daisy chain use case */ - j = i; - if (res_ctx->pool.stream_enc[i]->id == - link->link_enc->preferred_engine) - return res_ctx->pool.stream_enc[i]; - } - } - - /* TODO: Handle MST properly - * Currently pick next available stream encoder if found*/ - if (j >= 0 && link->public.sink[0]->sink_signal == - SIGNAL_TYPE_DISPLAY_PORT_MST) - return res_ctx->pool.stream_enc[j]; - - return NULL; -} - -/* TODO: release audio object */ -static void set_audio_in_use( - struct resource_context *res_ctx, - struct audio *audio) -{ - int i; - for (i = 0; i < res_ctx->pool.audio_count; i++) { - if (res_ctx->pool.audios[i] == audio) { - res_ctx->is_audio_acquired[i] = true; - } - } -} - -static struct audio *find_first_free_audio(struct resource_context *res_ctx) -{ - int i; - for (i = 0; i < res_ctx->pool.audio_count; i++) { - if (res_ctx->is_audio_acquired[i] == false) { - return res_ctx->pool.audios[i]; - } - } - - return 0; -} - - static struct clock_source *find_first_free_pll( struct resource_context *res_ctx) { @@ -850,135 +329,6 @@ static struct clock_source *find_first_free_pll( return 0; } -static bool check_timing_change(struct core_stream *cur_stream, - struct core_stream *new_stream) -{ - if (cur_stream == NULL) - return true; - - /* If sink pointer changed, it means this is a hotplug, we should do - * full hw setting. - */ - if (cur_stream->sink != new_stream->sink) - return true; - - return !is_same_timing( - &cur_stream->public.timing, - &new_stream->public.timing); -} - -static enum dc_status map_resources( - const struct dc *dc, - struct validate_context *context) -{ - uint8_t i, j; - - /* mark resources used for targets that are already active */ - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; - - if (!context->target_flags[i].unchanged) - continue; - - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - - attach_stream_to_controller( - &context->res_ctx, - stream); - - set_stream_engine_in_use( - &context->res_ctx, - stream->stream_enc); - - reference_clock_source( - &context->res_ctx, - stream->clock_source); - - if (stream->audio) { - set_audio_in_use(&context->res_ctx, - stream->audio); - } - } - } - - /* acquire new resources */ - for (i = 0; i < context->target_count; i++) { - struct core_target *target = context->targets[i]; - - if (context->target_flags[i].unchanged) - continue; - - for (j = 0; j < target->public.stream_count; j++) { - struct core_stream *stream = - DC_STREAM_TO_CORE(target->public.streams[j]); - struct core_stream *curr_stream; - - if (!assign_first_free_controller( - &context->res_ctx, stream)) - return DC_NO_CONTROLLER_RESOURCE; - - attach_stream_to_controller(&context->res_ctx, stream); - - stream->stream_enc = - find_first_free_match_stream_enc_for_link( - &context->res_ctx, - stream->sink->link); - - if (!stream->stream_enc) - return DC_NO_STREAM_ENG_RESOURCE; - - set_stream_engine_in_use( - &context->res_ctx, - stream->stream_enc); - stream->signal = - stream->sink->public.sink_signal; - - if (dc_is_dp_signal(stream->signal)) - stream->clock_source = context->res_ctx. - pool.clock_sources[DCE110_CLK_SRC_EXT]; - else - stream->clock_source = - find_used_clk_src_for_sharing( - context, stream); - if (stream->clock_source == NULL) - stream->clock_source = - find_first_free_pll(&context->res_ctx); - - if (stream->clock_source == NULL) - return DC_NO_CLOCK_SOURCE_RESOURCE; - - reference_clock_source( - &context->res_ctx, - stream->clock_source); - - /* TODO: Add check if ASIC support and EDID audio */ - if (!stream->sink->converter_disable_audio && - dc_is_audio_capable_signal( - stream->signal)) { - stream->audio = find_first_free_audio( - &context->res_ctx); - - if (!stream->audio) - return DC_NO_STREAM_AUDIO_RESOURCE; - - set_audio_in_use(&context->res_ctx, - stream->audio); - } - curr_stream = - dc->current_context.res_ctx.controller_ctx - [stream->controller_idx].stream; - context->res_ctx.controller_ctx[stream->controller_idx] - .flags.timing_changed = - check_timing_change(curr_stream, stream); - - } - } - - return DC_OK; -} - static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) { switch (crtc_id) { @@ -1143,7 +493,7 @@ static enum dc_status validate_mapped_resource( if (status != DC_OK) return status; - build_info_frame(stream); + dce_base_build_info_frame(stream); } } @@ -1260,6 +610,63 @@ static void set_target_unchanged( } } +static enum dc_status map_clock_resources( + const struct dc *dc, + struct validate_context *context) +{ + uint8_t i, j; + + /* mark resources used for targets that are already active */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + if (!context->target_flags[i].unchanged) + continue; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + reference_clock_source( + &context->res_ctx, + stream->clock_source); + } + } + + /* acquire new resources */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + if (context->target_flags[i].unchanged) + continue; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + if (dc_is_dp_signal(stream->signal)) + stream->clock_source = context->res_ctx. + pool.clock_sources[DCE110_CLK_SRC_EXT]; + else + stream->clock_source = + find_used_clk_src_for_sharing( + context, stream); + if (stream->clock_source == NULL) + stream->clock_source = + find_first_free_pll(&context->res_ctx); + + if (stream->clock_source == NULL) + return DC_NO_CLOCK_SOURCE_RESOURCE; + + reference_clock_source( + &context->res_ctx, + stream->clock_source); + } + } + + return DC_OK; +} + enum dc_status dce110_validate_with_context( const struct dc *dc, const struct dc_validation_set set[], @@ -1291,7 +698,8 @@ enum dc_status dce110_validate_with_context( context->res_ctx.pool = dc->res_pool; - result = map_resources(dc, context); + result = dce_base_map_resources(dc, context); + result = map_clock_resources(dc, context); if (result == DC_OK) result = validate_mapped_resource(dc, context); diff --git a/drivers/gpu/drm/amd/dal/dc/dce_base/Makefile b/drivers/gpu/drm/amd/dal/dc/dce_base/Makefile new file mode 100644 index 0000000..4f239f5 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce_base/Makefile @@ -0,0 +1,23 @@ +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE_BASE = dce_base_resource.o + +AMD_DAL_DCE_BASE = $(addprefix $(AMDDALPATH)/dc/dce_base/,$(DCE_BASE)) + +AMD_DAL_FILES += $(AMD_DAL_DCE_BASE) + + +############################################################################### +# DCE 11x +############################################################################### +ifdef 0#CONFIG_DRM_AMD_DAL_DCE11_0 +TG_DCE_BASE = dce_base_resource.o + +AMD_DAL_TG_DCE110 = $(addprefix \ + $(AMDDALPATH)/dc/dce_base/,$(TG_DCE_BASE)) + +AMD_DAL_FILES += $(AMD_DAL_TG_DCE_BASE) +endif + diff --git a/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c b/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c new file mode 100644 index 0000000..06047ab --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.c @@ -0,0 +1,667 @@ +/* +* 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 "dce_base_resource.h" + +#include "dc_services.h" + +#include "adjustment_types.h" +#include "set_mode_types.h" +#include "stream_encoder_types.h" +#include "link_encoder_types.h" + +#include "resource.h" + +static void attach_stream_to_controller( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + res_ctx->controller_ctx[stream->controller_idx].stream = stream; +} + +static void set_stream_engine_in_use( + struct resource_context *res_ctx, + struct stream_encoder *stream_enc) +{ + int i; + + for (i = 0; i < res_ctx->pool.stream_enc_count; i++) { + if (res_ctx->pool.stream_enc[i] == stream_enc) + res_ctx->is_stream_enc_acquired[i] = true; + } +} + +/* TODO: release audio object */ +static void set_audio_in_use( + struct resource_context *res_ctx, + struct audio *audio) +{ + int i; + for (i = 0; i < res_ctx->pool.audio_count; i++) { + if (res_ctx->pool.audios[i] == audio) { + res_ctx->is_audio_acquired[i] = true; + } + } +} + +static bool assign_first_free_controller( + struct resource_context *res_ctx, + struct core_stream *stream) +{ + uint8_t i; + for (i = 0; i < res_ctx->pool.controller_count; i++) { + if (!res_ctx->controller_ctx[i].stream) { + stream->tg = res_ctx->pool.timing_generators[i]; + stream->mi = res_ctx->pool.mis[i]; + stream->ipp = res_ctx->pool.ipps[i]; + stream->xfm = res_ctx->pool.transforms[i]; + stream->opp = res_ctx->pool.opps[i]; + stream->controller_idx = i; + stream->dis_clk = res_ctx->pool.display_clock; + return true; + } + } + return false; +} + +static struct stream_encoder *find_first_free_match_stream_enc_for_link( + struct resource_context *res_ctx, + struct core_link *link) +{ + uint8_t i; + int8_t j = -1; + + for (i = 0; i < res_ctx->pool.stream_enc_count; i++) { + if (!res_ctx->is_stream_enc_acquired[i] && + res_ctx->pool.stream_enc[i]) { + /* Store first available for MST second display + * in daisy chain use case */ + j = i; + if (res_ctx->pool.stream_enc[i]->id == + link->link_enc->preferred_engine) + return res_ctx->pool.stream_enc[i]; + } + } + + /* TODO: Handle MST properly + * Currently pick next available stream encoder if found*/ + if (j >= 0 && link->public.sink[0]->sink_signal == + SIGNAL_TYPE_DISPLAY_PORT_MST) + return res_ctx->pool.stream_enc[j]; + + return NULL; +} + +static struct audio *find_first_free_audio(struct resource_context *res_ctx) +{ + int i; + for (i = 0; i < res_ctx->pool.audio_count; i++) { + if (res_ctx->is_audio_acquired[i] == false) { + return res_ctx->pool.audios[i]; + } + } + + return 0; +} + +static bool check_timing_change(struct core_stream *cur_stream, + struct core_stream *new_stream) +{ + if (cur_stream == NULL) + return true; + + /* If sink pointer changed, it means this is a hotplug, we should do + * full hw setting. + */ + if (cur_stream->sink != new_stream->sink) + return true; + + return !is_same_timing( + &cur_stream->public.timing, + &new_stream->public.timing); +} + +enum dc_status dce_base_map_resources( + const struct dc *dc, + struct validate_context *context) +{ + uint8_t i, j; + + /* mark resources used for targets that are already active */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + if (!context->target_flags[i].unchanged) + continue; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + + attach_stream_to_controller( + &context->res_ctx, + stream); + + set_stream_engine_in_use( + &context->res_ctx, + stream->stream_enc); + + reference_clock_source( + &context->res_ctx, + stream->clock_source); + + if (stream->audio) { + set_audio_in_use(&context->res_ctx, + stream->audio); + } + } + } + + /* acquire new resources */ + for (i = 0; i < context->target_count; i++) { + struct core_target *target = context->targets[i]; + + if (context->target_flags[i].unchanged) + continue; + + for (j = 0; j < target->public.stream_count; j++) { + struct core_stream *stream = + DC_STREAM_TO_CORE(target->public.streams[j]); + struct core_stream *curr_stream; + + if (!assign_first_free_controller( + &context->res_ctx, stream)) + return DC_NO_CONTROLLER_RESOURCE; + + attach_stream_to_controller(&context->res_ctx, stream); + + stream->stream_enc = + find_first_free_match_stream_enc_for_link( + &context->res_ctx, + stream->sink->link); + + if (!stream->stream_enc) + return DC_NO_STREAM_ENG_RESOURCE; + + set_stream_engine_in_use( + &context->res_ctx, + stream->stream_enc); + stream->signal = + stream->sink->public.sink_signal; + + /* TODO: Add check if ASIC support and EDID audio */ + if (!stream->sink->converter_disable_audio && + dc_is_audio_capable_signal( + stream->signal)) { + stream->audio = find_first_free_audio( + &context->res_ctx); + + if (!stream->audio) + return DC_NO_STREAM_AUDIO_RESOURCE; + + set_audio_in_use(&context->res_ctx, + stream->audio); + } + curr_stream = + dc->current_context.res_ctx.controller_ctx + [stream->controller_idx].stream; + context->res_ctx.controller_ctx[stream->controller_idx] + .flags.timing_changed = + check_timing_change(curr_stream, stream); + + } + } + + return DC_OK; +} + +static enum ds_color_space build_default_color_space( + struct core_stream *stream) +{ + enum ds_color_space color_space = + DS_COLOR_SPACE_SRGB_FULLRANGE; + struct dc_crtc_timing *timing = &stream->public.timing; + + switch (stream->signal) { + /* TODO: implement other signal color space setting */ + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_DISPLAY_PORT_MST: + case SIGNAL_TYPE_EDP: + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + { + uint32_t pix_clk_khz; + + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 && + timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) { + if (timing->timing_standard == + TIMING_STANDARD_CEA770 && + timing->timing_standard == + TIMING_STANDARD_CEA861) + color_space = DS_COLOR_SPACE_SRGB_FULLRANGE; + + pix_clk_khz = timing->pix_clk_khz / 10; + if (timing->h_addressable == 640 && + timing->v_addressable == 480 && + (pix_clk_khz == 2520 || pix_clk_khz == 2517)) + color_space = DS_COLOR_SPACE_SRGB_FULLRANGE; + } else { + if (timing->timing_standard == + TIMING_STANDARD_CEA770 || + timing->timing_standard == + TIMING_STANDARD_CEA861) { + + color_space = + (timing->pix_clk_khz > PIXEL_CLOCK) ? + DS_COLOR_SPACE_YCBCR709 : + DS_COLOR_SPACE_YCBCR601; + } + } + break; + } + default: + switch (timing->pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + case PIXEL_ENCODING_YCBCR444: + if (timing->pix_clk_khz > PIXEL_CLOCK) + color_space = DS_COLOR_SPACE_YCBCR709; + else + color_space = DS_COLOR_SPACE_YCBCR601; + break; + default: + break; + } + break; + } + return color_space; +} + +static void translate_info_frame(const struct hw_info_frame *hw_info_frame, + struct encoder_info_frame *encoder_info_frame) +{ + dc_service_memset( + encoder_info_frame, 0, sizeof(struct encoder_info_frame)); + + /* For gamut we recalc checksum */ + if (hw_info_frame->gamut_packet.valid) { + uint8_t chk_sum = 0; + uint8_t *ptr; + uint8_t i; + + dc_service_memmove( + &encoder_info_frame->gamut, + &hw_info_frame->gamut_packet, + sizeof(struct hw_info_packet)); + + /*start of the Gamut data. */ + ptr = &encoder_info_frame->gamut.sb[3]; + + for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++) + chk_sum += ptr[i]; + + encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum); + } + + if (hw_info_frame->avi_info_packet.valid) { + dc_service_memmove( + &encoder_info_frame->avi, + &hw_info_frame->avi_info_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->vendor_info_packet.valid) { + dc_service_memmove( + &encoder_info_frame->vendor, + &hw_info_frame->vendor_info_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->spd_packet.valid) { + dc_service_memmove( + &encoder_info_frame->spd, + &hw_info_frame->spd_packet, + sizeof(struct hw_info_packet)); + } + + if (hw_info_frame->vsc_packet.valid) { + dc_service_memmove( + &encoder_info_frame->vsc, + &hw_info_frame->vsc_packet, + sizeof(struct hw_info_packet)); + } +} + +static void set_avi_info_frame(struct hw_info_packet *info_packet, + struct core_stream *stream) +{ + enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN; + struct info_frame info_frame = { {0} }; + uint32_t pixel_encoding = 0; + enum scanning_type scan_type = SCANNING_TYPE_NODATA; + enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; + bool itc = false; + uint8_t cn0_cn1 = 0; + uint8_t *check_sum = NULL; + uint8_t byte_index = 0; + + if (info_packet == NULL) + return; + + color_space = build_default_color_space(stream); + + /* Initialize header */ + info_frame.avi_info_packet.info_packet_hdmi.bits.header. + info_frame_type = INFO_FRAME_AVI; + /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall + * not be used in HDMI 2.0 (Section 10.1) */ + info_frame.avi_info_packet.info_packet_hdmi.bits.header.version = + INFO_FRAME_VERSION_2; + info_frame.avi_info_packet.info_packet_hdmi.bits.header.length = + INFO_FRAME_SIZE_AVI; + + /* IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built + * according to HDMI 2.0 spec (Section 10.1) + * Add "case PixelEncoding_YCbCr420: pixelEncoding = 3; break;" + * when YCbCr 4:2:0 is supported by DAL hardware. */ + + switch (stream->public.timing.pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + pixel_encoding = 1; + break; + + case PIXEL_ENCODING_YCBCR444: + pixel_encoding = 2; + break; + + case PIXEL_ENCODING_RGB: + default: + pixel_encoding = 0; + } + + /* Y0_Y1_Y2 : The pixel encoding */ + /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ + info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 = + pixel_encoding; + + + /* A0 = 1 Active Format Information valid */ + info_frame.avi_info_packet.info_packet_hdmi.bits.A0 = + ACTIVE_FORMAT_VALID; + + /* B0, B1 = 3; Bar info data is valid */ + info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 = + BAR_INFO_BOTH_VALID; + + info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 = + PICTURE_SCALING_UNIFORM; + + /* S0, S1 : Underscan / Overscan */ + /* TODO: un-hardcode scan type */ + scan_type = SCANNING_TYPE_UNDERSCAN; + info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type; + + /* C0, C1 : Colorimetry */ + if (color_space == DS_COLOR_SPACE_YCBCR709) + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_ITU709; + else if (color_space == DS_COLOR_SPACE_YCBCR601) + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_ITU601; + else + info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 = + COLORIMETRY_NO_DATA; + + + /* TODO: un-hardcode aspect ratio */ + aspect = stream->public.timing.aspect_ratio; + + switch (aspect) { + case ASPECT_RATIO_4_3: + case ASPECT_RATIO_16_9: + info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect; + break; + + case ASPECT_RATIO_NO_DATA: + case ASPECT_RATIO_64_27: + case ASPECT_RATIO_256_135: + default: + info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0; + } + + /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ + info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 = + ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; + + /* TODO: un-hardcode cn0_cn1 and itc */ + cn0_cn1 = 0; + itc = false; + + if (itc) { + info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1; + info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 = + cn0_cn1; + } + + /* TODO: un-hardcode q0_q1 */ + if (color_space == DS_COLOR_SPACE_SRGB_FULLRANGE) + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_FULL_RANGE; + else if (color_space == DS_COLOR_SPACE_SRGB_LIMITEDRANGE) + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_LIMITED_RANGE; + else + info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 = + RGB_QUANTIZATION_DEFAULT_RANGE; + + /* TODO : We should handle YCC quantization, + * but we do not have matrix calculation */ + info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 = + YYC_QUANTIZATION_LIMITED_RANGE; + + info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 = + stream->public.timing.vic; + + /* pixel repetition + * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel + * repetition start from 1 */ + info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0; + + /* Bar Info + * barTop: Line Number of End of Top Bar. + * barBottom: Line Number of Start of Bottom Bar. + * barLeft: Pixel Number of End of Left Bar. + * barRight: Pixel Number of Start of Right Bar. */ + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top = + stream->public.timing.v_border_top; + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom = + (stream->public.timing.v_border_top + - stream->public.timing.v_border_bottom + 1); + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left = + stream->public.timing.h_border_left; + info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right = + (stream->public.timing.h_total + - stream->public.timing.h_border_right + 1); + + /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ + check_sum = + &info_frame. + avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0]; + *check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI + + INFO_FRAME_VERSION_2; + + for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++) + *check_sum += info_frame.avi_info_packet.info_packet_hdmi. + packet_raw_data.sb[byte_index]; + + /* one byte complement */ + *check_sum = (uint8_t) (0x100 - *check_sum); + + /* Store in hw_path_mode */ + info_packet->hb0 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0; + info_packet->hb1 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1; + info_packet->hb2 = + info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2; + + for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++) + info_packet->sb[byte_index] = info_frame.avi_info_packet. + info_packet_hdmi.packet_raw_data.sb[byte_index]; + + info_packet->valid = true; +} + +static void set_vendor_info_packet(struct core_stream *stream, + struct hw_info_packet *info_packet) +{ + uint32_t length = 0; + bool hdmi_vic_mode = false; + uint8_t checksum = 0; + uint32_t i = 0; + enum dc_timing_3d_format format; + + ASSERT_CRITICAL(stream != NULL); + ASSERT_CRITICAL(info_packet != NULL); + + format = stream->public.timing.timing_3d_format; + + /* Can be different depending on packet content */ + length = 5; + + if (stream->public.timing.hdmi_vic != 0 + && stream->public.timing.h_total >= 3840 + && stream->public.timing.v_total >= 2160) + hdmi_vic_mode = true; + + /* According to HDMI 1.4a CTS, VSIF should be sent + * for both 3D stereo and HDMI VIC modes. + * For all other modes, there is no VSIF sent. */ + + if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode) + return; + + /* 24bit IEEE Registration identifier (0x000c03). LSB first. */ + info_packet->sb[1] = 0x03; + info_packet->sb[2] = 0x0C; + info_packet->sb[3] = 0x00; + + /*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format. + * The value for HDMI_Video_Format are: + * 0x0 (0b000) - No additional HDMI video format is presented in this + * packet + * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC + * parameter follows + * 0x2 (0b010) - 3D format indication present. 3D_Structure and + * potentially 3D_Ext_Data follows + * 0x3..0x7 (0b011..0b111) - reserved for future use */ + if (format != TIMING_3D_FORMAT_NONE) + info_packet->sb[4] = (2 << 5); + else if (hdmi_vic_mode) + info_packet->sb[4] = (1 << 5); + + /* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2): + * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure. + * The value for 3D_Structure are: + * 0x0 - Frame Packing + * 0x1 - Field Alternative + * 0x2 - Line Alternative + * 0x3 - Side-by-Side (full) + * 0x4 - L + depth + * 0x5 - L + depth + graphics + graphics-depth + * 0x6 - Top-and-Bottom + * 0x7 - Reserved for future use + * 0x8 - Side-by-Side (Half) + * 0x9..0xE - Reserved for future use + * 0xF - Not used */ + switch (format) { + case TIMING_3D_FORMAT_HW_FRAME_PACKING: + case TIMING_3D_FORMAT_SW_FRAME_PACKING: + info_packet->sb[5] = (0x0 << 4); + break; + + case TIMING_3D_FORMAT_SIDE_BY_SIDE: + case TIMING_3D_FORMAT_SBS_SW_PACKED: + info_packet->sb[5] = (0x8 << 4); + length = 6; + break; + + case TIMING_3D_FORMAT_TOP_AND_BOTTOM: + case TIMING_3D_FORMAT_TB_SW_PACKED: + info_packet->sb[5] = (0x6 << 4); + break; + + default: + break; + } + + /*PB5: If PB4 is set to 0x1 (extended resolution format) + * fill PB5 with the correct HDMI VIC code */ + if (hdmi_vic_mode) + info_packet->sb[5] = stream->public.timing.hdmi_vic; + + /* Header */ + info_packet->hb0 = 0x81; /* VSIF packet type. */ + info_packet->hb1 = 0x01; /* Version */ + + /* 4 lower bits = Length, 4 higher bits = 0 (reserved) */ + info_packet->hb2 = (uint8_t) (length); + + /* Calculate checksum */ + checksum = 0; + checksum += info_packet->hb0; + checksum += info_packet->hb1; + checksum += info_packet->hb2; + + for (i = 1; i <= length; i++) + checksum += info_packet->sb[i]; + + info_packet->sb[0] = (uint8_t) (0x100 - checksum); + + info_packet->valid = true; +} + +void dce_base_build_info_frame(struct core_stream *stream) +{ + enum signal_type signal = SIGNAL_TYPE_NONE; + struct hw_info_frame info_frame = { { 0 } }; + + /* default all packets to invalid */ + info_frame.avi_info_packet.valid = false; + info_frame.gamut_packet.valid = false; + info_frame.vendor_info_packet.valid = false; + info_frame.spd_packet.valid = false; + info_frame.vsc_packet.valid = false; + + signal = stream->sink->public.sink_signal; + + /* HDMi and DP have different info packets*/ + if (signal == SIGNAL_TYPE_HDMI_TYPE_A) { + set_avi_info_frame(&info_frame.avi_info_packet, + stream); + set_vendor_info_packet(stream, &info_frame.vendor_info_packet); + } + + translate_info_frame(&info_frame, + &stream->encoder_info_frame); +} diff --git a/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.h b/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.h new file mode 100644 index 0000000..eec06f0 --- /dev/null +++ b/drivers/gpu/drm/amd/dal/dc/dce_base/dce_base_resource.h @@ -0,0 +1,37 @@ +/* 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 __DCE_BASE_RESOURCE_H__ +#define __DCE_BASE_RESOURCE_H__ + +#include "dc_services.h" +#include "resource.h" + +void dce_base_build_info_frame(struct core_stream *stream); + +enum dc_status dce_base_map_resources( + const struct dc *dc, + struct validate_context *context); + +#endif -- 2.7.4