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

dcn21_hwseq.c (8173B)


      1/*
      2 * Copyright 2016 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
     26#include "dm_services.h"
     27#include "dm_helpers.h"
     28#include "core_types.h"
     29#include "resource.h"
     30#include "dce/dce_hwseq.h"
     31#include "dce110/dce110_hw_sequencer.h"
     32#include "dcn21_hwseq.h"
     33#include "vmid.h"
     34#include "reg_helper.h"
     35#include "hw/clk_mgr.h"
     36#include "dc_dmub_srv.h"
     37#include "abm.h"
     38
     39
     40#define DC_LOGGER_INIT(logger)
     41
     42#define CTX \
     43	hws->ctx
     44#define REG(reg)\
     45	hws->regs->reg
     46
     47#undef FN
     48#define FN(reg_name, field_name) \
     49	hws->shifts->field_name, hws->masks->field_name
     50
     51/* Temporary read settings, future will get values from kmd directly */
     52static void mmhub_update_page_table_config(struct dcn_hubbub_phys_addr_config *config,
     53		struct dce_hwseq *hws)
     54{
     55	uint32_t page_table_base_hi;
     56	uint32_t page_table_base_lo;
     57
     58	REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
     59			PAGE_DIRECTORY_ENTRY_HI32, &page_table_base_hi);
     60	REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
     61			PAGE_DIRECTORY_ENTRY_LO32, &page_table_base_lo);
     62
     63	config->gart_config.page_table_base_addr = ((uint64_t)page_table_base_hi << 32) | page_table_base_lo;
     64
     65}
     66
     67int dcn21_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
     68{
     69	struct dcn_hubbub_phys_addr_config config;
     70
     71	config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
     72	config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
     73	config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
     74	config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
     75	config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
     76	config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
     77	config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
     78	config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
     79	config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
     80
     81	mmhub_update_page_table_config(&config, hws);
     82
     83	return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
     84}
     85
     86// work around for Renoir s0i3, if register is programmed, bypass golden init.
     87
     88bool dcn21_s0i3_golden_init_wa(struct dc *dc)
     89{
     90	struct dce_hwseq *hws = dc->hwseq;
     91	uint32_t value = 0;
     92
     93	value = REG_READ(MICROSECOND_TIME_BASE_DIV);
     94
     95	return value != 0x00120464;
     96}
     97
     98void dcn21_exit_optimized_pwr_state(
     99		const struct dc *dc,
    100		struct dc_state *context)
    101{
    102	dc->clk_mgr->funcs->update_clocks(
    103			dc->clk_mgr,
    104			context,
    105			false);
    106}
    107
    108void dcn21_optimize_pwr_state(
    109		const struct dc *dc,
    110		struct dc_state *context)
    111{
    112	dc->clk_mgr->funcs->update_clocks(
    113			dc->clk_mgr,
    114			context,
    115			true);
    116}
    117
    118/* If user hotplug a HDMI monitor while in monitor off,
    119 * OS will do a mode set (with output timing) but keep output off.
    120 * In this case DAL will ask vbios to power up the pll in the PHY.
    121 * If user unplug the monitor (while we are on monitor off) or
    122 * system attempt to enter modern standby (which we will disable PLL),
    123 * PHY will hang on the next mode set attempt.
    124 * if enable PLL follow by disable PLL (without executing lane enable/disable),
    125 * RDPCS_PHY_DP_MPLLB_STATE remains 1,
    126 * which indicate that PLL disable attempt actually didn't go through.
    127 * As a workaround, insert PHY lane enable/disable before PLL disable.
    128 */
    129void dcn21_PLAT_58856_wa(struct dc_state *context, struct pipe_ctx *pipe_ctx)
    130{
    131	if (!pipe_ctx->stream->dpms_off)
    132		return;
    133
    134	pipe_ctx->stream->dpms_off = false;
    135	core_link_enable_stream(context, pipe_ctx);
    136	core_link_disable_stream(pipe_ctx);
    137	pipe_ctx->stream->dpms_off = true;
    138}
    139
    140static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst)
    141{
    142	union dmub_rb_cmd cmd;
    143	struct dc_context *dc = abm->ctx;
    144	uint32_t ramping_boundary = 0xFFFF;
    145
    146	memset(&cmd, 0, sizeof(cmd));
    147	cmd.abm_set_pipe.header.type = DMUB_CMD__ABM;
    148	cmd.abm_set_pipe.header.sub_type = DMUB_CMD__ABM_SET_PIPE;
    149	cmd.abm_set_pipe.abm_set_pipe_data.otg_inst = otg_inst;
    150	cmd.abm_set_pipe.abm_set_pipe_data.set_pipe_option = option;
    151	cmd.abm_set_pipe.abm_set_pipe_data.panel_inst = panel_inst;
    152	cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary;
    153	cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data);
    154
    155	dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
    156	dc_dmub_srv_cmd_execute(dc->dmub_srv);
    157	dc_dmub_srv_wait_idle(dc->dmub_srv);
    158
    159	return true;
    160}
    161
    162void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
    163{
    164	struct abm *abm = pipe_ctx->stream_res.abm;
    165	uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
    166	struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
    167
    168	struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu;
    169
    170	if (dmcu) {
    171		dce110_set_abm_immediate_disable(pipe_ctx);
    172		return;
    173	}
    174
    175	if (abm && panel_cntl) {
    176		dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_IMMEDIATELY_DISABLE,
    177				panel_cntl->inst);
    178		panel_cntl->funcs->store_backlight_level(panel_cntl);
    179	}
    180}
    181
    182void dcn21_set_pipe(struct pipe_ctx *pipe_ctx)
    183{
    184	struct abm *abm = pipe_ctx->stream_res.abm;
    185	uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
    186	struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
    187	struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu;
    188
    189	if (dmcu) {
    190		dce110_set_pipe(pipe_ctx);
    191		return;
    192	}
    193
    194	if (abm && panel_cntl)
    195		dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
    196}
    197
    198bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
    199		uint32_t backlight_pwm_u16_16,
    200		uint32_t frame_ramp)
    201{
    202	union dmub_rb_cmd cmd;
    203	struct dc_context *dc = pipe_ctx->stream->ctx;
    204	struct abm *abm = pipe_ctx->stream_res.abm;
    205	uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
    206	struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
    207
    208	if (dc->dc->res_pool->dmcu) {
    209		dce110_set_backlight_level(pipe_ctx, backlight_pwm_u16_16, frame_ramp);
    210		return true;
    211	}
    212
    213	if (abm && panel_cntl)
    214		dmub_abm_set_pipe(abm, otg_inst, SET_ABM_PIPE_NORMAL, panel_cntl->inst);
    215
    216	memset(&cmd, 0, sizeof(cmd));
    217	cmd.abm_set_backlight.header.type = DMUB_CMD__ABM;
    218	cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT;
    219	cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp;
    220	cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16;
    221	cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
    222	cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_cntl->inst);
    223	cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
    224
    225	dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd);
    226	dc_dmub_srv_cmd_execute(dc->dmub_srv);
    227	dc_dmub_srv_wait_idle(dc->dmub_srv);
    228
    229	return true;
    230}
    231
    232bool dcn21_is_abm_supported(struct dc *dc,
    233		struct dc_state *context, struct dc_stream_state *stream)
    234{
    235	int i;
    236
    237	for (i = 0; i < dc->res_pool->pipe_count; i++) {
    238		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    239
    240		if (pipe_ctx->stream == stream &&
    241				(pipe_ctx->prev_odm_pipe == NULL && pipe_ctx->next_odm_pipe == NULL))
    242			return true;
    243	}
    244	return false;
    245}
    246