Commit ac2e555e authored by Aurabindo Pillai's avatar Aurabindo Pillai Committed by Alex Deucher

drm/amd/display: Add DMCUB source files and changes for DCN32/321

DMCUB is the display engine microcontroller which aids in modesetting
and other display related features.
Signed-off-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4f29f9cf
......@@ -250,6 +250,37 @@ void dc_dmub_trace_event_control(struct dc *dc, bool enable)
dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable);
}
void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub)
{
union dmub_rb_cmd cmd = { 0 };
enum dmub_status status;
if (!dmub) {
return;
}
memset(&cmd, 0, sizeof(cmd));
/* Prepare fw command */
cmd.query_feature_caps.header.type = DMUB_CMD__QUERY_FEATURE_CAPS;
cmd.query_feature_caps.header.sub_type = 0;
cmd.query_feature_caps.header.ret_status = 1;
cmd.query_feature_caps.header.payload_bytes = sizeof(struct dmub_cmd_query_feature_caps_data);
/* Send command to fw */
status = dmub_srv_cmd_with_reply_data(dmub, &cmd);
ASSERT(status == DMUB_STATUS_OK);
/* If command was processed, copy feature caps to dmub srv */
if (status == DMUB_STATUS_OK &&
cmd.query_feature_caps.header.ret_status == 0) {
memcpy(&dmub->feature_caps,
&cmd.query_feature_caps.query_feature_caps_data,
sizeof(struct dmub_feature_caps));
}
}
bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data)
{
if (!dc_dmub_srv || !dc_dmub_srv->dmub || !diag_data)
......
......@@ -68,6 +68,8 @@ bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_bu
void dc_dmub_trace_event_control(struct dc *dc, bool enable);
void dc_dmub_srv_query_caps_cmd(struct dmub_srv *dmub);
void dc_dmub_srv_clear_inbox0_ack(struct dc_dmub_srv *dmub_srv);
void dc_dmub_srv_wait_for_inbox0_ack(struct dc_dmub_srv *dmub_srv);
void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, union dmub_inbox0_data_register data);
......
......@@ -246,6 +246,7 @@ struct dmub_srv_hw_params {
bool dpia_supported;
bool disable_dpia;
bool usb4_cm_version;
bool fw_in_system_memory;
};
/**
......@@ -310,6 +311,9 @@ struct dmub_srv_hw_funcs {
const struct dmub_window *cw0,
const struct dmub_window *cw1);
void (*backdoor_load_zfb_mode)(struct dmub_srv *dmub,
const struct dmub_window *cw0,
const struct dmub_window *cw1);
void (*setup_windows)(struct dmub_srv *dmub,
const struct dmub_window *cw2,
const struct dmub_window *cw3,
......@@ -365,6 +369,7 @@ struct dmub_srv_hw_funcs {
uint32_t (*get_gpint_dataout)(struct dmub_srv *dmub);
void (*configure_dmub_in_system_memory)(struct dmub_srv *dmub);
void (*clear_inbox0_ack_register)(struct dmub_srv *dmub);
uint32_t (*read_inbox0_ack_register)(struct dmub_srv *dmub);
void (*send_inbox0_cmd)(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
......@@ -412,6 +417,7 @@ struct dmub_srv {
/* private: internal use only */
const struct dmub_srv_common_regs *regs;
const struct dmub_srv_dcn31_regs *regs_dcn31;
const struct dmub_srv_dcn32_regs *regs_dcn32;
struct dmub_srv_base_funcs funcs;
struct dmub_srv_hw_funcs hw_funcs;
......
......@@ -641,7 +641,10 @@ enum dmub_cmd_type {
* Command type used for all panel control commands.
*/
DMUB_CMD__PANEL_CNTL = 74,
/**
* Command type used for <TODO:description>
*/
DMUB_CMD__CAB_FOR_SS = 75,
/**
* Command type used for interfacing with DPIA.
*/
......@@ -878,6 +881,23 @@ struct dmub_rb_cmd_mall {
uint8_t reserved2; /**< Reserved bits */
};
/**
* enum dmub_cmd_cab_type - TODO:
*/
enum dmub_cmd_cab_type {
DMUB_CMD__CAB_NO_IDLE_OPTIMIZATION = 0,
DMUB_CMD__CAB_NO_DCN_REQ = 1,
DMUB_CMD__CAB_DCN_SS_FIT_IN_CAB = 2,
};
/**
* struct dmub_rb_cmd_cab_for_ss - TODO:
*/
struct dmub_rb_cmd_cab_for_ss {
struct dmub_cmd_header header;
uint8_t cab_alloc_ways; /* total number of ways */
uint8_t debug_bits; /* debug bits */
};
/**
* enum dmub_cmd_idle_opt_type - Idle optimization command type.
*/
......@@ -2693,6 +2713,10 @@ union dmub_rb_cmd {
* Definition of a DMUB_CMD__MALL command.
*/
struct dmub_rb_cmd_mall mall;
/**
* Definition of a DMUB_CMD__CAB command.
*/
struct dmub_rb_cmd_cab_for_ss cab;
/**
* Definition of a DMUB_CMD__IDLE_OPT_DCN_RESTORE command.
*/
......
......@@ -23,6 +23,7 @@
DMUB = dmub_srv.o dmub_srv_stat.o dmub_reg.o dmub_dcn20.o dmub_dcn21.o
DMUB += dmub_dcn30.o dmub_dcn301.o dmub_dcn302.o dmub_dcn303.o
DMUB += dmub_dcn31.o dmub_dcn315.o dmub_dcn316.o
DMUB += dmub_dcn32.o
AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB))
......
/*
* Copyright 2022 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 "../dmub_srv.h"
#include "dmub_reg.h"
#include "dmub_dcn32.h"
#include "dcn/dcn_3_2_0_offset.h"
#include "dcn/dcn_3_2_0_sh_mask.h"
#define DCN_BASE__INST0_SEG2 0x000034C0
#define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg
#define CTX dmub
#define REGS dmub->regs_dcn32
#define REG_OFFSET_EXP(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
const struct dmub_srv_dcn32_regs dmub_srv_dcn32_regs = {
#define DMUB_SR(reg) REG_OFFSET_EXP(reg),
{ DMUB_DCN32_REGS() },
#undef DMUB_SR
#define DMUB_SF(reg, field) FD_MASK(reg, field),
{ DMUB_DCN32_FIELDS() },
#undef DMUB_SF
#define DMUB_SF(reg, field) FD_SHIFT(reg, field),
{ DMUB_DCN32_FIELDS() },
#undef DMUB_SF
};
static void dmub_dcn32_get_fb_base_offset(struct dmub_srv *dmub,
uint64_t *fb_base,
uint64_t *fb_offset)
{
uint32_t tmp;
if (dmub->fb_base || dmub->fb_offset) {
*fb_base = dmub->fb_base;
*fb_offset = dmub->fb_offset;
return;
}
REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
*fb_base = (uint64_t)tmp << 24;
REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
*fb_offset = (uint64_t)tmp << 24;
}
static inline void dmub_dcn32_translate_addr(const union dmub_addr *addr_in,
uint64_t fb_base,
uint64_t fb_offset,
union dmub_addr *addr_out)
{
addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
}
void dmub_dcn32_reset(struct dmub_srv *dmub)
{
union dmub_gpint_data_register cmd;
const uint32_t timeout = 30;
uint32_t in_reset, scratch, i;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
if (in_reset == 0) {
cmd.bits.status = 1;
cmd.bits.command_code = DMUB_GPINT__STOP_FW;
cmd.bits.param = 0;
dmub->hw_funcs.set_gpint(dmub, cmd);
/**
* Timeout covers both the ACK and the wait
* for remaining work to finish.
*
* This is mostly bound by the PHY disable sequence.
* Each register check will be greater than 1us, so
* don't bother using udelay.
*/
for (i = 0; i < timeout; ++i) {
if (dmub->hw_funcs.is_gpint_acked(dmub, cmd))
break;
}
for (i = 0; i < timeout; ++i) {
scratch = dmub->hw_funcs.get_gpint_response(dmub);
if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
break;
}
/* Clear the GPINT command manually so we don't reset again. */
cmd.all = 0;
dmub->hw_funcs.set_gpint(dmub, cmd);
/* Force reset in case we timed out, DMCUB is likely hung. */
}
REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1);
REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
REG_WRITE(DMCUB_INBOX1_RPTR, 0);
REG_WRITE(DMCUB_INBOX1_WPTR, 0);
REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
REG_WRITE(DMCUB_OUTBOX1_WPTR, 0);
REG_WRITE(DMCUB_SCRATCH0, 0);
}
void dmub_dcn32_reset_release(struct dmub_srv *dmub)
{
REG_WRITE(DMCUB_GPINT_DATAIN1, 0);
REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0);
REG_WRITE(DMCUB_SCRATCH15, dmub->psp_version & 0x001100FF);
REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1);
REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 0);
}
void dmub_dcn32_backdoor_load(struct dmub_srv *dmub,
const struct dmub_window *cw0,
const struct dmub_window *cw1)
{
union dmub_addr offset;
uint64_t fb_base, fb_offset;
dmub_dcn32_get_fb_base_offset(dmub, &fb_base, &fb_offset);
REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
dmub_dcn32_translate_addr(&cw0->offset, fb_base, fb_offset, &offset);
REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
DMCUB_REGION3_CW0_ENABLE, 1);
dmub_dcn32_translate_addr(&cw1->offset, fb_base, fb_offset, &offset);
REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
DMCUB_REGION3_CW1_ENABLE, 1);
REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
0x20);
}
void dmub_dcn32_backdoor_load_zfb_mode(struct dmub_srv *dmub,
const struct dmub_window *cw0,
const struct dmub_window *cw1)
{
union dmub_addr offset;
REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
offset = cw0->offset;
REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
DMCUB_REGION3_CW0_ENABLE, 1);
offset = cw1->offset;
REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
DMCUB_REGION3_CW1_ENABLE, 1);
REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
0x20);
}
void dmub_dcn32_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw2,
const struct dmub_window *cw3,
const struct dmub_window *cw4,
const struct dmub_window *cw5,
const struct dmub_window *cw6)
{
union dmub_addr offset;
offset = cw3->offset;
REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base);
REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0,
DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top,
DMCUB_REGION3_CW3_ENABLE, 1);
offset = cw4->offset;
REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
DMCUB_REGION3_CW4_ENABLE, 1);
offset = cw5->offset;
REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base);
REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0,
DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
DMCUB_REGION3_CW5_ENABLE, 1);
REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
DMCUB_REGION5_TOP_ADDRESS,
cw5->region.top - cw5->region.base - 1,
DMCUB_REGION5_ENABLE, 1);
offset = cw6->offset;
REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part);
REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base);
REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0,
DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top,
DMCUB_REGION3_CW6_ENABLE, 1);
}
void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
const struct dmub_region *inbox1)
{
REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base);
REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
}
uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_INBOX1_RPTR);
}
void dmub_dcn32_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset)
{
REG_WRITE(DMCUB_INBOX1_WPTR, wptr_offset);
}
void dmub_dcn32_setup_out_mailbox(struct dmub_srv *dmub,
const struct dmub_region *outbox1)
{
REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, outbox1->base);
REG_WRITE(DMCUB_OUTBOX1_SIZE, outbox1->top - outbox1->base);
}
uint32_t dmub_dcn32_get_outbox1_wptr(struct dmub_srv *dmub)
{
/**
* outbox1 wptr register is accessed without locks (dal & dc)
* and to be called only by dmub_srv_stat_get_notification()
*/
return REG_READ(DMCUB_OUTBOX1_WPTR);
}
void dmub_dcn32_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
{
/**
* outbox1 rptr register is accessed without locks (dal & dc)
* and to be called only by dmub_srv_stat_get_notification()
*/
REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset);
}
bool dmub_dcn32_is_hw_init(struct dmub_srv *dmub)
{
uint32_t is_hw_init;
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init);
return is_hw_init != 0;
}
bool dmub_dcn32_is_supported(struct dmub_srv *dmub)
{
uint32_t supported = 0;
REG_GET(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE, &supported);
return supported;
}
void dmub_dcn32_set_gpint(struct dmub_srv *dmub,
union dmub_gpint_data_register reg)
{
REG_WRITE(DMCUB_GPINT_DATAIN1, reg.all);
}
bool dmub_dcn32_is_gpint_acked(struct dmub_srv *dmub,
union dmub_gpint_data_register reg)
{
union dmub_gpint_data_register test;
reg.bits.status = 0;
test.all = REG_READ(DMCUB_GPINT_DATAIN1);
return test.all == reg.all;
}
uint32_t dmub_dcn32_get_gpint_response(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_SCRATCH7);
}
uint32_t dmub_dcn32_get_gpint_dataout(struct dmub_srv *dmub)
{
uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT);
REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0);
REG_WRITE(DMCUB_GPINT_DATAOUT, 0);
REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1);
REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0);
REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1);
return dataout;
}
union dmub_fw_boot_status dmub_dcn32_get_fw_boot_status(struct dmub_srv *dmub)
{
union dmub_fw_boot_status status;
status.all = REG_READ(DMCUB_SCRATCH0);
return status;
}
void dmub_dcn32_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
{
union dmub_fw_boot_options boot_options = {0};
boot_options.bits.z10_disable = params->disable_z10;
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
}
void dmub_dcn32_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip)
{
union dmub_fw_boot_options boot_options;
boot_options.all = REG_READ(DMCUB_SCRATCH14);
boot_options.bits.skip_phy_init_panel_sequence = skip;
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
}
void dmub_dcn32_setup_outbox0(struct dmub_srv *dmub,
const struct dmub_region *outbox0)
{
REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base);
REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base);
}
uint32_t dmub_dcn32_get_outbox0_wptr(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_OUTBOX0_WPTR);
}
void dmub_dcn32_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
{
REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset);
}
uint32_t dmub_dcn32_get_current_time(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_TIMER_CURRENT);
}
void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data)
{
uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
if (!dmub || !diag_data)
return;
memset(diag_data, 0, sizeof(*diag_data));
diag_data->dmcub_version = dmub->fw_version;
diag_data->scratch[0] = REG_READ(DMCUB_SCRATCH0);
diag_data->scratch[1] = REG_READ(DMCUB_SCRATCH1);
diag_data->scratch[2] = REG_READ(DMCUB_SCRATCH2);
diag_data->scratch[3] = REG_READ(DMCUB_SCRATCH3);
diag_data->scratch[4] = REG_READ(DMCUB_SCRATCH4);
diag_data->scratch[5] = REG_READ(DMCUB_SCRATCH5);
diag_data->scratch[6] = REG_READ(DMCUB_SCRATCH6);
diag_data->scratch[7] = REG_READ(DMCUB_SCRATCH7);
diag_data->scratch[8] = REG_READ(DMCUB_SCRATCH8);
diag_data->scratch[9] = REG_READ(DMCUB_SCRATCH9);
diag_data->scratch[10] = REG_READ(DMCUB_SCRATCH10);
diag_data->scratch[11] = REG_READ(DMCUB_SCRATCH11);
diag_data->scratch[12] = REG_READ(DMCUB_SCRATCH12);
diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13);
diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14);
diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15);
diag_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
diag_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
diag_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);
diag_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
diag_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
diag_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);
diag_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
diag_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
diag_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
diag_data->is_dmcub_enabled = is_dmub_enabled;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
diag_data->is_dmcub_soft_reset = is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
diag_data->is_dmcub_secure_reset = is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
diag_data->is_traceport_en = is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
diag_data->is_cw0_enabled = is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
diag_data->is_cw6_enabled = is_cw6_enabled;
}
void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub)
{
/* DMCUB_REGION3_TMR_AXI_SPACE values:
* 0b011 (0x3) - FB physical address
* 0b100 (0x4) - GPU virtual address
*
* Default value is 0x3 (FB Physical address for TMR). When programming
* DMUB to be in system memory, change to 0x4. The system memory allocated
* is accessible by both GPU and CPU, so we use GPU virtual address.
*/
REG_WRITE(DMCUB_REGION3_TMR_AXI_SPACE, 0x4);
}
void dmub_dcn32_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data)
{
REG_WRITE(DMCUB_INBOX0_WPTR, data.inbox0_cmd_common.all);
}
void dmub_dcn32_clear_inbox0_ack_register(struct dmub_srv *dmub)
{
REG_WRITE(DMCUB_SCRATCH17, 0);
}
uint32_t dmub_dcn32_read_inbox0_ack_register(struct dmub_srv *dmub)
{
return REG_READ(DMCUB_SCRATCH17);
}
/*
* Copyright 2022 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 _DMUB_DCN32_H_
#define _DMUB_DCN32_H_
#include "dmub_dcn31.h"
struct dmub_srv;
/* DCN32 register definitions. */
#define DMUB_DCN32_REGS() \
DMUB_SR(DMCUB_CNTL) \
DMUB_SR(DMCUB_CNTL2) \
DMUB_SR(DMCUB_SEC_CNTL) \
DMUB_SR(DMCUB_INBOX0_SIZE) \
DMUB_SR(DMCUB_INBOX0_RPTR) \
DMUB_SR(DMCUB_INBOX0_WPTR) \
DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \
DMUB_SR(DMCUB_INBOX1_SIZE) \
DMUB_SR(DMCUB_INBOX1_RPTR) \
DMUB_SR(DMCUB_INBOX1_WPTR) \
DMUB_SR(DMCUB_OUTBOX0_BASE_ADDRESS) \
DMUB_SR(DMCUB_OUTBOX0_SIZE) \
DMUB_SR(DMCUB_OUTBOX0_RPTR) \
DMUB_SR(DMCUB_OUTBOX0_WPTR) \
DMUB_SR(DMCUB_OUTBOX1_BASE_ADDRESS) \
DMUB_SR(DMCUB_OUTBOX1_SIZE) \
DMUB_SR(DMCUB_OUTBOX1_RPTR) \
DMUB_SR(DMCUB_OUTBOX1_WPTR) \
DMUB_SR(DMCUB_REGION3_CW0_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW1_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW2_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW3_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW4_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW5_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW6_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW7_OFFSET) \
DMUB_SR(DMCUB_REGION3_CW0_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW1_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW2_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW3_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW4_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW5_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW6_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW7_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION3_CW0_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW1_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW2_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW3_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW4_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW5_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW6_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW7_BASE_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW0_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW1_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW2_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW3_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW4_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW5_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW6_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION3_CW7_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION4_OFFSET) \
DMUB_SR(DMCUB_REGION4_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION4_TOP_ADDRESS) \
DMUB_SR(DMCUB_REGION5_OFFSET) \
DMUB_SR(DMCUB_REGION5_OFFSET_HIGH) \
DMUB_SR(DMCUB_REGION5_TOP_ADDRESS) \
DMUB_SR(DMCUB_SCRATCH0) \
DMUB_SR(DMCUB_SCRATCH1) \
DMUB_SR(DMCUB_SCRATCH2) \
DMUB_SR(DMCUB_SCRATCH3) \
DMUB_SR(DMCUB_SCRATCH4) \
DMUB_SR(DMCUB_SCRATCH5) \
DMUB_SR(DMCUB_SCRATCH6) \
DMUB_SR(DMCUB_SCRATCH7) \
DMUB_SR(DMCUB_SCRATCH8) \
DMUB_SR(DMCUB_SCRATCH9) \
DMUB_SR(DMCUB_SCRATCH10) \
DMUB_SR(DMCUB_SCRATCH11) \
DMUB_SR(DMCUB_SCRATCH12) \
DMUB_SR(DMCUB_SCRATCH13) \
DMUB_SR(DMCUB_SCRATCH14) \
DMUB_SR(DMCUB_SCRATCH15) \
DMUB_SR(DMCUB_SCRATCH16) \
DMUB_SR(DMCUB_SCRATCH17) \
DMUB_SR(DMCUB_GPINT_DATAIN1) \
DMUB_SR(DMCUB_GPINT_DATAOUT) \
DMUB_SR(CC_DC_PIPE_DIS) \
DMUB_SR(MMHUBBUB_SOFT_RESET) \
DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
DMUB_SR(DCN_VM_FB_OFFSET) \
DMUB_SR(DMCUB_TIMER_CURRENT) \
DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \
DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \
DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) \
DMUB_SR(DMCUB_REGION3_TMR_AXI_SPACE) \
DMUB_SR(DMCUB_INTERRUPT_ENABLE) \
DMUB_SR(DMCUB_INTERRUPT_ACK)
#define DMUB_DCN32_FIELDS() \
DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
DMUB_SF(DMCUB_CNTL, DMCUB_TRACEPORT_EN) \
DMUB_SF(DMCUB_CNTL2, DMCUB_SOFT_RESET) \
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \
DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \
DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \
DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_ENABLE) \
DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_ENABLE) \
DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_ENABLE) \
DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_ENABLE) \
DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_ENABLE) \
DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE) \
DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_ENABLE) \
DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_ENABLE) \
DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_TOP_ADDRESS) \
DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_ENABLE) \
DMUB_SF(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE) \
DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \
DMUB_SF(DMCUB_REGION3_TMR_AXI_SPACE, DMCUB_REGION3_TMR_AXI_SPACE) \
DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \
DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK)
struct dmub_srv_dcn32_reg_offset {
#define DMUB_SR(reg) uint32_t reg;
DMUB_DCN32_REGS()
DMCUB_INTERNAL_REGS()
#undef DMUB_SR
};
struct dmub_srv_dcn32_reg_shift {
#define DMUB_SF(reg, field) uint8_t reg##__##field;
DMUB_DCN32_FIELDS()
#undef DMUB_SF
};
struct dmub_srv_dcn32_reg_mask {
#define DMUB_SF(reg, field) uint32_t reg##__##field;
DMUB_DCN32_FIELDS()
#undef DMUB_SF
};
struct dmub_srv_dcn32_regs {
const struct dmub_srv_dcn32_reg_offset offset;
const struct dmub_srv_dcn32_reg_mask mask;
const struct dmub_srv_dcn32_reg_shift shift;
};
extern const struct dmub_srv_dcn32_regs dmub_srv_dcn32_regs;
void dmub_dcn32_reset(struct dmub_srv *dmub);
void dmub_dcn32_reset_release(struct dmub_srv *dmub);
void dmub_dcn32_backdoor_load(struct dmub_srv *dmub,
const struct dmub_window *cw0,
const struct dmub_window *cw1);
void dmub_dcn32_backdoor_load_zfb_mode(struct dmub_srv *dmub,
const struct dmub_window *cw0,
const struct dmub_window *cw1);
void dmub_dcn32_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw2,
const struct dmub_window *cw3,
const struct dmub_window *cw4,
const struct dmub_window *cw5,
const struct dmub_window *cw6);
void dmub_dcn32_setup_mailbox(struct dmub_srv *dmub,
const struct dmub_region *inbox1);
uint32_t dmub_dcn32_get_inbox1_rptr(struct dmub_srv *dmub);
void dmub_dcn32_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
void dmub_dcn32_setup_out_mailbox(struct dmub_srv *dmub,
const struct dmub_region *outbox1);
uint32_t dmub_dcn32_get_outbox1_wptr(struct dmub_srv *dmub);
void dmub_dcn32_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
bool dmub_dcn32_is_hw_init(struct dmub_srv *dmub);
bool dmub_dcn32_is_supported(struct dmub_srv *dmub);
void dmub_dcn32_set_gpint(struct dmub_srv *dmub,
union dmub_gpint_data_register reg);
bool dmub_dcn32_is_gpint_acked(struct dmub_srv *dmub,
union dmub_gpint_data_register reg);
uint32_t dmub_dcn32_get_gpint_response(struct dmub_srv *dmub);
uint32_t dmub_dcn32_get_gpint_dataout(struct dmub_srv *dmub);
void dmub_dcn32_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params);
void dmub_dcn32_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip);
union dmub_fw_boot_status dmub_dcn32_get_fw_boot_status(struct dmub_srv *dmub);
void dmub_dcn32_setup_outbox0(struct dmub_srv *dmub,
const struct dmub_region *outbox0);
uint32_t dmub_dcn32_get_outbox0_wptr(struct dmub_srv *dmub);
void dmub_dcn32_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
uint32_t dmub_dcn32_get_current_time(struct dmub_srv *dmub);
void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data);
void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub);
void dmub_dcn32_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
void dmub_dcn32_clear_inbox0_ack_register(struct dmub_srv *dmub);
uint32_t dmub_dcn32_read_inbox0_ack_register(struct dmub_srv *dmub);
#endif /* _DMUB_DCN32_H_ */
......@@ -34,6 +34,7 @@
#include "dmub_dcn31.h"
#include "dmub_dcn315.h"
#include "dmub_dcn316.h"
#include "dmub_dcn32.h"
#include "os_types.h"
/*
* Note: the DMUB service is standalone. No additional headers should be
......@@ -260,6 +261,43 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
break;
case DMUB_ASIC_DCN32:
case DMUB_ASIC_DCN321:
dmub->regs_dcn32 = &dmub_srv_dcn32_regs;
funcs->configure_dmub_in_system_memory = dmub_dcn32_configure_dmub_in_system_memory;
funcs->send_inbox0_cmd = dmub_dcn32_send_inbox0_cmd;
funcs->clear_inbox0_ack_register = dmub_dcn32_clear_inbox0_ack_register;
funcs->read_inbox0_ack_register = dmub_dcn32_read_inbox0_ack_register;
funcs->reset = dmub_dcn32_reset;
funcs->reset_release = dmub_dcn32_reset_release;
funcs->backdoor_load = dmub_dcn32_backdoor_load;
funcs->backdoor_load_zfb_mode = dmub_dcn32_backdoor_load_zfb_mode;
funcs->setup_windows = dmub_dcn32_setup_windows;
funcs->setup_mailbox = dmub_dcn32_setup_mailbox;
funcs->get_inbox1_rptr = dmub_dcn32_get_inbox1_rptr;
funcs->set_inbox1_wptr = dmub_dcn32_set_inbox1_wptr;
funcs->setup_out_mailbox = dmub_dcn32_setup_out_mailbox;
funcs->get_outbox1_wptr = dmub_dcn32_get_outbox1_wptr;
funcs->set_outbox1_rptr = dmub_dcn32_set_outbox1_rptr;
funcs->is_supported = dmub_dcn32_is_supported;
funcs->is_hw_init = dmub_dcn32_is_hw_init;
funcs->set_gpint = dmub_dcn32_set_gpint;
funcs->is_gpint_acked = dmub_dcn32_is_gpint_acked;
funcs->get_gpint_response = dmub_dcn32_get_gpint_response;
funcs->get_gpint_dataout = dmub_dcn32_get_gpint_dataout;
funcs->get_fw_status = dmub_dcn32_get_fw_boot_status;
funcs->enable_dmub_boot_options = dmub_dcn32_enable_dmub_boot_options;
funcs->skip_dmub_panel_power_sequence = dmub_dcn32_skip_dmub_panel_power_sequence;
/* outbox0 call stacks */
funcs->setup_outbox0 = dmub_dcn32_setup_outbox0;
funcs->get_outbox0_wptr = dmub_dcn32_get_outbox0_wptr;
funcs->set_outbox0_rptr = dmub_dcn32_set_outbox0_rptr;
funcs->get_current_time = dmub_dcn32_get_current_time;
funcs->get_diagnostic_data = dmub_dcn32_get_diagnostic_data;
break;
default:
return false;
}
......@@ -501,6 +539,9 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
cw1.region.base = DMUB_CW1_BASE;
cw1.region.top = cw1.region.base + stack_fb->size - 1;
if (params->fw_in_system_memory && dmub->hw_funcs.configure_dmub_in_system_memory)
dmub->hw_funcs.configure_dmub_in_system_memory(dmub);
if (params->load_inst_const && dmub->hw_funcs.backdoor_load) {
/**
* Read back all the instruction memory so we don't hang the
......@@ -508,7 +549,11 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
* flushed yet. This only occurs in backdoor loading.
*/
dmub_flush_buffer_mem(inst_fb);
dmub->hw_funcs.backdoor_load(dmub, &cw0, &cw1);
if (params->fw_in_system_memory && dmub->hw_funcs.backdoor_load_zfb_mode)
dmub->hw_funcs.backdoor_load_zfb_mode(dmub, &cw0, &cw1);
else
dmub->hw_funcs.backdoor_load(dmub, &cw0, &cw1);
}
cw2.offset.quad_part = data_fb->gpu_addr;
......@@ -583,6 +628,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
if (dmub->hw_funcs.enable_dmub_boot_options)
dmub->hw_funcs.enable_dmub_boot_options(dmub, params);
if (dmub->hw_funcs.skip_dmub_panel_power_sequence)
dmub->hw_funcs.skip_dmub_panel_power_sequence(dmub,
params->skip_panel_power_sequence);
if (dmub->hw_funcs.reset_release)
dmub->hw_funcs.reset_release(dmub);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment