cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

link_hwss_hpo_dp.c (9990B)


      1/*
      2 * Copyright 2022 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25#include "link_hwss_hpo_dp.h"
     26#include "dm_helpers.h"
     27#include "core_types.h"
     28#include "dccg.h"
     29#include "dc_link_dp.h"
     30#include "clk_mgr.h"
     31
     32static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link)
     33{
     34	switch (link->link_enc->transmitter) {
     35	case TRANSMITTER_UNIPHY_A:
     36		return PHYD32CLKA;
     37	case TRANSMITTER_UNIPHY_B:
     38		return PHYD32CLKB;
     39	case TRANSMITTER_UNIPHY_C:
     40		return PHYD32CLKC;
     41	case TRANSMITTER_UNIPHY_D:
     42		return PHYD32CLKD;
     43	case TRANSMITTER_UNIPHY_E:
     44		return PHYD32CLKE;
     45	default:
     46		return PHYD32CLKA;
     47	}
     48}
     49
     50static void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
     51		struct fixed31_32 throttled_vcp_size)
     52{
     53	struct hpo_dp_stream_encoder *hpo_dp_stream_encoder =
     54			pipe_ctx->stream_res.hpo_dp_stream_enc;
     55	struct hpo_dp_link_encoder *hpo_dp_link_encoder =
     56			pipe_ctx->link_res.hpo_dp_link_enc;
     57
     58	hpo_dp_link_encoder->funcs->set_throttled_vcp_size(hpo_dp_link_encoder,
     59			hpo_dp_stream_encoder->inst,
     60			throttled_vcp_size);
     61}
     62
     63static void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
     64		const struct dc_link_settings *link_settings,
     65		struct fixed31_32 throttled_vcp_size)
     66{
     67	struct hpo_dp_stream_encoder *hpo_dp_stream_encoder =
     68			pipe_ctx->stream_res.hpo_dp_stream_enc;
     69	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
     70	struct fixed31_32 h_blank_in_ms, time_slot_in_ms, mtp_cnt_per_h_blank;
     71	uint32_t link_bw_in_kbps =
     72			dc_link_bandwidth_kbps(pipe_ctx->stream->link, link_settings);
     73	uint16_t hblank_min_symbol_width = 0;
     74
     75	if (link_bw_in_kbps > 0) {
     76		h_blank_in_ms = dc_fixpt_div(dc_fixpt_from_int(
     77				timing->h_total - timing->h_addressable),
     78				dc_fixpt_from_fraction(timing->pix_clk_100hz, 10));
     79		time_slot_in_ms = dc_fixpt_from_fraction(32 * 4, link_bw_in_kbps);
     80		mtp_cnt_per_h_blank = dc_fixpt_div(h_blank_in_ms,
     81				dc_fixpt_mul_int(time_slot_in_ms, 64));
     82		hblank_min_symbol_width = dc_fixpt_floor(
     83				dc_fixpt_mul(mtp_cnt_per_h_blank, throttled_vcp_size));
     84	}
     85
     86	hpo_dp_stream_encoder->funcs->set_hblank_min_symbol_width(hpo_dp_stream_encoder,
     87			hblank_min_symbol_width);
     88}
     89
     90static int get_odm_segment_count(struct pipe_ctx *pipe_ctx)
     91{
     92	struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
     93	int count = 1;
     94
     95	while (odm_pipe != NULL) {
     96		count++;
     97		odm_pipe = odm_pipe->next_odm_pipe;
     98	}
     99
    100	return count;
    101}
    102
    103static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
    104{
    105	struct dc *dc = pipe_ctx->stream->ctx->dc;
    106	struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
    107	struct hpo_dp_link_encoder *link_enc = pipe_ctx->link_res.hpo_dp_link_enc;
    108	struct dccg *dccg = dc->res_pool->dccg;
    109	struct timing_generator *tg = pipe_ctx->stream_res.tg;
    110	struct dtbclk_dto_params dto_params = {0};
    111	enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link);
    112
    113	dto_params.otg_inst = tg->inst;
    114	dto_params.pixclk_khz = pipe_ctx->stream->phy_pix_clk;
    115	dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx);
    116	dto_params.timing = &pipe_ctx->stream->timing;
    117	dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr);
    118
    119	dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst);
    120	dccg->funcs->enable_symclk32_se(dccg, stream_enc->inst, phyd32clk);
    121	dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
    122	stream_enc->funcs->enable_stream(stream_enc);
    123	stream_enc->funcs->map_stream_to_link(stream_enc, stream_enc->inst, link_enc->inst);
    124}
    125
    126static void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
    127{
    128	struct dc *dc = pipe_ctx->stream->ctx->dc;
    129	struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
    130	struct dccg *dccg = dc->res_pool->dccg;
    131	struct timing_generator *tg = pipe_ctx->stream_res.tg;
    132	struct dtbclk_dto_params dto_params = {0};
    133
    134	dto_params.otg_inst = tg->inst;
    135	dto_params.timing = &pipe_ctx->stream->timing;
    136
    137	stream_enc->funcs->disable(stream_enc);
    138	dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
    139	dccg->funcs->disable_symclk32_se(dccg, stream_enc->inst);
    140	dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst);
    141}
    142
    143static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
    144{
    145	struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
    146	struct dc_stream_state *stream = pipe_ctx->stream;
    147	struct dc_link *link = stream->link;
    148
    149	stream_enc->funcs->set_stream_attribute(
    150			stream_enc,
    151			&stream->timing,
    152			stream->output_color_space,
    153			stream->use_vsc_sdp_for_colorimetry,
    154			stream->timing.flags.DSC,
    155			false);
    156	dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
    157}
    158
    159static void enable_hpo_dp_fpga_link_output(struct dc_link *link,
    160		const struct link_resource *link_res,
    161		enum signal_type signal,
    162		enum clock_source_id clock_source,
    163		const struct dc_link_settings *link_settings)
    164{
    165	const struct dc *dc = link->dc;
    166	enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(link);
    167	int phyd32clk_freq_khz = link_settings->link_rate == LINK_RATE_UHBR10 ? 312500 :
    168			link_settings->link_rate == LINK_RATE_UHBR13_5 ? 412875 :
    169			link_settings->link_rate == LINK_RATE_UHBR20 ? 625000 : 0;
    170
    171	dm_set_phyd32clk(dc->ctx, phyd32clk_freq_khz);
    172	dc->res_pool->dccg->funcs->set_physymclk(
    173			dc->res_pool->dccg,
    174			link->link_enc_hw_inst,
    175			PHYSYMCLK_FORCE_SRC_PHYD32CLK,
    176			true);
    177	dc->res_pool->dccg->funcs->enable_symclk32_le(
    178			dc->res_pool->dccg,
    179			link_res->hpo_dp_link_enc->inst,
    180			phyd32clk);
    181	link_res->hpo_dp_link_enc->funcs->link_enable(
    182			link_res->hpo_dp_link_enc,
    183			link_settings->lane_count);
    184
    185}
    186
    187static void enable_hpo_dp_link_output(struct dc_link *link,
    188		const struct link_resource *link_res,
    189		enum signal_type signal,
    190		enum clock_source_id clock_source,
    191		const struct dc_link_settings *link_settings)
    192{
    193	if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment))
    194		enable_hpo_dp_fpga_link_output(link, link_res, signal,
    195				clock_source, link_settings);
    196	else
    197		link_res->hpo_dp_link_enc->funcs->enable_link_phy(
    198				link_res->hpo_dp_link_enc,
    199				link_settings,
    200				link->link_enc->transmitter,
    201				link->link_enc->hpd_source);
    202}
    203
    204
    205static void disable_hpo_dp_fpga_link_output(struct dc_link *link,
    206		const struct link_resource *link_res,
    207		enum signal_type signal)
    208{
    209	const struct dc *dc = link->dc;
    210
    211	link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc);
    212	dc->res_pool->dccg->funcs->disable_symclk32_le(
    213			dc->res_pool->dccg,
    214			link_res->hpo_dp_link_enc->inst);
    215	dc->res_pool->dccg->funcs->set_physymclk(
    216			dc->res_pool->dccg,
    217			link->link_enc_hw_inst,
    218			PHYSYMCLK_FORCE_SRC_SYMCLK,
    219			false);
    220	dm_set_phyd32clk(dc->ctx, 0);
    221}
    222
    223static void disable_hpo_dp_link_output(struct dc_link *link,
    224		const struct link_resource *link_res,
    225		enum signal_type signal)
    226{
    227	if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment)) {
    228		disable_hpo_dp_fpga_link_output(link, link_res, signal);
    229	} else {
    230		link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc);
    231		link_res->hpo_dp_link_enc->funcs->disable_link_phy(
    232				link_res->hpo_dp_link_enc, signal);
    233	}
    234}
    235
    236static void set_hpo_dp_link_test_pattern(struct dc_link *link,
    237		const struct link_resource *link_res,
    238		struct encoder_set_dp_phy_pattern_param *tp_params)
    239{
    240	link_res->hpo_dp_link_enc->funcs->set_link_test_pattern(
    241			link_res->hpo_dp_link_enc, tp_params);
    242	dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
    243}
    244
    245static void set_hpo_dp_lane_settings(struct dc_link *link,
    246		const struct link_resource *link_res,
    247		const struct dc_link_settings *link_settings,
    248		const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
    249{
    250	link_res->hpo_dp_link_enc->funcs->set_ffe(
    251			link_res->hpo_dp_link_enc,
    252			link_settings,
    253			lane_settings[0].FFE_PRESET.raw);
    254}
    255
    256static void update_hpo_dp_stream_allocation_table(struct dc_link *link,
    257		const struct link_resource *link_res,
    258		const struct link_mst_stream_allocation_table *table)
    259{
    260	link_res->hpo_dp_link_enc->funcs->update_stream_allocation_table(
    261			link_res->hpo_dp_link_enc,
    262			table);
    263}
    264
    265static const struct link_hwss hpo_dp_link_hwss = {
    266	.setup_stream_encoder = setup_hpo_dp_stream_encoder,
    267	.reset_stream_encoder = reset_hpo_dp_stream_encoder,
    268	.setup_stream_attribute = setup_hpo_dp_stream_attribute,
    269	.ext = {
    270		.set_throttled_vcp_size = set_hpo_dp_throttled_vcp_size,
    271		.set_hblank_min_symbol_width = set_hpo_dp_hblank_min_symbol_width,
    272		.enable_dp_link_output = enable_hpo_dp_link_output,
    273		.disable_dp_link_output = disable_hpo_dp_link_output,
    274		.set_dp_link_test_pattern  = set_hpo_dp_link_test_pattern,
    275		.set_dp_lane_settings = set_hpo_dp_lane_settings,
    276		.update_stream_allocation_table = update_hpo_dp_stream_allocation_table,
    277	},
    278};
    279
    280bool can_use_hpo_dp_link_hwss(const struct dc_link *link,
    281		const struct link_resource *link_res)
    282{
    283	return link_res->hpo_dp_link_enc != NULL;
    284}
    285
    286const struct link_hwss *get_hpo_dp_link_hwss(void)
    287{
    288	return &hpo_dp_link_hwss;
    289}
    290