Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,37 @@
#
# Copyright 2017 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.
#
#
# Makefile for common 'dce' logic
# HW object file under this folder follow similar pattern for HW programming
# - register offset and/or shift + mask stored in the dec_hw struct
# - register programming through common macros that look up register
# offset/shift/mask stored in dce_hw struct
DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o \
dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \
dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \
dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o dmub_psr.o dmub_abm.o dmub_abm_lcd.o dce_panel_cntl.o \
dmub_hw_lock_mgr.o dmub_outbox.o dmub_replay.o
AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE))
AMD_DISPLAY_FILES += $(AMD_DAL_DCE)
@@ -0,0 +1,307 @@
/*
* Copyright 2012-16 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 <linux/slab.h>
#include "dce_abm.h"
#include "dm_services.h"
#include "reg_helper.h"
#include "fixed31_32.h"
#include "dc.h"
#include "atom.h"
#define TO_DCE_ABM(abm)\
container_of(abm, struct dce_abm, base)
#define REG(reg) \
(abm_dce->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
abm_dce->abm_shift->field_name, abm_dce->abm_mask->field_name
#define DC_LOGGER \
abm->ctx->logger
#define CTX \
abm_dce->base.ctx
#define MCP_ABM_LEVEL_SET 0x65
#define MCP_ABM_PIPE_SET 0x66
#define MCP_BL_SET 0x67
#define MCP_DISABLE_ABM_IMMEDIATELY 255
static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id, uint32_t panel_inst)
{
(void)panel_inst;
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
uint32_t rampingBoundary = 0xFFFF;
if (abm->dmcu_is_running == false)
return true;
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
1, 80000);
/* set ramping boundary */
REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary);
/* setDMCUParam_Pipe */
REG_UPDATE_2(MASTER_COMM_CMD_REG,
MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET,
MASTER_COMM_CMD_REG_BYTE1, controller_id);
/* notifyDMCUMsg */
REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
1, 80000);
return true;
}
static void dmcu_set_backlight_level(
struct dce_abm *abm_dce,
uint32_t backlight_pwm_u16_16,
uint32_t frame_ramp,
uint32_t controller_id,
uint32_t panel_id)
{
unsigned int backlight_8_bit = 0;
uint32_t s2;
if (backlight_pwm_u16_16 & 0x10000)
// Check for max backlight condition
backlight_8_bit = 0xFF;
else
// Take MSB of fractional part since backlight is not max
backlight_8_bit = (backlight_pwm_u16_16 >> 8) & 0xFF;
dce_abm_set_pipe(&abm_dce->base, controller_id, panel_id);
/* waitDMCUReadyForCmd */
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
0, 1, 80000);
/* setDMCUParam_BL */
REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_pwm_u16_16);
/* write ramp */
if (controller_id == 0)
frame_ramp = 0;
REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp);
/* setDMCUParam_Cmd */
REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET);
/* notifyDMCUMsg */
REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
/* UpdateRequestedBacklightLevel */
s2 = REG_READ(BIOS_SCRATCH_2);
s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
backlight_8_bit &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >>
ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
s2 |= (backlight_8_bit << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
REG_WRITE(BIOS_SCRATCH_2, s2);
/* waitDMCUReadyForCmd */
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
0, 1, 80000);
}
static void dce_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level)
{
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x103);
REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x101);
REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x103);
REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x101);
REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x101);
REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0,
ABM1_HG_NUM_OF_BINS_SEL, 0,
ABM1_HG_VMAX_SEL, 1,
ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0);
REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0,
ABM1_IPCSC_COEFF_SEL_R, 2,
ABM1_IPCSC_COEFF_SEL_G, 4,
ABM1_IPCSC_COEFF_SEL_B, 2);
REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL,
BL1_PWM_CURRENT_ABM_LEVEL, backlight);
REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL,
BL1_PWM_TARGET_ABM_LEVEL, backlight);
REG_UPDATE(BL1_PWM_USER_LEVEL,
BL1_PWM_USER_LEVEL, user_level);
REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000);
REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0,
ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1,
ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1,
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1);
}
static unsigned int dce_abm_get_current_backlight(struct abm *abm)
{
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
/* return backlight in hardware format which is unsigned 17 bits, with
* 1 bit integer and 16 bit fractional
*/
return backlight;
}
static unsigned int dce_abm_get_target_backlight(struct abm *abm)
{
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL);
/* return backlight in hardware format which is unsigned 17 bits, with
* 1 bit integer and 16 bit fractional
*/
return backlight;
}
static bool dce_abm_set_level(struct abm *abm, uint32_t level)
{
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
if (abm->dmcu_is_running == false)
return true;
REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
1, 80000);
/* setDMCUParam_ABMLevel */
REG_UPDATE_2(MASTER_COMM_CMD_REG,
MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET,
MASTER_COMM_CMD_REG_BYTE2, level);
/* notifyDMCUMsg */
REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
return true;
}
static bool dce_abm_immediate_disable(struct abm *abm, uint32_t panel_inst)
{
if (abm->dmcu_is_running == false)
return true;
dce_abm_set_pipe(abm, MCP_DISABLE_ABM_IMMEDIATELY, panel_inst);
return true;
}
static bool dce_abm_set_backlight_level_pwm(
struct abm *abm,
unsigned int backlight_pwm_u16_16,
unsigned int frame_ramp,
unsigned int controller_id,
unsigned int panel_inst)
{
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
backlight_pwm_u16_16, backlight_pwm_u16_16);
dmcu_set_backlight_level(abm_dce,
backlight_pwm_u16_16,
frame_ramp,
controller_id,
panel_inst);
return true;
}
static const struct abm_funcs dce_funcs = {
.abm_init = dce_abm_init,
.set_abm_level = dce_abm_set_level,
.set_pipe = dce_abm_set_pipe,
.set_backlight_level_pwm = dce_abm_set_backlight_level_pwm,
.get_current_backlight = dce_abm_get_current_backlight,
.get_target_backlight = dce_abm_get_target_backlight,
.init_abm_config = NULL,
.set_abm_immediate_disable = dce_abm_immediate_disable,
};
static void dce_abm_construct(
struct dce_abm *abm_dce,
struct dc_context *ctx,
const struct dce_abm_registers *regs,
const struct dce_abm_shift *abm_shift,
const struct dce_abm_mask *abm_mask)
{
struct abm *base = &abm_dce->base;
base->ctx = ctx;
base->funcs = &dce_funcs;
base->dmcu_is_running = false;
abm_dce->regs = regs;
abm_dce->abm_shift = abm_shift;
abm_dce->abm_mask = abm_mask;
}
struct abm *dce_abm_create(
struct dc_context *ctx,
const struct dce_abm_registers *regs,
const struct dce_abm_shift *abm_shift,
const struct dce_abm_mask *abm_mask)
{
struct dce_abm *abm_dce = kzalloc_obj(*abm_dce);
if (abm_dce == NULL) {
BREAK_TO_DEBUGGER();
return NULL;
}
dce_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask);
abm_dce->base.funcs = &dce_funcs;
return &abm_dce->base;
}
void dce_abm_destroy(struct abm **abm)
{
struct dce_abm *abm_dce = TO_DCE_ABM(*abm);
kfree(abm_dce);
*abm = NULL;
}
@@ -0,0 +1,450 @@
/*
* Copyright 2012-2026 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_ABM_H_
#define _DCE_ABM_H_
#include "abm.h"
#define ABM_COMMON_REG_LIST_DCE_BASE() \
SR(MASTER_COMM_CNTL_REG), \
SR(MASTER_COMM_CMD_REG), \
SR(MASTER_COMM_DATA_REG1)
#define ABM_DCE110_COMMON_REG_LIST() \
ABM_COMMON_REG_LIST_DCE_BASE(), \
SR(DC_ABM1_HG_SAMPLE_RATE), \
SR(DC_ABM1_LS_SAMPLE_RATE), \
SR(BL1_PWM_BL_UPDATE_SAMPLE_RATE), \
SR(DC_ABM1_HG_MISC_CTRL), \
SR(DC_ABM1_IPCSC_COEFF_SEL), \
SR(BL1_PWM_CURRENT_ABM_LEVEL), \
SR(BL1_PWM_TARGET_ABM_LEVEL), \
SR(BL1_PWM_USER_LEVEL), \
SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \
SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \
SR(DC_ABM1_ACE_OFFSET_SLOPE_0), \
SR(DC_ABM1_ACE_THRES_12), \
SR(BIOS_SCRATCH_2)
#define ABM_DCN10_REG_LIST(id)\
ABM_COMMON_REG_LIST_DCE_BASE(), \
SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \
SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_USER_LEVEL, ABM, id), \
SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \
SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
NBIO_SR(BIOS_SCRATCH_2)
#define ABM_DCN20_REG_LIST() \
ABM_COMMON_REG_LIST_DCE_BASE(), \
SR(DC_ABM1_HG_SAMPLE_RATE), \
SR(DC_ABM1_LS_SAMPLE_RATE), \
SR(BL1_PWM_BL_UPDATE_SAMPLE_RATE), \
SR(DC_ABM1_HG_MISC_CTRL), \
SR(DC_ABM1_IPCSC_COEFF_SEL), \
SR(BL1_PWM_CURRENT_ABM_LEVEL), \
SR(BL1_PWM_TARGET_ABM_LEVEL), \
SR(BL1_PWM_USER_LEVEL), \
SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \
SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \
SR(DC_ABM1_ACE_OFFSET_SLOPE_0), \
SR(DC_ABM1_ACE_THRES_12), \
NBIO_SR(BIOS_SCRATCH_2)
#define ABM_DCN301_REG_LIST(id)\
ABM_COMMON_REG_LIST_DCE_BASE(), \
SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \
SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_USER_LEVEL, ABM, id), \
SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
NBIO_SR(BIOS_SCRATCH_2)
#define ABM_DCN302_REG_LIST(id)\
ABM_COMMON_REG_LIST_DCE_BASE(), \
SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \
SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_USER_LEVEL, ABM, id), \
SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \
SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
NBIO_SR(BIOS_SCRATCH_2)
#define ABM_DCN30_REG_LIST(id)\
ABM_COMMON_REG_LIST_DCE_BASE(), \
SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \
SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
SRI(BL1_PWM_USER_LEVEL, ABM, id), \
SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \
SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
NBIO_SR(BIOS_SCRATCH_2)
#define ABM_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \
ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE1, mask_sh), \
ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh)
#define ABM_MASK_SH_LIST_DCE110(mask_sh) \
ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
ABM_SF(DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
ABM_SF(DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_VMAX_SEL, mask_sh), \
ABM_SF(DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \
ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_R, mask_sh), \
ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_G, mask_sh), \
ABM_SF(DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_B, mask_sh), \
ABM_SF(BL1_PWM_CURRENT_ABM_LEVEL, \
BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \
ABM_SF(BL1_PWM_TARGET_ABM_LEVEL, \
BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \
ABM_SF(BL1_PWM_USER_LEVEL, \
BL1_PWM_USER_LEVEL, mask_sh), \
ABM_SF(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh)
#define ABM_MASK_SH_LIST_DCN10_COMMON(mask_sh) \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_VMAX_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_R, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_G, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_B, mask_sh), \
ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \
BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \
BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \
BL1_PWM_USER_LEVEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh)
#define ABM_MASK_SH_LIST_DCN10(mask_sh) \
ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
ABM_MASK_SH_LIST_DCN10_COMMON(mask_sh)
#define ABM_MASK_SH_LIST_DCN20(mask_sh) ABM_MASK_SH_LIST_DCE110(mask_sh)
#define ABM_MASK_SH_LIST_DCN30(mask_sh) ABM_MASK_SH_LIST_DCN10(mask_sh)
#define ABM_MASK_SH_LIST_DCN35(mask_sh) ABM_MASK_SH_LIST_DCN10_COMMON(mask_sh)
#define ABM_MASK_SH_LIST_DCN32(mask_sh) \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_VMAX_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_R, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_G, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_B, mask_sh), \
ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \
BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \
BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \
BL1_PWM_USER_LEVEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh)
#define ABM_MASK_SH_LIST_DCN401(mask_sh) \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_VMAX_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_R, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_G, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_B, mask_sh), \
ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \
BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \
BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \
BL1_PWM_USER_LEVEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \
ABM1_ACE_SLOPE_DATA, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \
ABM1_ACE_OFFSET_DATA, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_OFFSET_SLOPE_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_THRES_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_IGNORE_MASTER_LOCK_EN, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_READBACK_DB_REG_VALUE_EN, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_DBUF_REG_UPDATE_PENDING, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_LOCK, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_THRES_DATA, \
ABM1_ACE_THRES_DATA_1, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_THRES_DATA, \
ABM1_ACE_THRES_DATA_2, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_RESULT_DATA, \
ABM1_HG_RESULT_DATA, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_RESULT_INDEX, \
ABM1_HG_RESULT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, \
ABM1_HG_BIN_33_40_SHIFT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, \
ABM1_HG_BIN_33_64_SHIFT_FLAG, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, \
ABM1_HG_BIN_41_48_SHIFT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, \
ABM1_HG_BIN_49_56_SHIFT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \
ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh)
#define ABM_MASK_SH_LIST_DCN42(mask_sh) \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_VMAX_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_R, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_G, mask_sh), \
ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
ABM1_IPCSC_COEFF_SEL_B, mask_sh), \
ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \
BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \
BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \
ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \
BL1_PWM_USER_LEVEL, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \
ABM1_ACE_SLOPE_DATA, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \
ABM1_ACE_OFFSET_DATA, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_OFFSET_SLOPE_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_IGNORE_MASTER_LOCK_EN, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_READBACK_DB_REG_VALUE_EN, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_DBUF_REG_UPDATE_PENDING, mask_sh), \
ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
ABM1_ACE_LOCK, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_RESULT_DATA, \
ABM1_HG_RESULT_DATA, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_RESULT_INDEX, \
ABM1_HG_RESULT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, \
ABM1_HG_BIN_33_40_SHIFT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, \
ABM1_HG_BIN_33_64_SHIFT_FLAG, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, \
ABM1_HG_BIN_41_48_SHIFT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, \
ABM1_HG_BIN_49_56_SHIFT_INDEX, mask_sh), \
ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \
ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh)
#define ABM_REG_FIELD_LIST(type) \
type ABM1_HG_NUM_OF_BINS_SEL; \
type ABM1_HG_VMAX_SEL; \
type ABM1_HG_BIN_BITWIDTH_SIZE_SEL; \
type ABM1_IPCSC_COEFF_SEL_R; \
type ABM1_IPCSC_COEFF_SEL_G; \
type ABM1_IPCSC_COEFF_SEL_B; \
type BL1_PWM_CURRENT_ABM_LEVEL; \
type BL1_PWM_TARGET_ABM_LEVEL; \
type BL1_PWM_USER_LEVEL; \
type ABM1_LS_MIN_PIXEL_VALUE_THRES; \
type ABM1_LS_MAX_PIXEL_VALUE_THRES; \
type ABM1_HG_REG_READ_MISSED_FRAME_CLEAR; \
type ABM1_LS_REG_READ_MISSED_FRAME_CLEAR; \
type ABM1_BL_REG_READ_MISSED_FRAME_CLEAR; \
type MASTER_COMM_INTERRUPT; \
type MASTER_COMM_CMD_REG_BYTE0; \
type MASTER_COMM_CMD_REG_BYTE1; \
type MASTER_COMM_CMD_REG_BYTE2; \
type ABM1_HG_BIN_33_40_SHIFT_INDEX; \
type ABM1_HG_BIN_33_64_SHIFT_FLAG; \
type ABM1_HG_BIN_41_48_SHIFT_INDEX; \
type ABM1_HG_BIN_49_56_SHIFT_INDEX; \
type ABM1_HG_BIN_57_64_SHIFT_INDEX; \
type ABM1_HG_RESULT_DATA; \
type ABM1_HG_RESULT_INDEX; \
type ABM1_ACE_SLOPE_DATA; \
type ABM1_ACE_OFFSET_DATA; \
type ABM1_ACE_OFFSET_SLOPE_INDEX; \
type ABM1_ACE_THRES_INDEX; \
type ABM1_ACE_IGNORE_MASTER_LOCK_EN; \
type ABM1_ACE_READBACK_DB_REG_VALUE_EN; \
type ABM1_ACE_DBUF_REG_UPDATE_PENDING; \
type ABM1_ACE_LOCK; \
type ABM1_ACE_THRES_DATA_1; \
type ABM1_ACE_THRES_DATA_2
struct dce_abm_shift {
ABM_REG_FIELD_LIST(uint8_t);
};
struct dce_abm_mask {
ABM_REG_FIELD_LIST(uint32_t);
};
struct dce_abm_registers {
uint32_t DC_ABM1_HG_SAMPLE_RATE;
uint32_t DC_ABM1_LS_SAMPLE_RATE;
uint32_t BL1_PWM_BL_UPDATE_SAMPLE_RATE;
uint32_t DC_ABM1_HG_MISC_CTRL;
uint32_t DC_ABM1_IPCSC_COEFF_SEL;
uint32_t BL1_PWM_CURRENT_ABM_LEVEL;
uint32_t BL1_PWM_TARGET_ABM_LEVEL;
uint32_t BL1_PWM_USER_LEVEL;
uint32_t DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES;
uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS;
uint32_t DC_ABM1_ACE_OFFSET_SLOPE_0;
uint32_t DC_ABM1_ACE_OFFSET_SLOPE_DATA;
uint32_t DC_ABM1_ACE_PWL_CNTL;
uint32_t DC_ABM1_HG_BIN_33_40_SHIFT_INDEX;
uint32_t DC_ABM1_HG_BIN_33_64_SHIFT_FLAG;
uint32_t DC_ABM1_HG_BIN_41_48_SHIFT_INDEX;
uint32_t DC_ABM1_HG_BIN_49_56_SHIFT_INDEX;
uint32_t DC_ABM1_HG_BIN_57_64_SHIFT_INDEX;
uint32_t DC_ABM1_HG_RESULT_DATA;
uint32_t DC_ABM1_HG_RESULT_INDEX;
uint32_t DC_ABM1_ACE_THRES_DATA;
uint32_t DC_ABM1_ACE_THRES_12;
uint32_t MASTER_COMM_CNTL_REG;
uint32_t MASTER_COMM_CMD_REG;
uint32_t MASTER_COMM_DATA_REG1;
uint32_t BIOS_SCRATCH_2;
};
struct dce_abm {
struct abm base;
const struct dce_abm_registers *regs;
const struct dce_abm_shift *abm_shift;
const struct dce_abm_mask *abm_mask;
};
struct abm *dce_abm_create(
struct dc_context *ctx,
const struct dce_abm_registers *regs,
const struct dce_abm_shift *abm_shift,
const struct dce_abm_mask *abm_mask);
void dce_abm_destroy(struct abm **abm);
#endif /* _DCE_ABM_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,173 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DAL_AUDIO_DCE_110_H__
#define __DAL_AUDIO_DCE_110_H__
#include "audio.h"
#define AUD_COMMON_REG_LIST(id)\
SRI(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id),\
SRI(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id),\
SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS),\
SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES),\
SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES),\
SR(DCCG_AUDIO_DTO_SOURCE),\
SR(DCCG_AUDIO_DTO0_MODULE),\
SR(DCCG_AUDIO_DTO0_PHASE),\
SR(DCCG_AUDIO_DTO1_MODULE),\
SR(DCCG_AUDIO_DTO1_PHASE)
/* set field name */
#define SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)\
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO2_USE_512FBR_DTO, mask_sh),\
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_USE_512FBR_DTO, mask_sh),\
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO1_USE_512FBR_DTO, mask_sh),\
SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\
SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh)
#define AUD_COMMON_MASK_SH_LIST(mask_sh)\
AUD_COMMON_MASK_SH_LIST_BASE(mask_sh),\
SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define AUD_DCE60_MASK_SH_LIST(mask_sh)\
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\
SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh), \
SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh)
#endif
struct dce_audio_registers {
uint32_t AZALIA_F0_CODEC_ENDPOINT_INDEX;
uint32_t AZALIA_F0_CODEC_ENDPOINT_DATA;
uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS;
uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES;
uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES;
uint32_t DCCG_AUDIO_DTO_SOURCE;
uint32_t DCCG_AUDIO_DTO0_MODULE;
uint32_t DCCG_AUDIO_DTO0_PHASE;
uint32_t DCCG_AUDIO_DTO1_MODULE;
uint32_t DCCG_AUDIO_DTO1_PHASE;
uint32_t AUDIO_RATE_CAPABILITIES;
};
struct dce_audio_shift {
uint8_t AZALIA_ENDPOINT_REG_INDEX;
uint8_t AZALIA_ENDPOINT_REG_DATA;
uint8_t AUDIO_RATE_CAPABILITIES;
uint8_t CLKSTOP;
uint8_t EPSS;
uint8_t DCCG_AUDIO_DTO0_SOURCE_SEL;
uint8_t DCCG_AUDIO_DTO_SEL;
uint8_t DCCG_AUDIO_DTO0_MODULE;
uint8_t DCCG_AUDIO_DTO0_PHASE;
uint8_t DCCG_AUDIO_DTO1_MODULE;
uint8_t DCCG_AUDIO_DTO1_PHASE;
uint8_t DCCG_AUDIO_DTO2_USE_512FBR_DTO;
uint32_t DCCG_AUDIO_DTO0_USE_512FBR_DTO;
uint32_t DCCG_AUDIO_DTO1_USE_512FBR_DTO;
uint32_t CLOCK_GATING_DISABLE;
};
struct dce_audio_mask {
uint32_t AZALIA_ENDPOINT_REG_INDEX;
uint32_t AZALIA_ENDPOINT_REG_DATA;
uint32_t AUDIO_RATE_CAPABILITIES;
uint32_t CLKSTOP;
uint32_t EPSS;
uint32_t DCCG_AUDIO_DTO0_SOURCE_SEL;
uint32_t DCCG_AUDIO_DTO_SEL;
uint32_t DCCG_AUDIO_DTO0_MODULE;
uint32_t DCCG_AUDIO_DTO0_PHASE;
uint32_t DCCG_AUDIO_DTO1_MODULE;
uint32_t DCCG_AUDIO_DTO1_PHASE;
uint32_t DCCG_AUDIO_DTO2_USE_512FBR_DTO;
uint32_t DCCG_AUDIO_DTO0_USE_512FBR_DTO;
uint32_t DCCG_AUDIO_DTO1_USE_512FBR_DTO;
uint32_t CLOCK_GATING_DISABLE;
};
struct dce_audio {
struct audio base;
const struct dce_audio_registers *regs;
const struct dce_audio_shift *shifts;
const struct dce_audio_mask *masks;
};
struct audio *dce_audio_create(
struct dc_context *ctx,
unsigned int inst,
const struct dce_audio_registers *reg,
const struct dce_audio_shift *shifts,
const struct dce_audio_mask *masks);
void dce_aud_destroy(struct audio **audio);
void dce_aud_hw_init(struct audio *audio);
void dce_aud_az_enable(struct audio *audio);
void dce_aud_az_disable(struct audio *audio);
void dce_aud_az_disable_hbr_audio(struct audio *audio);
void dce_aud_az_configure(struct audio *audio,
enum signal_type signal,
const struct audio_crtc_info *crtc_info,
const struct audio_info *audio_info,
const struct audio_dp_link_info *dp_link_info);
void dce_aud_wall_dto_setup(struct audio *audio,
enum signal_type signal,
const struct audio_crtc_info *crtc_info,
const struct audio_pll_info *pll_info);
#endif /*__DAL_AUDIO_DCE_110_H__*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,329 @@
/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DAL_AUX_ENGINE_DCE110_H__
#define __DAL_AUX_ENGINE_DCE110_H__
#include "gpio_service_interface.h"
#include "inc/hw/aux_engine.h"
enum aux_return_code_type;
#define AUX_COMMON_REG_LIST0(id)\
SRI(AUX_CONTROL, DP_AUX, id), \
SRI(AUX_ARB_CONTROL, DP_AUX, id), \
SRI(AUX_SW_DATA, DP_AUX, id), \
SRI(AUX_SW_CONTROL, DP_AUX, id), \
SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \
SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id), \
SRI(AUX_SW_STATUS, DP_AUX, id)
#define AUX_COMMON_REG_LIST(id)\
SRI(AUX_CONTROL, DP_AUX, id), \
SRI(AUX_ARB_CONTROL, DP_AUX, id), \
SRI(AUX_SW_DATA, DP_AUX, id), \
SRI(AUX_SW_CONTROL, DP_AUX, id), \
SRI(AUX_INTERRUPT_CONTROL, DP_AUX, id), \
SRI(AUX_SW_STATUS, DP_AUX, id), \
SR(AUXN_IMPCAL), \
SR(AUXP_IMPCAL)
struct dce110_aux_registers {
uint32_t AUX_CONTROL;
uint32_t AUX_ARB_CONTROL;
uint32_t AUX_SW_DATA;
uint32_t AUX_SW_CONTROL;
uint32_t AUX_INTERRUPT_CONTROL;
uint32_t AUX_DPHY_RX_CONTROL1;
uint32_t AUX_SW_STATUS;
uint32_t AUXN_IMPCAL;
uint32_t AUXP_IMPCAL;
uint32_t AUX_RESET_MASK;
};
#define DCE_AUX_REG_FIELD_LIST(type)\
type AUX_EN;\
type AUX_RESET;\
type AUX_RESET_DONE;\
type AUX_REG_RW_CNTL_STATUS;\
type AUX_SW_USE_AUX_REG_REQ;\
type AUX_SW_DONE_USING_AUX_REG;\
type AUX_SW_AUTOINCREMENT_DISABLE;\
type AUX_SW_DATA_RW;\
type AUX_SW_INDEX;\
type AUX_SW_GO;\
type AUX_SW_DATA;\
type AUX_SW_REPLY_BYTE_COUNT;\
type AUX_SW_DONE;\
type AUX_SW_DONE_ACK;\
type AUXN_IMPCAL_ENABLE;\
type AUXP_IMPCAL_ENABLE;\
type AUXN_IMPCAL_OVERRIDE_ENABLE;\
type AUXP_IMPCAL_OVERRIDE_ENABLE;\
type AUX_RX_TIMEOUT_LEN;\
type AUX_RX_TIMEOUT_LEN_MUL;\
type AUXN_CALOUT_ERROR_AK;\
type AUXP_CALOUT_ERROR_AK;\
type AUX_SW_START_DELAY;\
type AUX_SW_WR_BYTES
#define DCE10_AUX_MASK_SH_LIST(mask_sh)\
AUX_SF(AUX_CONTROL, AUX_EN, mask_sh),\
AUX_SF(AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
AUX_SF(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
AUX_SF(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
AUX_SF(AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
AUX_SF(AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
AUX_SF(AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
AUX_SF(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
AUX_SF(AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
AUX_SF(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
#define DCE_AUX_MASK_SH_LIST(mask_sh)\
AUX_SF(AUX_CONTROL, AUX_EN, mask_sh),\
AUX_SF(AUX_CONTROL, AUX_RESET, mask_sh),\
AUX_SF(AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
AUX_SF(AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
AUX_SF(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
AUX_SF(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
AUX_SF(AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
AUX_SF(AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
AUX_SF(AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
AUX_SF(AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
AUX_SF(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
AUX_SF(AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
AUX_SF(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
#define DCE12_AUX_MASK_SH_LIST(mask_sh)\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_EN, mask_sh),\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET, mask_sh),\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
AUX_SF(DP_AUX0_AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
/* DCN10 MASK */
#define DCN10_AUX_MASK_SH_LIST(mask_sh)\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_EN, mask_sh),\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET, mask_sh),\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
AUX_SF(DP_AUX0_AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_ENABLE, mask_sh),\
AUX_SF(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, mask_sh),\
AUX_SF(AUXN_IMPCAL, AUXN_IMPCAL_OVERRIDE_ENABLE, mask_sh)
/* for all other DCN */
#define DCN_AUX_MASK_SH_LIST(mask_sh)\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_EN, mask_sh),\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET, mask_sh),\
AUX_SF(DP_AUX0_AUX_CONTROL, AUX_RESET_DONE, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_REG_RW_CNTL_STATUS, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, mask_sh),\
AUX_SF(DP_AUX0_AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_START_DELAY, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_WR_BYTES, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_DATA, AUX_SW_DATA, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
AUX_SF(DP_AUX0_AUX_SW_STATUS, AUX_SW_DONE, mask_sh),\
AUX_SF(DP_AUX0_AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, mask_sh),\
AUX_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\
AUX_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh)
#define AUX_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
enum { /* This is the timeout as defined in DP 1.2a,
* 2.3.4 "Detailed uPacket TX AUX CH State Description".
*/
AUX_TIMEOUT_PERIOD = 400,
/* Ideally, the SW timeout should be just above 550usec
* which is programmed in HW.
* But the SW timeout of 600usec is not reliable,
* because on some systems, delay_in_microseconds()
* returns faster than it should.
* EPR #379763: by trial-and-error on different systems,
* 700usec is the minimum reliable SW timeout for polling
* the AUX_SW_STATUS.AUX_SW_DONE bit.
* This timeout expires *only* when there is
* AUX Error or AUX Timeout conditions - not during normal operation.
* During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set
* at most within ~240usec. That means,
* increasing this timeout will not affect normal operation,
* and we'll timeout after
* SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 2400usec.
* This timeout is especially important for
* converters, resume from S3, and CTS.
*/
SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 6
};
struct dce_aux {
uint32_t inst;
struct ddc *ddc;
struct dc_context *ctx;
/* following values are expressed in milliseconds */
uint32_t delay;
uint32_t max_defer_write_retry;
bool acquire_reset;
struct dce_aux_funcs *funcs;
};
struct dce110_aux_registers_mask {
DCE_AUX_REG_FIELD_LIST(uint32_t);
};
struct dce110_aux_registers_shift {
DCE_AUX_REG_FIELD_LIST(uint8_t);
};
struct aux_engine_dce110 {
struct dce_aux base;
const struct dce110_aux_registers *regs;
const struct dce110_aux_registers_mask *mask;
const struct dce110_aux_registers_shift *shift;
struct {
uint32_t aux_control;
uint32_t aux_arb_control;
uint32_t aux_sw_data;
uint32_t aux_sw_control;
uint32_t aux_interrupt_control;
uint32_t aux_dphy_rx_control1;
uint32_t aux_dphy_rx_control0;
uint32_t aux_sw_status;
} addr;
uint32_t polling_timeout_period;
};
struct aux_engine_dce110_init_data {
uint32_t engine_id;
uint32_t timeout_period;
struct dc_context *ctx;
const struct dce110_aux_registers *regs;
};
struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
struct dc_context *ctx,
uint32_t inst,
uint32_t timeout_period,
const struct dce110_aux_registers *regs,
const struct dce110_aux_registers_mask *mask,
const struct dce110_aux_registers_shift *shift,
bool is_ext_aux_timeout_configurable);
void dce110_engine_destroy(struct dce_aux **engine);
bool dce110_aux_engine_acquire(
struct dce_aux *aux_engine,
struct ddc *ddc);
int dce_aux_transfer_raw(struct ddc_service *ddc,
struct aux_payload *cmd,
enum aux_return_code_type *operation_result);
int dce_aux_transfer_raw_with_ddc_pin(struct ddc_service *ddc,
struct aux_payload *cmd,
enum aux_return_code_type *operation_result);
int dce_aux_transfer_raw_without_ddc_pin(struct ddc_service *ddc,
struct aux_payload *cmd,
enum aux_return_code_type *operation_result);
int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
struct aux_payload *payload,
enum aux_return_code_type *operation_result);
bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
struct aux_payload *cmd);
struct dce_aux_funcs {
uint32_t (*configure_timeout)
(struct ddc_service *ddc,
uint32_t timeout);
void (*destroy)
(struct aux_engine **ptr);
};
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,355 @@
/* 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 __DC_CLOCK_SOURCE_DCE_H__
#define __DC_CLOCK_SOURCE_DCE_H__
#include "../inc/clock_source.h"
#define TO_DCE110_CLK_SRC(clk_src)\
container_of(clk_src, struct dce110_clk_src, base)
#define CS_COMMON_REG_LIST_DCE_100_110(id) \
SRI(RESYNC_CNTL, PIXCLK, id), \
SRI(PLL_CNTL, BPHYC_PLL, id)
#define CS_COMMON_REG_LIST_DCE_80(id) \
SRI(RESYNC_CNTL, PIXCLK, id), \
SRI(PLL_CNTL, DCCG_PLL, id)
#define CS_COMMON_REG_LIST_DCE_112(id) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, id)
#define CS_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
CS_SF(PLL_CNTL, PLL_REF_DIV_SRC, mask_sh),\
CS_SF(PIXCLK1_RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, mask_sh),\
CS_SF(PLL_POST_DIV, PLL_POST_DIV_PIXCLK, mask_sh),\
CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh)
#define CS_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\
CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\
CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh)
#define CS_COMMON_REG_LIST_DCN2_0(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(PHASE, DP_DTO, 2),\
SRII(PHASE, DP_DTO, 3),\
SRII(PHASE, DP_DTO, 4),\
SRII(PHASE, DP_DTO, 5),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 2),\
SRII(MODULO, DP_DTO, 3),\
SRII(MODULO, DP_DTO, 4),\
SRII(MODULO, DP_DTO, 5),\
SRII(PIXEL_RATE_CNTL, OTG, 0),\
SRII(PIXEL_RATE_CNTL, OTG, 1),\
SRII(PIXEL_RATE_CNTL, OTG, 2),\
SRII(PIXEL_RATE_CNTL, OTG, 3),\
SRII(PIXEL_RATE_CNTL, OTG, 4),\
SRII(PIXEL_RATE_CNTL, OTG, 5)
#define CS_COMMON_REG_LIST_DCN201(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(PIXEL_RATE_CNTL, OTG, 0),\
SRII(PIXEL_RATE_CNTL, OTG, 1)
#define CS_COMMON_REG_LIST_DCN2_1(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(PHASE, DP_DTO, 2),\
SRII(PHASE, DP_DTO, 3),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 2),\
SRII(MODULO, DP_DTO, 3),\
SRII(PIXEL_RATE_CNTL, OTG, 0),\
SRII(PIXEL_RATE_CNTL, OTG, 1),\
SRII(PIXEL_RATE_CNTL, OTG, 2),\
SRII(PIXEL_RATE_CNTL, OTG, 3)
#define CS_COMMON_REG_LIST_DCN3_0(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(PHASE, DP_DTO, 2),\
SRII(PHASE, DP_DTO, 3),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 2),\
SRII(MODULO, DP_DTO, 3),\
SRII(PIXEL_RATE_CNTL, OTG, 0),\
SRII(PIXEL_RATE_CNTL, OTG, 1),\
SRII(PIXEL_RATE_CNTL, OTG, 2),\
SRII(PIXEL_RATE_CNTL, OTG, 3)
#define CS_COMMON_REG_LIST_DCN3_01(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(PHASE, DP_DTO, 2),\
SRII(PHASE, DP_DTO, 3),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 2),\
SRII(MODULO, DP_DTO, 3),\
SRII(PIXEL_RATE_CNTL, OTG, 0),\
SRII(PIXEL_RATE_CNTL, OTG, 1),\
SRII(PIXEL_RATE_CNTL, OTG, 2),\
SRII(PIXEL_RATE_CNTL, OTG, 3)
#define CS_COMMON_REG_LIST_DCN3_02(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(PHASE, DP_DTO, 2),\
SRII(PHASE, DP_DTO, 3),\
SRII(PHASE, DP_DTO, 4),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 2),\
SRII(MODULO, DP_DTO, 3),\
SRII(MODULO, DP_DTO, 4),\
SRII(PIXEL_RATE_CNTL, OTG, 0),\
SRII(PIXEL_RATE_CNTL, OTG, 1),\
SRII(PIXEL_RATE_CNTL, OTG, 2),\
SRII(PIXEL_RATE_CNTL, OTG, 3),\
SRII(PIXEL_RATE_CNTL, OTG, 4)
#define CS_COMMON_REG_LIST_DCN3_03(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(PIXEL_RATE_CNTL, OTG, 0),\
SRII(PIXEL_RATE_CNTL, OTG, 1)
#define CS_COMMON_MASK_SH_LIST_DCN2_0(mask_sh)\
CS_SF(DP_DTO0_PHASE, DP_DTO0_PHASE, mask_sh),\
CS_SF(DP_DTO0_MODULO, DP_DTO0_MODULO, mask_sh),\
CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\
CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh)
#define CS_COMMON_MASK_SH_LIST_DCN3_1_4(mask_sh)\
CS_COMMON_MASK_SH_LIST_DCN2_0(mask_sh),\
CS_SF(OTG0_PIXEL_RATE_CNTL, PIPE0_DTO_SRC_SEL, mask_sh),
#define CS_COMMON_MASK_SH_LIST_DCN3_2(mask_sh)\
CS_COMMON_MASK_SH_LIST_DCN2_0(mask_sh),\
CS_SF(OTG0_PIXEL_RATE_CNTL, PIPE0_DTO_SRC_SEL, mask_sh)
#define CS_COMMON_MASK_SH_LIST_DCN4_0_1(mask_sh)\
CS_COMMON_MASK_SH_LIST_DCN3_2(mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, OTG0_TMDS_PIXEL_RATE_DIV, mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, DPDTO0_INT, mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, OTG1_TMDS_PIXEL_RATE_DIV, mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, DPDTO1_INT, mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, OTG2_TMDS_PIXEL_RATE_DIV, mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, DPDTO2_INT, mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, OTG3_TMDS_PIXEL_RATE_DIV, mask_sh),\
CS_SF(OTG_PIXEL_RATE_DIV, DPDTO3_INT, mask_sh)
#define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
SRII(PHASE, DP_DTO, 0),\
SRII(PHASE, DP_DTO, 1),\
SRII(PHASE, DP_DTO, 2),\
SRII(PHASE, DP_DTO, 3),\
SRII(MODULO, DP_DTO, 0),\
SRII(MODULO, DP_DTO, 1),\
SRII(MODULO, DP_DTO, 2),\
SRII(MODULO, DP_DTO, 3),\
SRII(PIXEL_RATE_CNTL, OTG, 0), \
SRII(PIXEL_RATE_CNTL, OTG, 1), \
SRII(PIXEL_RATE_CNTL, OTG, 2), \
SRII(PIXEL_RATE_CNTL, OTG, 3)
#define CS_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\
CS_SF(DP_DTO0_PHASE, DP_DTO0_PHASE, mask_sh),\
CS_SF(DP_DTO0_MODULO, DP_DTO0_MODULO, mask_sh),\
CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\
CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh)
#define CS_REG_FIELD_LIST(type) \
type PLL_REF_DIV_SRC; \
type DCCG_DEEP_COLOR_CNTL1; \
type PHYPLLA_DCCG_DEEP_COLOR_CNTL; \
type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \
type PLL_POST_DIV_PIXCLK; \
type PLL_REF_DIV; \
type DP_DTO0_PHASE; \
type DP_DTO0_MODULO; \
type DP_DTO0_ENABLE;
#define CS_REG_FIELD_LIST_DCN32(type) \
type PIPE0_DTO_SRC_SEL;
#define CS_REG_FIELD_LIST_DCN401(type) \
type DPDTO0_INT; \
type DPDTO1_INT; \
type DPDTO2_INT; \
type DPDTO3_INT; \
type OTG0_TMDS_PIXEL_RATE_DIV; \
type OTG1_TMDS_PIXEL_RATE_DIV; \
type OTG2_TMDS_PIXEL_RATE_DIV; \
type OTG3_TMDS_PIXEL_RATE_DIV;
struct dce110_clk_src_shift {
CS_REG_FIELD_LIST(uint8_t)
CS_REG_FIELD_LIST_DCN32(uint8_t)
CS_REG_FIELD_LIST_DCN401(uint8_t)
};
struct dce110_clk_src_mask {
CS_REG_FIELD_LIST(uint32_t)
CS_REG_FIELD_LIST_DCN32(uint32_t)
CS_REG_FIELD_LIST_DCN401(uint32_t)
};
struct dce110_clk_src_regs {
uint32_t RESYNC_CNTL;
uint32_t PIXCLK_RESYNC_CNTL;
uint32_t PLL_CNTL;
uint32_t OTG_PIXEL_RATE_DIV;
/* below are for DTO.
* todo: should probably use different struct to not waste space
*/
uint32_t PHASE[MAX_PIPES];
uint32_t MODULO[MAX_PIPES];
uint32_t PIXEL_RATE_CNTL[MAX_PIPES];
};
struct dce110_clk_src {
struct clock_source base;
const struct dce110_clk_src_regs *regs;
const struct dce110_clk_src_mask *cs_mask;
const struct dce110_clk_src_shift *cs_shift;
struct dc_bios *bios;
struct spread_spectrum_data *dp_ss_params;
uint32_t dp_ss_params_cnt;
struct spread_spectrum_data *hdmi_ss_params;
uint32_t hdmi_ss_params_cnt;
struct spread_spectrum_data *dvi_ss_params;
uint32_t dvi_ss_params_cnt;
struct spread_spectrum_data *lvds_ss_params;
uint32_t lvds_ss_params_cnt;
uint32_t ext_clk_khz;
uint32_t ref_freq_khz;
struct calc_pll_clock_source calc_pll;
struct calc_pll_clock_source calc_pll_hdmi;
};
bool dce110_clk_src_construct(
struct dce110_clk_src *clk_src,
struct dc_context *ctx,
struct dc_bios *bios,
enum clock_source_id id,
const struct dce110_clk_src_regs *regs,
const struct dce110_clk_src_shift *cs_shift,
const struct dce110_clk_src_mask *cs_mask);
bool dce112_clk_src_construct(
struct dce110_clk_src *clk_src,
struct dc_context *ctx,
struct dc_bios *bios,
enum clock_source_id id,
const struct dce110_clk_src_regs *regs,
const struct dce110_clk_src_shift *cs_shift,
const struct dce110_clk_src_mask *cs_mask);
bool dcn20_clk_src_construct(
struct dce110_clk_src *clk_src,
struct dc_context *ctx,
struct dc_bios *bios,
enum clock_source_id id,
const struct dce110_clk_src_regs *regs,
const struct dce110_clk_src_shift *cs_shift,
const struct dce110_clk_src_mask *cs_mask);
bool dcn3_clk_src_construct(
struct dce110_clk_src *clk_src,
struct dc_context *ctx,
struct dc_bios *bios,
enum clock_source_id id,
const struct dce110_clk_src_regs *regs,
const struct dce110_clk_src_shift *cs_shift,
const struct dce110_clk_src_mask *cs_mask);
bool dcn301_clk_src_construct(
struct dce110_clk_src *clk_src,
struct dc_context *ctx,
struct dc_bios *bios,
enum clock_source_id id,
const struct dce110_clk_src_regs *regs,
const struct dce110_clk_src_shift *cs_shift,
const struct dce110_clk_src_mask *cs_mask);
bool dcn31_clk_src_construct(
struct dce110_clk_src *clk_src,
struct dc_context *ctx,
struct dc_bios *bios,
enum clock_source_id id,
const struct dce110_clk_src_regs *regs,
const struct dce110_clk_src_shift *cs_shift,
const struct dce110_clk_src_mask *cs_mask);
bool dcn401_clk_src_construct(
struct dce110_clk_src *clk_src,
struct dc_context *ctx,
struct dc_bios *bios,
enum clock_source_id id,
const struct dce110_clk_src_regs *regs,
const struct dce110_clk_src_shift *cs_shift,
const struct dce110_clk_src_mask *cs_mask);
/* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */
struct pixel_rate_range_table_entry {
unsigned int range_min_khz;
unsigned int range_max_khz;
unsigned int target_pixel_rate_khz;
unsigned short mult_factor;
unsigned short div_factor;
};
extern const struct pixel_rate_range_table_entry video_optimized_pixel_rates[];
const struct pixel_rate_range_table_entry *look_up_in_video_optimized_rate_tlb(
unsigned int pixel_rate_khz);
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,331 @@
/*
* Copyright 2012-16 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_DMCU_H_
#define _DCE_DMCU_H_
#include "dmcu.h"
#define DMCU_COMMON_REG_LIST_DCE_BASE() \
SR(DMCU_CTRL), \
SR(DMCU_STATUS), \
SR(DMCU_RAM_ACCESS_CTRL), \
SR(DMCU_IRAM_WR_CTRL), \
SR(DMCU_IRAM_WR_DATA), \
SR(MASTER_COMM_DATA_REG1), \
SR(MASTER_COMM_DATA_REG2), \
SR(MASTER_COMM_DATA_REG3), \
SR(MASTER_COMM_CMD_REG), \
SR(MASTER_COMM_CNTL_REG), \
SR(SLAVE_COMM_DATA_REG1), \
SR(SLAVE_COMM_DATA_REG2), \
SR(SLAVE_COMM_DATA_REG3), \
SR(SLAVE_COMM_CMD_REG), \
SR(DMCU_IRAM_RD_CTRL), \
SR(DMCU_IRAM_RD_DATA), \
SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
SR(SMU_INTERRUPT_CONTROL), \
SR(DC_DMCU_SCRATCH)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define DMCU_DCE60_REG_LIST() \
SR(DMCU_CTRL), \
SR(DMCU_STATUS), \
SR(DMCU_RAM_ACCESS_CTRL), \
SR(DMCU_IRAM_WR_CTRL), \
SR(DMCU_IRAM_WR_DATA), \
SR(MASTER_COMM_DATA_REG1), \
SR(MASTER_COMM_DATA_REG2), \
SR(MASTER_COMM_DATA_REG3), \
SR(MASTER_COMM_CMD_REG), \
SR(MASTER_COMM_CNTL_REG), \
SR(DMCU_IRAM_RD_CTRL), \
SR(DMCU_IRAM_RD_DATA), \
SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
SR(DC_DMCU_SCRATCH)
#endif
#define DMCU_DCE80_REG_LIST() \
SR(DMCU_CTRL), \
SR(DMCU_STATUS), \
SR(DMCU_RAM_ACCESS_CTRL), \
SR(DMCU_IRAM_WR_CTRL), \
SR(DMCU_IRAM_WR_DATA), \
SR(MASTER_COMM_DATA_REG1), \
SR(MASTER_COMM_DATA_REG2), \
SR(MASTER_COMM_DATA_REG3), \
SR(MASTER_COMM_CMD_REG), \
SR(MASTER_COMM_CNTL_REG), \
SR(DMCU_IRAM_RD_CTRL), \
SR(DMCU_IRAM_RD_DATA), \
SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
SR(SMU_INTERRUPT_CONTROL), \
SR(DC_DMCU_SCRATCH)
#define DMCU_DCE110_COMMON_REG_LIST() \
DMCU_COMMON_REG_LIST_DCE_BASE(), \
SR(DCI_MEM_PWR_STATUS)
#define DMCU_DCN10_REG_LIST()\
DMCU_COMMON_REG_LIST_DCE_BASE(), \
SR(DMU_MEM_PWR_CNTL)
#define DMCU_DCN20_REG_LIST()\
DMCU_DCN10_REG_LIST(), \
SR(DMCUB_SCRATCH15)
#define DMCU_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
DMCU_SF(DMCU_CTRL, \
DMCU_ENABLE, mask_sh), \
DMCU_SF(DMCU_STATUS, \
UC_IN_STOP_MODE, mask_sh), \
DMCU_SF(DMCU_STATUS, \
UC_IN_RESET, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_HOST_ACCESS_EN, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_WR_ADDR_AUTO_INC, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_RD_ADDR_AUTO_INC, mask_sh), \
DMCU_SF(MASTER_COMM_CMD_REG, \
MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \
DMCU_SF(SLAVE_COMM_CNTL_REG, SLAVE_COMM_INTERRUPT, mask_sh), \
DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
STATIC_SCREEN1_INT_TO_UC_EN, mask_sh), \
DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
STATIC_SCREEN2_INT_TO_UC_EN, mask_sh), \
DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
STATIC_SCREEN3_INT_TO_UC_EN, mask_sh), \
DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
STATIC_SCREEN4_INT_TO_UC_EN, mask_sh), \
DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define DMCU_MASK_SH_LIST_DCE60(mask_sh) \
DMCU_SF(DMCU_CTRL, \
DMCU_ENABLE, mask_sh), \
DMCU_SF(DMCU_STATUS, \
UC_IN_STOP_MODE, mask_sh), \
DMCU_SF(DMCU_STATUS, \
UC_IN_RESET, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_HOST_ACCESS_EN, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_WR_ADDR_AUTO_INC, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_RD_ADDR_AUTO_INC, mask_sh), \
DMCU_SF(MASTER_COMM_CMD_REG, \
MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh)
#endif
#define DMCU_MASK_SH_LIST_DCE80(mask_sh) \
DMCU_SF(DMCU_CTRL, \
DMCU_ENABLE, mask_sh), \
DMCU_SF(DMCU_STATUS, \
UC_IN_STOP_MODE, mask_sh), \
DMCU_SF(DMCU_STATUS, \
UC_IN_RESET, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_HOST_ACCESS_EN, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_WR_ADDR_AUTO_INC, mask_sh), \
DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
IRAM_RD_ADDR_AUTO_INC, mask_sh), \
DMCU_SF(MASTER_COMM_CMD_REG, \
MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \
DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh)
#define DMCU_MASK_SH_LIST_DCE110(mask_sh) \
DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
DMCU_SF(DCI_MEM_PWR_STATUS, \
DMCU_IRAM_MEM_PWR_STATE, mask_sh)
#define DMCU_MASK_SH_LIST_DCN10(mask_sh) \
DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
DMCU_SF(DMU_MEM_PWR_CNTL, \
DMCU_IRAM_MEM_PWR_STATE, mask_sh)
#define DMCU_REG_FIELD_LIST(type) \
type DMCU_IRAM_MEM_PWR_STATE; \
type IRAM_HOST_ACCESS_EN; \
type IRAM_WR_ADDR_AUTO_INC; \
type IRAM_RD_ADDR_AUTO_INC; \
type DMCU_ENABLE; \
type UC_IN_STOP_MODE; \
type UC_IN_RESET; \
type MASTER_COMM_CMD_REG_BYTE0; \
type MASTER_COMM_INTERRUPT; \
type SLAVE_COMM_INTERRUPT; \
type DPHY_RX_FAST_TRAINING_CAPABLE; \
type DPHY_LOAD_BS_COUNT; \
type STATIC_SCREEN1_INT_TO_UC_EN; \
type STATIC_SCREEN2_INT_TO_UC_EN; \
type STATIC_SCREEN3_INT_TO_UC_EN; \
type STATIC_SCREEN4_INT_TO_UC_EN; \
type DP_SEC_GSP0_LINE_NUM; \
type DP_SEC_GSP0_PRIORITY; \
type DC_SMU_INT_ENABLE
struct dce_dmcu_shift {
DMCU_REG_FIELD_LIST(uint8_t);
};
struct dce_dmcu_mask {
DMCU_REG_FIELD_LIST(uint32_t);
};
struct dce_dmcu_registers {
uint32_t DMCU_CTRL;
uint32_t DMCU_STATUS;
uint32_t DMCU_RAM_ACCESS_CTRL;
uint32_t DCI_MEM_PWR_STATUS;
uint32_t DMU_MEM_PWR_CNTL;
uint32_t DMCU_IRAM_WR_CTRL;
uint32_t DMCU_IRAM_WR_DATA;
uint32_t MASTER_COMM_DATA_REG1;
uint32_t MASTER_COMM_DATA_REG2;
uint32_t MASTER_COMM_DATA_REG3;
uint32_t MASTER_COMM_CMD_REG;
uint32_t MASTER_COMM_CNTL_REG;
uint32_t SLAVE_COMM_DATA_REG1;
uint32_t SLAVE_COMM_DATA_REG2;
uint32_t SLAVE_COMM_DATA_REG3;
uint32_t SLAVE_COMM_CMD_REG;
uint32_t SLAVE_COMM_CNTL_REG;
uint32_t DMCU_IRAM_RD_CTRL;
uint32_t DMCU_IRAM_RD_DATA;
uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK;
uint32_t SMU_INTERRUPT_CONTROL;
uint32_t DC_DMCU_SCRATCH;
uint32_t DMCUB_SCRATCH15;
};
struct dce_dmcu {
struct dmcu base;
const struct dce_dmcu_registers *regs;
const struct dce_dmcu_shift *dmcu_shift;
const struct dce_dmcu_mask *dmcu_mask;
};
/*******************************************************************
* MASTER_COMM_DATA_REG1 Bit position Data
* 7:0 hyst_frames[7:0]
* 14:8 hyst_lines[6:0]
* 15 RFB_UPDATE_AUTO_EN
* 18:16 phy_num[2:0]
* 21:19 dcp_sel[2:0]
* 22 phy_type
* 23 frame_cap_ind
* 26:24 aux_chan[2:0]
* 30:27 aux_repeat[3:0]
* 31:31 reserved[31:31]
******************************************************************/
union dce_dmcu_psr_config_data_reg1 {
struct {
unsigned int timehyst_frames:8; /*[7:0]*/
unsigned int hyst_lines:7; /*[14:8]*/
unsigned int rfb_update_auto_en:1; /*[15:15]*/
unsigned int dp_port_num:3; /*[18:16]*/
unsigned int dcp_sel:3; /*[21:19]*/
unsigned int phy_type:1; /*[22:22]*/
unsigned int frame_cap_ind:1; /*[23:23]*/
unsigned int aux_chan:3; /*[26:24]*/
unsigned int aux_repeat:4; /*[30:27]*/
unsigned int allow_smu_optimizations:1; /*[31:31]*/
} bits;
unsigned int u32All;
};
/*******************************************************************
* MASTER_COMM_DATA_REG2
*******************************************************************/
union dce_dmcu_psr_config_data_reg2 {
struct {
unsigned int dig_fe:3; /*[2:0]*/
unsigned int dig_be:3; /*[5:3]*/
unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/
unsigned int reserved:9; /*[15:7]*/
unsigned int frame_delay:8; /*[23:16]*/
unsigned int smu_phy_id:4; /*[27:24]*/
unsigned int num_of_controllers:4; /*[31:28]*/
} bits;
unsigned int u32All;
};
/*******************************************************************
* MASTER_COMM_DATA_REG3
*******************************************************************/
union dce_dmcu_psr_config_data_reg3 {
struct {
unsigned int psr_level:16; /*[15:0]*/
unsigned int link_rate:4; /*[19:16]*/
unsigned int reserved:12; /*[31:20]*/
} bits;
unsigned int u32All;
};
union dce_dmcu_psr_config_data_wait_loop_reg1 {
struct {
unsigned int wait_loop:16; /* [15:0] */
unsigned int reserved:16; /* [31:16] */
} bits;
unsigned int u32;
};
struct dmcu *dce_dmcu_create(
struct dc_context *ctx,
const struct dce_dmcu_registers *regs,
const struct dce_dmcu_shift *dmcu_shift,
const struct dce_dmcu_mask *dmcu_mask);
struct dmcu *dcn10_dmcu_create(
struct dc_context *ctx,
const struct dce_dmcu_registers *regs,
const struct dce_dmcu_shift *dmcu_shift,
const struct dce_dmcu_mask *dmcu_mask);
struct dmcu *dcn20_dmcu_create(
struct dc_context *ctx,
const struct dce_dmcu_registers *regs,
const struct dce_dmcu_shift *dmcu_shift,
const struct dce_dmcu_mask *dmcu_mask);
struct dmcu *dcn21_dmcu_create(
struct dc_context *ctx,
const struct dce_dmcu_registers *regs,
const struct dce_dmcu_shift *dmcu_shift,
const struct dce_dmcu_mask *dmcu_mask);
void dce_dmcu_destroy(struct dmcu **dmcu);
#endif /* _DCE_ABM_H_ */
@@ -0,0 +1,84 @@
/*
* Copyright 2018 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_i2c.h"
#include "reg_helper.h"
bool dce_i2c_oem_device_present(
struct resource_pool *pool,
struct ddc_service *ddc,
size_t slave_address
)
{
(void)pool;
struct dc *dc = ddc->ctx->dc;
struct dc_bios *dcb = dc->ctx->dc_bios;
struct graphics_object_id id = {0};
struct graphics_object_i2c_info i2c_info;
if (!dc->ctx->dc_bios->fw_info.oem_i2c_present)
return false;
id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id;
id.enum_id = 0;
id.type = OBJECT_TYPE_GENERIC;
if (dcb->funcs->get_i2c_info(dcb, id, &i2c_info) != BP_RESULT_OK)
return false;
if (i2c_info.i2c_slave_address != slave_address)
return false;
return true;
}
bool dce_i2c_submit_command(
struct resource_pool *pool,
struct ddc *ddc,
struct i2c_command *cmd)
{
struct dce_i2c_hw *dce_i2c_hw;
struct dce_i2c_sw dce_i2c_sw = {0};
if (!ddc) {
BREAK_TO_DEBUGGER();
return false;
}
if (!cmd) {
BREAK_TO_DEBUGGER();
return false;
}
dce_i2c_hw = acquire_i2c_hw_engine(pool, ddc);
if (dce_i2c_hw)
return dce_i2c_submit_command_hw(pool, ddc, cmd, dce_i2c_hw);
dce_i2c_sw.ctx = ddc->ctx;
if (dce_i2c_engine_acquire_sw(&dce_i2c_sw, ddc)) {
return dce_i2c_submit_command_sw(pool, ddc, cmd, &dce_i2c_sw);
}
return false;
}
@@ -0,0 +1,44 @@
/*
* Copyright 2018 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_I2C_H__
#define __DCE_I2C_H__
#include "inc/core_types.h"
#include "dce_i2c_hw.h"
#include "dce_i2c_sw.h"
bool dce_i2c_oem_device_present(
struct resource_pool *pool,
struct ddc_service *ddc,
size_t slave_address
);
bool dce_i2c_submit_command(
struct resource_pool *pool,
struct ddc *ddc,
struct i2c_command *cmd);
#endif
@@ -0,0 +1,758 @@
/*
* Copyright 2018 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 "resource.h"
#include "dce_i2c.h"
#include "dce_i2c_hw.h"
#include "reg_helper.h"
#include "include/gpio_service_interface.h"
#define CTX \
dce_i2c_hw->ctx
#define REG(reg)\
dce_i2c_hw->regs->reg
#undef FN
#define FN(reg_name, field_name) \
dce_i2c_hw->shifts->field_name, dce_i2c_hw->masks->field_name
static void execute_transaction(
struct dce_i2c_hw *dce_i2c_hw)
{
REG_UPDATE_N(SETUP, 5,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
REG_UPDATE_5(DC_I2C_CONTROL,
DC_I2C_SOFT_RESET, 0,
DC_I2C_SW_STATUS_RESET, 0,
DC_I2C_SEND_RESET, 0,
DC_I2C_GO, 0,
DC_I2C_TRANSACTION_COUNT, dce_i2c_hw->transaction_count - 1);
/* start I2C transfer */
REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
/* all transactions were executed and HW buffer became empty
* (even though it actually happens when status becomes DONE)
*/
dce_i2c_hw->transaction_count = 0;
dce_i2c_hw->buffer_used_bytes = 0;
}
static enum i2c_channel_operation_result get_channel_status(
struct dce_i2c_hw *dce_i2c_hw,
uint8_t *returned_bytes)
{
(void)returned_bytes;
uint32_t i2c_sw_status = 0;
uint32_t value =
REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
else if (value & dce_i2c_hw->masks->DC_I2C_SW_STOPPED_ON_NACK)
return I2C_CHANNEL_OPERATION_NO_RESPONSE;
else if (value & dce_i2c_hw->masks->DC_I2C_SW_TIMEOUT)
return I2C_CHANNEL_OPERATION_TIMEOUT;
else if (value & dce_i2c_hw->masks->DC_I2C_SW_ABORTED)
return I2C_CHANNEL_OPERATION_FAILED;
else if (value & dce_i2c_hw->masks->DC_I2C_SW_DONE)
return I2C_CHANNEL_OPERATION_SUCCEEDED;
/*
* this is the case when HW used for communication, I2C_SW_STATUS
* could be zero
*/
return I2C_CHANNEL_OPERATION_SUCCEEDED;
}
static uint32_t get_hw_buffer_available_size(
const struct dce_i2c_hw *dce_i2c_hw)
{
return dce_i2c_hw->buffer_size -
dce_i2c_hw->buffer_used_bytes;
}
static void process_channel_reply(
struct dce_i2c_hw *dce_i2c_hw,
struct i2c_payload *reply)
{
uint32_t length = reply->length;
uint8_t *buffer = reply->data;
REG_SET_3(DC_I2C_DATA, 0,
DC_I2C_INDEX, dce_i2c_hw->buffer_used_write,
DC_I2C_DATA_RW, 1,
DC_I2C_INDEX_WRITE, 1);
while (length) {
/* after reading the status,
* if the I2C operation executed successfully
* (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
* should read data bytes from I2C circular data buffer
*/
uint32_t i2c_data;
REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
*buffer++ = (uint8_t)i2c_data;
--length;
}
}
static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw)
{
unsigned int arbitrate;
unsigned int i2c_hw_status;
REG_GET(HW_STATUS, DC_I2C_DDC1_HW_STATUS, &i2c_hw_status);
if (i2c_hw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW)
return false;
REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY)
return false;
return true;
}
static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
{
uint32_t i2c_sw_status = 0;
REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
return false;
if (is_engine_available(dce_i2c_hw))
return false;
return true;
}
static bool process_transaction(
struct dce_i2c_hw *dce_i2c_hw,
struct i2c_request_transaction_data *request)
{
uint32_t length = request->length;
uint8_t *buffer = request->data;
bool last_transaction = false;
uint32_t value = 0;
if (is_hw_busy(dce_i2c_hw)) {
request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
return false;
}
last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
(request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ));
switch (dce_i2c_hw->transaction_count) {
case 0:
REG_UPDATE_5(DC_I2C_TRANSACTION0,
DC_I2C_STOP_ON_NACK0, 1,
DC_I2C_START0, 1,
DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
DC_I2C_COUNT0, length,
DC_I2C_STOP0, last_transaction ? 1 : 0);
break;
case 1:
REG_UPDATE_5(DC_I2C_TRANSACTION1,
DC_I2C_STOP_ON_NACK0, 1,
DC_I2C_START0, 1,
DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
DC_I2C_COUNT0, length,
DC_I2C_STOP0, last_transaction ? 1 : 0);
break;
case 2:
REG_UPDATE_5(DC_I2C_TRANSACTION2,
DC_I2C_STOP_ON_NACK0, 1,
DC_I2C_START0, 1,
DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
DC_I2C_COUNT0, length,
DC_I2C_STOP0, last_transaction ? 1 : 0);
break;
case 3:
REG_UPDATE_5(DC_I2C_TRANSACTION3,
DC_I2C_STOP_ON_NACK0, 1,
DC_I2C_START0, 1,
DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
DC_I2C_COUNT0, length,
DC_I2C_STOP0, last_transaction ? 1 : 0);
break;
default:
/* TODO Warning ? */
break;
}
/* Write the I2C address and I2C data
* into the hardware circular buffer, one byte per entry.
* As an example, the 7-bit I2C slave address for CRT monitor
* for reading DDC/EDID information is 0b1010001.
* For an I2C send operation, the LSB must be programmed to 0;
* for I2C receive operation, the LSB must be programmed to 1.
*/
if (dce_i2c_hw->transaction_count == 0) {
value = REG_SET_4(DC_I2C_DATA, 0,
DC_I2C_DATA_RW, false,
DC_I2C_DATA, request->address,
DC_I2C_INDEX, 0,
DC_I2C_INDEX_WRITE, 1);
dce_i2c_hw->buffer_used_write = 0;
} else
value = REG_SET_2(DC_I2C_DATA, 0,
DC_I2C_DATA_RW, false,
DC_I2C_DATA, request->address);
dce_i2c_hw->buffer_used_write++;
if (!(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)) {
while (length) {
REG_SET_2(DC_I2C_DATA, value,
DC_I2C_INDEX_WRITE, 0,
DC_I2C_DATA, *buffer++);
dce_i2c_hw->buffer_used_write++;
--length;
}
}
++dce_i2c_hw->transaction_count;
dce_i2c_hw->buffer_used_bytes += length + 1;
return last_transaction;
}
static inline void reset_hw_engine(struct dce_i2c_hw *dce_i2c_hw)
{
REG_UPDATE_2(DC_I2C_CONTROL,
DC_I2C_SW_STATUS_RESET, 1,
DC_I2C_SW_STATUS_RESET, 1);
}
static void set_speed(
struct dce_i2c_hw *dce_i2c_hw,
uint32_t speed)
{
uint32_t xtal_ref_div = 0, ref_base_div = 0;
uint32_t prescale = 0;
uint32_t i2c_ref_clock = 0;
if (speed == 0)
return;
REG_GET_2(MICROSECOND_TIME_BASE_DIV, MICROSECOND_TIME_BASE_DIV, &ref_base_div,
XTAL_REF_DIV, &xtal_ref_div);
if (xtal_ref_div == 0)
xtal_ref_div = 2;
if (ref_base_div == 0)
i2c_ref_clock = (dce_i2c_hw->reference_frequency * 2);
else
i2c_ref_clock = ref_base_div * 1000;
prescale = (i2c_ref_clock / xtal_ref_div) / speed;
if (dce_i2c_hw->masks->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
REG_UPDATE_N(SPEED, 3,
FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), prescale,
FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
else
REG_UPDATE_N(SPEED, 2,
FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), prescale,
FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
}
static bool acquire_engine(struct dce_i2c_hw *dce_i2c_hw)
{
uint32_t arbitrate = 0;
REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
switch (arbitrate) {
case DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW:
return true;
case DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW:
return false;
case DC_I2C_STATUS__DC_I2C_STATUS_IDLE:
default:
break;
}
REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, true);
REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
if (arbitrate != DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
return false;
return true;
}
static bool setup_engine(
struct dce_i2c_hw *dce_i2c_hw)
{
// Deassert soft reset to unblock I2C engine registers
REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SOFT_RESET, false);
uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
uint32_t reset_length = 0;
if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL) {
REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 0);
REG_WAIT(DIO_MEM_PWR_STATUS, I2C_MEM_PWR_STATE, 0, 0, 5);
}
}
if (dce_i2c_hw->masks->DC_I2C_DDC1_CLK_EN)
REG_UPDATE_N(SETUP, 1,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_EN), 1);
if (!acquire_engine(dce_i2c_hw))
return false;
/*set SW requested I2c speed to default, if API calls in it will be override later*/
set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz);
if (dce_i2c_hw->setup_limit != 0)
i2c_setup_limit = dce_i2c_hw->setup_limit;
/* Program pin select */
REG_UPDATE_5(DC_I2C_CONTROL,
DC_I2C_GO, 0,
DC_I2C_SEND_RESET, 0,
DC_I2C_SW_STATUS_RESET, 1,
DC_I2C_TRANSACTION_COUNT, 0,
DC_I2C_DDC_SELECT, dce_i2c_hw->engine_id);
/* Program time limit */
if (dce_i2c_hw->send_reset_length == 0) {
/*pre-dcn*/
REG_UPDATE_N(SETUP, 2,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
} else {
reset_length = dce_i2c_hw->send_reset_length;
REG_UPDATE_N(SETUP, 3,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_SEND_RESET_LENGTH), reset_length,
FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
}
/* Program HW priority
* set to High - interrupt software I2C at any time
* Enable restart of SW I2C that was interrupted by HW
* disable queuing of software while I2C is in use by HW
*/
REG_UPDATE(DC_I2C_ARBITRATION,
DC_I2C_NO_QUEUED_SW_GO, 0);
return true;
}
/**
* cntl_stuck_hw_workaround - Workaround for I2C engine stuck state
* @dce_i2c_hw: Pointer to dce_i2c_hw structure
*
* If we boot without an HDMI display, the I2C engine does not get initialized
* correctly. One of its symptoms is that SW_USE_I2C does not get cleared after
* acquire. After setting SW_DONE_USING_I2C on release, the engine gets
* immediately reacquired by SW, preventing DMUB from using it.
*
* This function checks the I2C arbitration status and applies a release
* workaround if necessary.
*/
static void cntl_stuck_hw_workaround(struct dce_i2c_hw *dce_i2c_hw)
{
uint32_t arbitrate = 0;
REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
if (arbitrate != DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
return;
// Still acquired after release, release again as a workaround
REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, true);
REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
ASSERT(arbitrate != DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW);
}
static void release_engine(
struct dce_i2c_hw *dce_i2c_hw)
{
bool safe_to_reset;
/* Reset HW engine */
{
uint32_t i2c_sw_status = 0;
REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
/* if used by SW, safe to reset */
safe_to_reset = (i2c_sw_status == 1);
}
if (safe_to_reset)
REG_UPDATE_2(DC_I2C_CONTROL,
DC_I2C_SOFT_RESET, 1,
DC_I2C_SW_STATUS_RESET, 1);
else
REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
/* HW I2c engine - clock gating feature */
if (!dce_i2c_hw->engine_keep_power_up_count)
REG_UPDATE_N(SETUP, 1, FN(SETUP, DC_I2C_DDC1_ENABLE), 0);
/*for HW HDCP Ri polling failure w/a test*/
set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz_hdcp);
// Release I2C engine so it can be used by HW or DMCU, automatically clears SW_USE_I2C
REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, true);
cntl_stuck_hw_workaround(dce_i2c_hw);
if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL)
REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1);
}
}
struct dce_i2c_hw *acquire_i2c_hw_engine(
struct resource_pool *pool,
struct ddc *ddc)
{
uint32_t counter = 0;
enum gpio_result result;
struct dce_i2c_hw *dce_i2c_hw = NULL;
if (!ddc)
return NULL;
if (ddc->hw_info.hw_supported) {
enum gpio_ddc_line line = dal_ddc_get_line(ddc);
if (line < pool->res_cap->num_ddc)
dce_i2c_hw = pool->hw_i2cs[line];
}
if (!dce_i2c_hw)
return NULL;
if (pool->i2c_hw_buffer_in_use || !is_engine_available(dce_i2c_hw))
return NULL;
do {
result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
GPIO_DDC_CONFIG_TYPE_MODE_I2C);
if (result == GPIO_RESULT_OK)
break;
/* i2c_engine is busy by VBios, lets wait and retry */
udelay(10);
++counter;
} while (counter < 2);
if (result != GPIO_RESULT_OK)
return NULL;
dce_i2c_hw->ddc = ddc;
if (!setup_engine(dce_i2c_hw)) {
release_engine(dce_i2c_hw);
return NULL;
}
pool->i2c_hw_buffer_in_use = true;
return dce_i2c_hw;
}
static enum i2c_channel_operation_result dce_i2c_hw_engine_wait_on_operation_result(struct dce_i2c_hw *dce_i2c_hw,
uint32_t timeout,
enum i2c_channel_operation_result expected_result)
{
enum i2c_channel_operation_result result;
uint32_t i = 0;
if (!timeout)
return I2C_CHANNEL_OPERATION_SUCCEEDED;
do {
result = get_channel_status(
dce_i2c_hw, NULL);
if (result != expected_result)
break;
udelay(1);
++i;
} while (i < timeout);
return result;
}
static void submit_channel_request_hw(
struct dce_i2c_hw *dce_i2c_hw,
struct i2c_request_transaction_data *request)
{
request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
if (!process_transaction(dce_i2c_hw, request))
return;
if (is_hw_busy(dce_i2c_hw)) {
request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
return;
}
reset_hw_engine(dce_i2c_hw);
execute_transaction(dce_i2c_hw);
}
static uint32_t get_transaction_timeout_hw(
const struct dce_i2c_hw *dce_i2c_hw,
uint32_t length,
uint32_t speed)
{
uint32_t period_timeout;
uint32_t num_of_clock_stretches;
if (!speed)
return 0;
period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
num_of_clock_stretches = 1 + (length << 3) + 1;
num_of_clock_stretches +=
(dce_i2c_hw->buffer_used_bytes << 3) +
(dce_i2c_hw->transaction_count << 1);
return period_timeout * num_of_clock_stretches;
}
static bool dce_i2c_hw_engine_submit_payload(struct dce_i2c_hw *dce_i2c_hw,
struct i2c_payload *payload,
bool middle_of_transaction,
uint32_t speed)
{
struct i2c_request_transaction_data request;
uint32_t transaction_timeout;
enum i2c_channel_operation_result operation_result;
bool result = false;
/* We need following:
* transaction length will not exceed
* the number of free bytes in HW buffer (minus one for address)
*/
if (payload->length >=
get_hw_buffer_available_size(dce_i2c_hw)) {
return false;
}
if (!payload->write)
request.action = middle_of_transaction ?
DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
DCE_I2C_TRANSACTION_ACTION_I2C_READ;
else
request.action = middle_of_transaction ?
DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
request.address = (uint8_t) ((payload->address << 1) | (payload->write ? 0 : 1));
request.length = payload->length;
request.data = payload->data;
/* obtain timeout value before submitting request */
transaction_timeout = get_transaction_timeout_hw(
dce_i2c_hw, payload->length + 1, speed);
submit_channel_request_hw(
dce_i2c_hw, &request);
if ((request.status == I2C_CHANNEL_OPERATION_FAILED) ||
(request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY))
return false;
/* wait until transaction proceed */
operation_result = dce_i2c_hw_engine_wait_on_operation_result(
dce_i2c_hw,
transaction_timeout,
I2C_CHANNEL_OPERATION_ENGINE_BUSY);
/* update transaction status */
if (operation_result == I2C_CHANNEL_OPERATION_SUCCEEDED)
result = true;
if (result && (!payload->write))
process_channel_reply(dce_i2c_hw, payload);
return result;
}
bool dce_i2c_submit_command_hw(
struct resource_pool *pool,
struct ddc *ddc,
struct i2c_command *cmd,
struct dce_i2c_hw *dce_i2c_hw)
{
(void)ddc;
uint8_t index_of_payload = 0;
bool result;
set_speed(dce_i2c_hw, cmd->speed);
result = true;
while (index_of_payload < cmd->number_of_payloads) {
bool mot = (index_of_payload != cmd->number_of_payloads - 1);
struct i2c_payload *payload = cmd->payloads + index_of_payload;
if (!dce_i2c_hw_engine_submit_payload(
dce_i2c_hw, payload, mot, cmd->speed)) {
result = false;
break;
}
++index_of_payload;
}
pool->i2c_hw_buffer_in_use = false;
release_engine(dce_i2c_hw);
dal_ddc_close(dce_i2c_hw->ddc);
dce_i2c_hw->ddc = NULL;
return result;
}
void dce_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks)
{
dce_i2c_hw->ctx = ctx;
dce_i2c_hw->engine_id = engine_id;
dce_i2c_hw->reference_frequency = (ctx->dc_bios->fw_info.pll_info.crystal_frequency) >> 1;
dce_i2c_hw->regs = regs;
dce_i2c_hw->shifts = shifts;
dce_i2c_hw->masks = masks;
dce_i2c_hw->buffer_used_bytes = 0;
dce_i2c_hw->transaction_count = 0;
dce_i2c_hw->engine_keep_power_up_count = 1;
dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED;
dce_i2c_hw->send_reset_length = 0;
dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE;
}
void dce100_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks)
{
dce_i2c_hw_construct(dce_i2c_hw,
ctx,
engine_id,
regs,
shifts,
masks);
dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE100;
}
void dce112_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks)
{
dce100_i2c_hw_construct(dce_i2c_hw,
ctx,
engine_id,
regs,
shifts,
masks);
dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED_100KHZ;
}
void dcn1_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks)
{
dce112_i2c_hw_construct(dce_i2c_hw,
ctx,
engine_id,
regs,
shifts,
masks);
dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCN;
}
void dcn2_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks)
{
dcn1_i2c_hw_construct(dce_i2c_hw,
ctx,
engine_id,
regs,
shifts,
masks);
dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_9;
if (ctx->dc->debug.scl_reset_length10)
dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_10;
}
@@ -0,0 +1,355 @@
/*
* Copyright 2018 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_I2C_HW_H__
#define __DCE_I2C_HW_H__
enum dc_i2c_status {
DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW,
DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY = 2,
};
enum dc_i2c_arbitration {
DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
};
enum i2c_channel_operation_result {
I2C_CHANNEL_OPERATION_SUCCEEDED,
I2C_CHANNEL_OPERATION_FAILED,
I2C_CHANNEL_OPERATION_NOT_GRANTED,
I2C_CHANNEL_OPERATION_IS_BUSY,
I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED,
I2C_CHANNEL_OPERATION_CHANNEL_IN_USE,
I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED,
I2C_CHANNEL_OPERATION_ENGINE_BUSY,
I2C_CHANNEL_OPERATION_TIMEOUT,
I2C_CHANNEL_OPERATION_NO_RESPONSE,
I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS,
I2C_CHANNEL_OPERATION_WRONG_PARAMETER,
I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES,
I2C_CHANNEL_OPERATION_NOT_STARTED
};
enum dce_i2c_transaction_action {
DCE_I2C_TRANSACTION_ACTION_I2C_WRITE = 0x00,
DCE_I2C_TRANSACTION_ACTION_I2C_READ = 0x10,
DCE_I2C_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20,
DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40,
DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT = 0x50,
DCE_I2C_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60,
DCE_I2C_TRANSACTION_ACTION_DP_WRITE = 0x80,
DCE_I2C_TRANSACTION_ACTION_DP_READ = 0x90
};
enum {
I2C_SETUP_TIME_LIMIT_DCE = 255,
I2C_SETUP_TIME_LIMIT_DCN = 3,
I2C_HW_BUFFER_SIZE_DCE100 = 538,
I2C_HW_BUFFER_SIZE_DCE = 144,
I2C_SEND_RESET_LENGTH_9 = 9,
I2C_SEND_RESET_LENGTH_10 = 10,
DEFAULT_I2C_HW_SPEED = 50,
DEFAULT_I2C_HW_SPEED_100KHZ = 100,
TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32,
};
#define I2C_HW_ENGINE_COMMON_REG_LIST(id)\
SRI(SETUP, DC_I2C_DDC, id),\
SRI(SPEED, DC_I2C_DDC, id),\
SRI(HW_STATUS, DC_I2C_DDC, id),\
SR(DC_I2C_ARBITRATION),\
SR(DC_I2C_CONTROL),\
SR(DC_I2C_SW_STATUS),\
SR(DC_I2C_TRANSACTION0),\
SR(DC_I2C_TRANSACTION1),\
SR(DC_I2C_TRANSACTION2),\
SR(DC_I2C_TRANSACTION3),\
SR(DC_I2C_DATA),\
SR(MICROSECOND_TIME_BASE_DIV)
#define I2C_HW_ENGINE_COMMON_REG_LIST_DCN30(id)\
I2C_HW_ENGINE_COMMON_REG_LIST(id),\
SR(DIO_MEM_PWR_CTRL),\
SR(DIO_MEM_PWR_STATUS)
#define I2C_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE, mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT, mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN, mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN, mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL, mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY, mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY, mask_sh),\
I2C_SF(DC_I2C_DDC1_HW_STATUS, DC_I2C_DDC1_HW_STATUS, mask_sh),\
I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, mask_sh),\
I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, mask_sh),\
I2C_SF(DC_I2C_ARBITRATION, DC_I2C_NO_QUEUED_SW_GO, mask_sh),\
I2C_SF(DC_I2C_ARBITRATION, DC_I2C_SW_PRIORITY, mask_sh),\
I2C_SF(DC_I2C_CONTROL, DC_I2C_SOFT_RESET, mask_sh),\
I2C_SF(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, mask_sh),\
I2C_SF(DC_I2C_CONTROL, DC_I2C_GO, mask_sh),\
I2C_SF(DC_I2C_CONTROL, DC_I2C_SEND_RESET, mask_sh),\
I2C_SF(DC_I2C_CONTROL, DC_I2C_TRANSACTION_COUNT, mask_sh),\
I2C_SF(DC_I2C_CONTROL, DC_I2C_DDC_SELECT, mask_sh),\
I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE, mask_sh),\
I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD, mask_sh),\
I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STOPPED_ON_NACK, mask_sh),\
I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_TIMEOUT, mask_sh),\
I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_ABORTED, mask_sh),\
I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_DONE, mask_sh),\
I2C_SF(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, mask_sh),\
I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0, mask_sh),\
I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_START0, mask_sh),\
I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_RW0, mask_sh),\
I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_STOP0, mask_sh),\
I2C_SF(DC_I2C_TRANSACTION0, DC_I2C_COUNT0, mask_sh),\
I2C_SF(DC_I2C_DATA, DC_I2C_DATA_RW, mask_sh),\
I2C_SF(DC_I2C_DATA, DC_I2C_DATA, mask_sh),\
I2C_SF(DC_I2C_DATA, DC_I2C_INDEX, mask_sh),\
I2C_SF(DC_I2C_DATA, DC_I2C_INDEX_WRITE, mask_sh),\
I2C_SF(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, mask_sh),\
I2C_SF(MICROSECOND_TIME_BASE_DIV, MICROSECOND_TIME_BASE_DIV, mask_sh),\
I2C_SF(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, mask_sh)
#define I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh)\
I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
I2C_SF(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL, mask_sh)
struct dce_i2c_shift {
uint8_t DC_I2C_DDC1_ENABLE;
uint8_t DC_I2C_DDC1_TIME_LIMIT;
uint8_t DC_I2C_DDC1_DATA_DRIVE_EN;
uint8_t DC_I2C_DDC1_CLK_DRIVE_EN;
uint8_t DC_I2C_DDC1_DATA_DRIVE_SEL;
uint8_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
uint8_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
uint8_t DC_I2C_DDC1_HW_STATUS;
uint8_t DC_I2C_SW_DONE_USING_I2C_REG;
uint8_t DC_I2C_SW_USE_I2C_REG_REQ;
uint8_t DC_I2C_NO_QUEUED_SW_GO;
uint8_t DC_I2C_SW_PRIORITY;
uint8_t DC_I2C_SOFT_RESET;
uint8_t DC_I2C_SW_STATUS_RESET;
uint8_t DC_I2C_GO;
uint8_t DC_I2C_SEND_RESET;
uint8_t DC_I2C_TRANSACTION_COUNT;
uint8_t DC_I2C_DDC_SELECT;
uint8_t DC_I2C_DDC1_PRESCALE;
uint8_t DC_I2C_DDC1_THRESHOLD;
uint8_t DC_I2C_DDC1_START_STOP_TIMING_CNTL;
uint8_t DC_I2C_SW_STOPPED_ON_NACK;
uint8_t DC_I2C_SW_TIMEOUT;
uint8_t DC_I2C_SW_ABORTED;
uint8_t DC_I2C_SW_DONE;
uint8_t DC_I2C_SW_STATUS;
uint8_t DC_I2C_STOP_ON_NACK0;
uint8_t DC_I2C_START0;
uint8_t DC_I2C_RW0;
uint8_t DC_I2C_STOP0;
uint8_t DC_I2C_COUNT0;
uint8_t DC_I2C_DATA_RW;
uint8_t DC_I2C_DATA;
uint8_t DC_I2C_INDEX;
uint8_t DC_I2C_INDEX_WRITE;
uint8_t XTAL_REF_DIV;
uint8_t MICROSECOND_TIME_BASE_DIV;
uint8_t DC_I2C_DDC1_SEND_RESET_LENGTH;
uint8_t DC_I2C_REG_RW_CNTL_STATUS;
uint8_t I2C_LIGHT_SLEEP_FORCE;
uint8_t I2C_MEM_PWR_STATE;
uint8_t DC_I2C_DDC1_CLK_EN;
};
struct dce_i2c_mask {
uint32_t DC_I2C_DDC1_ENABLE;
uint32_t DC_I2C_DDC1_TIME_LIMIT;
uint32_t DC_I2C_DDC1_DATA_DRIVE_EN;
uint32_t DC_I2C_DDC1_CLK_DRIVE_EN;
uint32_t DC_I2C_DDC1_DATA_DRIVE_SEL;
uint32_t DC_I2C_DDC1_INTRA_TRANSACTION_DELAY;
uint32_t DC_I2C_DDC1_INTRA_BYTE_DELAY;
uint32_t DC_I2C_DDC1_HW_STATUS;
uint32_t DC_I2C_SW_DONE_USING_I2C_REG;
uint32_t DC_I2C_SW_USE_I2C_REG_REQ;
uint32_t DC_I2C_NO_QUEUED_SW_GO;
uint32_t DC_I2C_SW_PRIORITY;
uint32_t DC_I2C_SOFT_RESET;
uint32_t DC_I2C_SW_STATUS_RESET;
uint32_t DC_I2C_GO;
uint32_t DC_I2C_SEND_RESET;
uint32_t DC_I2C_TRANSACTION_COUNT;
uint32_t DC_I2C_DDC_SELECT;
uint32_t DC_I2C_DDC1_PRESCALE;
uint32_t DC_I2C_DDC1_THRESHOLD;
uint32_t DC_I2C_DDC1_START_STOP_TIMING_CNTL;
uint32_t DC_I2C_SW_STOPPED_ON_NACK;
uint32_t DC_I2C_SW_TIMEOUT;
uint32_t DC_I2C_SW_ABORTED;
uint32_t DC_I2C_SW_DONE;
uint32_t DC_I2C_SW_STATUS;
uint32_t DC_I2C_STOP_ON_NACK0;
uint32_t DC_I2C_START0;
uint32_t DC_I2C_RW0;
uint32_t DC_I2C_STOP0;
uint32_t DC_I2C_COUNT0;
uint32_t DC_I2C_DATA_RW;
uint32_t DC_I2C_DATA;
uint32_t DC_I2C_INDEX;
uint32_t DC_I2C_INDEX_WRITE;
uint32_t XTAL_REF_DIV;
uint32_t MICROSECOND_TIME_BASE_DIV;
uint32_t DC_I2C_DDC1_SEND_RESET_LENGTH;
uint32_t DC_I2C_REG_RW_CNTL_STATUS;
uint32_t I2C_LIGHT_SLEEP_FORCE;
uint32_t I2C_MEM_PWR_STATE;
uint32_t DC_I2C_DDC1_CLK_EN;
};
#define I2C_COMMON_MASK_SH_LIST_DCN2(mask_sh)\
I2C_COMMON_MASK_SH_LIST_DCE110(mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_SEND_RESET_LENGTH, mask_sh)
#define I2C_COMMON_MASK_SH_LIST_DCN30(mask_sh)\
I2C_COMMON_MASK_SH_LIST_DCN2(mask_sh),\
I2C_SF(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh),\
I2C_SF(DIO_MEM_PWR_STATUS, I2C_MEM_PWR_STATE, mask_sh)
#define I2C_COMMON_MASK_SH_LIST_DCN35(mask_sh)\
I2C_COMMON_MASK_SH_LIST_DCN30(mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_EN, mask_sh)
#define I2C_COMMON_MASK_SH_LIST_DCN401(mask_sh)\
I2C_COMMON_MASK_SH_LIST_DCN30(mask_sh),\
I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_EN, mask_sh)
struct dce_i2c_registers {
uint32_t SETUP;
uint32_t SPEED;
uint32_t HW_STATUS;
uint32_t DC_I2C_ARBITRATION;
uint32_t DC_I2C_CONTROL;
uint32_t DC_I2C_SW_STATUS;
uint32_t DC_I2C_TRANSACTION0;
uint32_t DC_I2C_TRANSACTION1;
uint32_t DC_I2C_TRANSACTION2;
uint32_t DC_I2C_TRANSACTION3;
uint32_t DC_I2C_DATA;
uint32_t MICROSECOND_TIME_BASE_DIV;
uint32_t DIO_MEM_PWR_CTRL;
uint32_t DIO_MEM_PWR_STATUS;
};
enum dce_i2c_transaction_address_space {
DCE_I2C_TRANSACTION_ADDRESS_SPACE_I2C = 1,
DCE_I2C_TRANSACTION_ADDRESS_SPACE_DPCD
};
struct i2c_request_transaction_data {
enum dce_i2c_transaction_action action;
enum i2c_channel_operation_result status;
uint8_t address;
uint32_t length;
uint8_t *data;
};
struct dce_i2c_hw {
struct ddc *ddc;
uint32_t engine_keep_power_up_count;
uint32_t transaction_count;
uint32_t buffer_used_bytes;
uint32_t buffer_used_write;
uint32_t reference_frequency;
uint32_t default_speed;
uint32_t engine_id;
uint32_t setup_limit;
uint32_t send_reset_length;
uint32_t buffer_size;
struct dc_context *ctx;
const struct dce_i2c_registers *regs;
const struct dce_i2c_shift *shifts;
const struct dce_i2c_mask *masks;
};
void dce_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks);
void dce100_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks);
void dce112_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks);
void dcn1_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks);
void dcn2_i2c_hw_construct(
struct dce_i2c_hw *dce_i2c_hw,
struct dc_context *ctx,
uint32_t engine_id,
const struct dce_i2c_registers *regs,
const struct dce_i2c_shift *shifts,
const struct dce_i2c_mask *masks);
bool dce_i2c_submit_command_hw(
struct resource_pool *pool,
struct ddc *ddc,
struct i2c_command *cmd,
struct dce_i2c_hw *dce_i2c_hw);
struct dce_i2c_hw *acquire_i2c_hw_engine(
struct resource_pool *pool,
struct ddc *ddc);
#endif
@@ -0,0 +1,499 @@
/*
* Copyright 2018 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_i2c.h"
#include "dce_i2c_sw.h"
#include "include/gpio_service_interface.h"
#define SCL false
#define SDA true
void dce_i2c_sw_construct(
struct dce_i2c_sw *dce_i2c_sw,
struct dc_context *ctx)
{
dce_i2c_sw->ctx = ctx;
}
static inline bool read_bit_from_ddc(
struct ddc *ddc,
bool data_nor_clock)
{
uint32_t value = 0;
if (data_nor_clock)
dal_gpio_get_value(ddc->pin_data, &value);
else
dal_gpio_get_value(ddc->pin_clock, &value);
return (value != 0);
}
static inline void write_bit_to_ddc(
struct ddc *ddc,
bool data_nor_clock,
bool bit)
{
uint32_t value = bit ? 1 : 0;
if (data_nor_clock)
dal_gpio_set_value(ddc->pin_data, value);
else
dal_gpio_set_value(ddc->pin_clock, value);
}
static void release_engine_dce_sw(
struct resource_pool *pool,
struct dce_i2c_sw *dce_i2c_sw)
{
(void)pool;
dal_ddc_close(dce_i2c_sw->ddc);
dce_i2c_sw->ddc = NULL;
}
static bool wait_for_scl_high_sw(
struct dc_context *ctx,
struct ddc *ddc,
uint32_t clock_delay_div_4)
{
(void)ctx;
uint32_t scl_retry = 0;
uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
udelay(clock_delay_div_4);
do {
if (read_bit_from_ddc(ddc, SCL))
return true;
udelay(clock_delay_div_4);
++scl_retry;
} while (scl_retry <= scl_retry_max);
return false;
}
static bool write_byte_sw(
struct dc_context *ctx,
struct ddc *ddc_handle,
uint32_t clock_delay_div_4,
uint8_t byte)
{
int32_t shift = 7;
bool ack;
/* bits are transmitted serially, starting from MSB */
do {
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SCL, true);
if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
return false;
write_bit_to_ddc(ddc_handle, SCL, false);
--shift;
} while (shift >= 0);
/* The display sends ACK by preventing the SDA from going high
* after the SCL pulse we use to send our last data bit.
* If the SDA goes high after that bit, it's a NACK
*/
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SDA, true);
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SCL, true);
if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
return false;
/* read ACK bit */
ack = !read_bit_from_ddc(ddc_handle, SDA);
udelay(clock_delay_div_4 << 1);
write_bit_to_ddc(ddc_handle, SCL, false);
udelay(clock_delay_div_4 << 1);
return ack;
}
static bool read_byte_sw(
struct dc_context *ctx,
struct ddc *ddc_handle,
uint32_t clock_delay_div_4,
uint8_t *byte,
bool more)
{
int32_t shift = 7;
uint8_t data = 0;
/* The data bits are read from MSB to LSB;
* bit is read while SCL is high
*/
do {
write_bit_to_ddc(ddc_handle, SCL, true);
if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
return false;
if (read_bit_from_ddc(ddc_handle, SDA))
data |= (1 << shift);
write_bit_to_ddc(ddc_handle, SCL, false);
udelay(clock_delay_div_4 << 1);
--shift;
} while (shift >= 0);
/* read only whole byte */
*byte = data;
udelay(clock_delay_div_4);
/* send the acknowledge bit:
* SDA low means ACK, SDA high means NACK
*/
write_bit_to_ddc(ddc_handle, SDA, !more);
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SCL, true);
if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
return false;
write_bit_to_ddc(ddc_handle, SCL, false);
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SDA, true);
udelay(clock_delay_div_4);
return true;
}
static bool stop_sync_sw(
struct dc_context *ctx,
struct ddc *ddc_handle,
uint32_t clock_delay_div_4)
{
uint32_t retry = 0;
/* The I2C communications stop signal is:
* the SDA going high from low, while the SCL is high.
*/
write_bit_to_ddc(ddc_handle, SCL, false);
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SDA, false);
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SCL, true);
if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
return false;
write_bit_to_ddc(ddc_handle, SDA, true);
do {
udelay(clock_delay_div_4);
if (read_bit_from_ddc(ddc_handle, SDA))
return true;
++retry;
} while (retry <= 2);
return false;
}
static bool i2c_write_sw(
struct dc_context *ctx,
struct ddc *ddc_handle,
uint32_t clock_delay_div_4,
uint8_t address,
uint32_t length,
const uint8_t *data)
{
uint32_t i = 0;
if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
return false;
while (i < length) {
if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, data[i]))
return false;
++i;
}
return true;
}
static bool i2c_read_sw(
struct dc_context *ctx,
struct ddc *ddc_handle,
uint32_t clock_delay_div_4,
uint8_t address,
uint32_t length,
uint8_t *data)
{
uint32_t i = 0;
if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
return false;
while (i < length) {
if (!read_byte_sw(ctx, ddc_handle, clock_delay_div_4, data + i,
i < length - 1))
return false;
++i;
}
return true;
}
static bool start_sync_sw(
struct dc_context *ctx,
struct ddc *ddc_handle,
uint32_t clock_delay_div_4)
{
uint32_t retry = 0;
/* The I2C communications start signal is:
* the SDA going low from high, while the SCL is high.
*/
write_bit_to_ddc(ddc_handle, SCL, true);
udelay(clock_delay_div_4);
do {
write_bit_to_ddc(ddc_handle, SDA, true);
if (!read_bit_from_ddc(ddc_handle, SDA)) {
++retry;
continue;
}
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SCL, true);
if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
break;
write_bit_to_ddc(ddc_handle, SDA, false);
udelay(clock_delay_div_4);
write_bit_to_ddc(ddc_handle, SCL, false);
udelay(clock_delay_div_4);
return true;
} while (retry <= I2C_SW_RETRIES);
return false;
}
static void dce_i2c_sw_engine_set_speed(
struct dce_i2c_sw *engine,
uint32_t speed)
{
ASSERT(speed);
engine->speed = speed ? speed : DCE_I2C_DEFAULT_I2C_SW_SPEED;
engine->clock_delay = 1000 / engine->speed;
if (engine->clock_delay < 12)
engine->clock_delay = 12;
}
static bool dce_i2c_sw_engine_acquire_engine(
struct dce_i2c_sw *engine,
struct ddc *ddc)
{
enum gpio_result result;
result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
GPIO_DDC_CONFIG_TYPE_MODE_I2C);
if (result != GPIO_RESULT_OK)
return false;
engine->ddc = ddc;
return true;
}
bool dce_i2c_engine_acquire_sw(
struct dce_i2c_sw *dce_i2c_sw,
struct ddc *ddc_handle)
{
uint32_t counter = 0;
bool result;
do {
result = dce_i2c_sw_engine_acquire_engine(
dce_i2c_sw, ddc_handle);
if (result)
break;
/* i2c_engine is busy by VBios, lets wait and retry */
udelay(10);
++counter;
} while (counter < 2);
return result;
}
static void dce_i2c_sw_engine_submit_channel_request(struct dce_i2c_sw *engine,
struct i2c_request_transaction_data *req)
{
struct ddc *ddc = engine->ddc;
uint32_t clock_delay_div_4 = engine->clock_delay >> 2;
/* send sync (start / repeated start) */
bool result = start_sync_sw(engine->ctx, ddc, clock_delay_div_4);
/* process payload */
if (result) {
switch (req->action) {
case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE:
case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT:
result = i2c_write_sw(engine->ctx, ddc, clock_delay_div_4,
req->address, req->length, req->data);
break;
case DCE_I2C_TRANSACTION_ACTION_I2C_READ:
case DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT:
result = i2c_read_sw(engine->ctx, ddc, clock_delay_div_4,
req->address, req->length, req->data);
break;
default:
result = false;
break;
}
}
/* send stop if not 'mot' or operation failed */
if (!result ||
(req->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
(req->action == DCE_I2C_TRANSACTION_ACTION_I2C_READ))
if (!stop_sync_sw(engine->ctx, ddc, clock_delay_div_4))
result = false;
req->status = result ?
I2C_CHANNEL_OPERATION_SUCCEEDED :
I2C_CHANNEL_OPERATION_FAILED;
}
static bool dce_i2c_sw_engine_submit_payload(struct dce_i2c_sw *engine,
struct i2c_payload *payload,
bool middle_of_transaction)
{
struct i2c_request_transaction_data request;
if (!payload->write)
request.action = middle_of_transaction ?
DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
DCE_I2C_TRANSACTION_ACTION_I2C_READ;
else
request.action = middle_of_transaction ?
DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
request.address = (uint8_t) ((payload->address << 1) | (payload->write ? 0 : 1));
request.length = payload->length;
request.data = payload->data;
dce_i2c_sw_engine_submit_channel_request(engine, &request);
if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
(request.status == I2C_CHANNEL_OPERATION_FAILED))
return false;
return true;
}
bool dce_i2c_submit_command_sw(
struct resource_pool *pool,
struct ddc *ddc,
struct i2c_command *cmd,
struct dce_i2c_sw *dce_i2c_sw)
{
(void)ddc;
uint8_t index_of_payload = 0;
bool result;
dce_i2c_sw_engine_set_speed(dce_i2c_sw, cmd->speed);
result = true;
while (index_of_payload < cmd->number_of_payloads) {
bool mot = (index_of_payload != cmd->number_of_payloads - 1);
struct i2c_payload *payload = cmd->payloads + index_of_payload;
if (!dce_i2c_sw_engine_submit_payload(
dce_i2c_sw, payload, mot)) {
result = false;
break;
}
++index_of_payload;
}
release_engine_dce_sw(pool, dce_i2c_sw);
return result;
}
@@ -0,0 +1,57 @@
/*
* Copyright 2018 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_I2C_SW_H__
#define __DCE_I2C_SW_H__
enum {
DCE_I2C_DEFAULT_I2C_SW_SPEED = 50,
I2C_SW_RETRIES = 10,
I2C_SW_TIMEOUT_DELAY = 3000,
};
struct dce_i2c_sw {
struct ddc *ddc;
struct dc_context *ctx;
uint32_t clock_delay;
uint32_t speed;
};
void dce_i2c_sw_construct(
struct dce_i2c_sw *dce_i2c_sw,
struct dc_context *ctx);
bool dce_i2c_submit_command_sw(
struct resource_pool *pool,
struct ddc *ddc,
struct i2c_command *cmd,
struct dce_i2c_sw *dce_i2c_sw);
bool dce_i2c_engine_acquire_sw(
struct dce_i2c_sw *dce_i2c_sw,
struct ddc *ddc_handle);
#endif
@@ -0,0 +1,312 @@
/*
* Copyright 2017 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_ipp.h"
#include "reg_helper.h"
#include "dm_services.h"
#define REG(reg) \
(ipp_dce->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
ipp_dce->ipp_shift->field_name, ipp_dce->ipp_mask->field_name
#define CTX \
ipp_dce->base.ctx
static void dce_ipp_cursor_set_position(
struct input_pixel_processor *ipp,
const struct dc_cursor_position *position,
const struct dc_cursor_mi_param *param)
{
(void)param;
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
/* lock cursor registers */
REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true);
/* Flag passed in structure differentiates cursor enable/disable. */
/* Update if it differs from cached state. */
REG_UPDATE(CUR_CONTROL, CURSOR_EN, position->enable);
REG_SET_2(CUR_POSITION, 0,
CURSOR_X_POSITION, position->x,
CURSOR_Y_POSITION, position->y);
REG_SET_2(CUR_HOT_SPOT, 0,
CURSOR_HOT_SPOT_X, position->x_hotspot,
CURSOR_HOT_SPOT_Y, position->y_hotspot);
/* unlock cursor registers */
REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false);
}
static void dce_ipp_cursor_set_attributes(
struct input_pixel_processor *ipp,
const struct dc_cursor_attributes *attributes)
{
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
int mode;
/* Lock cursor registers */
REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, true);
/* Program cursor control */
switch (attributes->color_format) {
case CURSOR_MODE_MONO:
mode = 0;
break;
case CURSOR_MODE_COLOR_1BIT_AND:
mode = 1;
break;
case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
mode = 2;
break;
case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
mode = 3;
break;
default:
BREAK_TO_DEBUGGER(); /* unsupported */
mode = 0;
}
REG_UPDATE_3(CUR_CONTROL,
CURSOR_MODE, mode,
CURSOR_2X_MAGNIFY, attributes->attribute_flags.bits.ENABLE_MAGNIFICATION,
CUR_INV_TRANS_CLAMP, attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING);
if (attributes->color_format == CURSOR_MODE_MONO) {
REG_SET_3(CUR_COLOR1, 0,
CUR_COLOR1_BLUE, 0,
CUR_COLOR1_GREEN, 0,
CUR_COLOR1_RED, 0);
REG_SET_3(CUR_COLOR2, 0,
CUR_COLOR2_BLUE, 0xff,
CUR_COLOR2_GREEN, 0xff,
CUR_COLOR2_RED, 0xff);
}
/*
* Program cursor size -- NOTE: HW spec specifies that HW register
* stores size as (height - 1, width - 1)
*/
REG_SET_2(CUR_SIZE, 0,
CURSOR_WIDTH, attributes->width-1,
CURSOR_HEIGHT, attributes->height-1);
/* Program cursor surface address */
/* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor
* surface base address in byte. It is 4K byte aligned.
* The correct way to program cursor surface address is to first write
* to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS
*/
REG_SET(CUR_SURFACE_ADDRESS_HIGH, 0,
CURSOR_SURFACE_ADDRESS_HIGH, attributes->address.high_part);
REG_SET(CUR_SURFACE_ADDRESS, 0,
CURSOR_SURFACE_ADDRESS, attributes->address.low_part);
/* Unlock Cursor registers. */
REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false);
}
static void dce_ipp_program_prescale(struct input_pixel_processor *ipp,
struct ipp_prescale_params *params)
{
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
/* set to bypass mode first before change */
REG_UPDATE(PRESCALE_GRPH_CONTROL,
GRPH_PRESCALE_BYPASS, 1);
REG_SET_2(PRESCALE_VALUES_GRPH_R, 0,
GRPH_PRESCALE_SCALE_R, params->scale,
GRPH_PRESCALE_BIAS_R, params->bias);
REG_SET_2(PRESCALE_VALUES_GRPH_G, 0,
GRPH_PRESCALE_SCALE_G, params->scale,
GRPH_PRESCALE_BIAS_G, params->bias);
REG_SET_2(PRESCALE_VALUES_GRPH_B, 0,
GRPH_PRESCALE_SCALE_B, params->scale,
GRPH_PRESCALE_BIAS_B, params->bias);
if (params->mode != IPP_PRESCALE_MODE_BYPASS) {
REG_UPDATE(PRESCALE_GRPH_CONTROL,
GRPH_PRESCALE_BYPASS, 0);
/* If prescale is in use, then legacy lut should be bypassed */
REG_UPDATE(INPUT_GAMMA_CONTROL,
GRPH_INPUT_GAMMA_MODE, 1);
}
}
static void dce_ipp_program_input_lut(
struct input_pixel_processor *ipp,
const struct dc_gamma *gamma)
{
unsigned int i;
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
/* power on LUT memory */
if (REG(DCFE_MEM_PWR_CTRL))
REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 1);
/* enable all */
REG_SET(DC_LUT_WRITE_EN_MASK, 0, DC_LUT_WRITE_EN_MASK, 0x7);
/* 256 entry mode */
REG_UPDATE(DC_LUT_RW_MODE, DC_LUT_RW_MODE, 0);
/* LUT-256, unsigned, integer, new u0.12 format */
REG_SET_3(DC_LUT_CONTROL, 0,
DC_LUT_DATA_R_FORMAT, 3,
DC_LUT_DATA_G_FORMAT, 3,
DC_LUT_DATA_B_FORMAT, 3);
/* start from index 0 */
REG_SET(DC_LUT_RW_INDEX, 0,
DC_LUT_RW_INDEX, 0);
for (i = 0; i < gamma->num_entries; i++) {
REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR,
dc_fixpt_round(
gamma->entries.red[i]));
REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR,
dc_fixpt_round(
gamma->entries.green[i]));
REG_SET(DC_LUT_SEQ_COLOR, 0, DC_LUT_SEQ_COLOR,
dc_fixpt_round(
gamma->entries.blue[i]));
}
/* power off LUT memory */
if (REG(DCFE_MEM_PWR_CTRL))
REG_SET(DCFE_MEM_PWR_CTRL, 0, DCP_LUT_MEM_PWR_DIS, 0);
/* bypass prescale, enable legacy LUT */
REG_UPDATE(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, 1);
REG_UPDATE(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, 0);
}
static void dce_ipp_set_degamma(
struct input_pixel_processor *ipp,
enum ipp_degamma_mode mode)
{
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0;
ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB);
REG_SET_3(DEGAMMA_CONTROL, 0,
GRPH_DEGAMMA_MODE, degamma_type,
CURSOR_DEGAMMA_MODE, degamma_type,
CURSOR2_DEGAMMA_MODE, degamma_type);
}
#if defined(CONFIG_DRM_AMD_DC_SI)
static void dce60_ipp_set_degamma(
struct input_pixel_processor *ipp,
enum ipp_degamma_mode mode)
{
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0;
ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB);
/* DCE6 does not have CURSOR2_DEGAMMA_MODE bit in DEGAMMA_CONTROL reg */
REG_SET_2(DEGAMMA_CONTROL, 0,
GRPH_DEGAMMA_MODE, degamma_type,
CURSOR_DEGAMMA_MODE, degamma_type);
}
#endif
static const struct ipp_funcs dce_ipp_funcs = {
.ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes,
.ipp_cursor_set_position = dce_ipp_cursor_set_position,
.ipp_program_prescale = dce_ipp_program_prescale,
.ipp_program_input_lut = dce_ipp_program_input_lut,
.ipp_set_degamma = dce_ipp_set_degamma
};
#if defined(CONFIG_DRM_AMD_DC_SI)
static const struct ipp_funcs dce60_ipp_funcs = {
.ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes,
.ipp_cursor_set_position = dce_ipp_cursor_set_position,
.ipp_program_prescale = dce_ipp_program_prescale,
.ipp_program_input_lut = dce_ipp_program_input_lut,
.ipp_set_degamma = dce60_ipp_set_degamma
};
#endif
/*****************************************/
/* Constructor, Destructor */
/*****************************************/
void dce_ipp_construct(
struct dce_ipp *ipp_dce,
struct dc_context *ctx,
int inst,
const struct dce_ipp_registers *regs,
const struct dce_ipp_shift *ipp_shift,
const struct dce_ipp_mask *ipp_mask)
{
ipp_dce->base.ctx = ctx;
ipp_dce->base.inst = inst;
ipp_dce->base.funcs = &dce_ipp_funcs;
ipp_dce->regs = regs;
ipp_dce->ipp_shift = ipp_shift;
ipp_dce->ipp_mask = ipp_mask;
}
#if defined(CONFIG_DRM_AMD_DC_SI)
void dce60_ipp_construct(
struct dce_ipp *ipp_dce,
struct dc_context *ctx,
int inst,
const struct dce_ipp_registers *regs,
const struct dce_ipp_shift *ipp_shift,
const struct dce_ipp_mask *ipp_mask)
{
ipp_dce->base.ctx = ctx;
ipp_dce->base.inst = inst;
ipp_dce->base.funcs = &dce60_ipp_funcs;
ipp_dce->regs = regs;
ipp_dce->ipp_shift = ipp_shift;
ipp_dce->ipp_mask = ipp_mask;
}
#endif
void dce_ipp_destroy(struct input_pixel_processor **ipp)
{
kfree(TO_DCE_IPP(*ipp));
*ipp = NULL;
}
@@ -0,0 +1,287 @@
/*
* Copyright 2017 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_IPP_H_
#define _DCE_IPP_H_
#include "ipp.h"
#define TO_DCE_IPP(ipp)\
container_of(ipp, struct dce_ipp, base)
#define IPP_COMMON_REG_LIST_DCE_BASE(id) \
SRI(CUR_UPDATE, DCP, id), \
SRI(CUR_CONTROL, DCP, id), \
SRI(CUR_POSITION, DCP, id), \
SRI(CUR_HOT_SPOT, DCP, id), \
SRI(CUR_COLOR1, DCP, id), \
SRI(CUR_COLOR2, DCP, id), \
SRI(CUR_SIZE, DCP, id), \
SRI(CUR_SURFACE_ADDRESS_HIGH, DCP, id), \
SRI(CUR_SURFACE_ADDRESS, DCP, id), \
SRI(PRESCALE_GRPH_CONTROL, DCP, id), \
SRI(PRESCALE_VALUES_GRPH_R, DCP, id), \
SRI(PRESCALE_VALUES_GRPH_G, DCP, id), \
SRI(PRESCALE_VALUES_GRPH_B, DCP, id), \
SRI(INPUT_GAMMA_CONTROL, DCP, id), \
SRI(DC_LUT_WRITE_EN_MASK, DCP, id), \
SRI(DC_LUT_RW_MODE, DCP, id), \
SRI(DC_LUT_CONTROL, DCP, id), \
SRI(DC_LUT_RW_INDEX, DCP, id), \
SRI(DC_LUT_SEQ_COLOR, DCP, id), \
SRI(DEGAMMA_CONTROL, DCP, id)
#define IPP_DCE100_REG_LIST_DCE_BASE(id) \
IPP_COMMON_REG_LIST_DCE_BASE(id), \
SRI(DCFE_MEM_PWR_CTRL, CRTC, id)
#define IPP_DCE110_REG_LIST_DCE_BASE(id) \
IPP_COMMON_REG_LIST_DCE_BASE(id), \
SRI(DCFE_MEM_PWR_CTRL, DCFE, id)
#define IPP_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
IPP_SF(CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \
IPP_SF(CUR_CONTROL, CURSOR_EN, mask_sh), \
IPP_SF(CUR_CONTROL, CURSOR_MODE, mask_sh), \
IPP_SF(CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \
IPP_SF(CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \
IPP_SF(CUR_POSITION, CURSOR_X_POSITION, mask_sh), \
IPP_SF(CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \
IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \
IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \
IPP_SF(CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \
IPP_SF(CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \
IPP_SF(CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \
IPP_SF(CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \
IPP_SF(CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \
IPP_SF(CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \
IPP_SF(CUR_SIZE, CURSOR_WIDTH, mask_sh), \
IPP_SF(CUR_SIZE, CURSOR_HEIGHT, mask_sh), \
IPP_SF(CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \
IPP_SF(CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \
IPP_SF(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \
IPP_SF(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \
IPP_SF(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \
IPP_SF(DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \
IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \
IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \
IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \
IPP_SF(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \
IPP_SF(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \
IPP_SF(DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \
IPP_SF(DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \
IPP_SF(DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh)
#define IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
IPP_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh)
#define IPP_DCE120_MASK_SH_LIST_SOC_BASE(mask_sh) \
IPP_SF(DCP0_CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \
IPP_SF(DCP0_CUR_CONTROL, CURSOR_EN, mask_sh), \
IPP_SF(DCP0_CUR_CONTROL, CURSOR_MODE, mask_sh), \
IPP_SF(DCP0_CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \
IPP_SF(DCP0_CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \
IPP_SF(DCP0_CUR_POSITION, CURSOR_X_POSITION, mask_sh), \
IPP_SF(DCP0_CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \
IPP_SF(DCP0_CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \
IPP_SF(DCP0_CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \
IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \
IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \
IPP_SF(DCP0_CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \
IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \
IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \
IPP_SF(DCP0_CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \
IPP_SF(DCP0_CUR_SIZE, CURSOR_WIDTH, mask_sh), \
IPP_SF(DCP0_CUR_SIZE, CURSOR_HEIGHT, mask_sh), \
IPP_SF(DCP0_CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \
IPP_SF(DCP0_CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \
IPP_SF(DCP0_PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \
IPP_SF(DCP0_PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \
IPP_SF(DCP0_PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \
IPP_SF(DCP0_PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \
IPP_SF(DCP0_PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \
IPP_SF(DCP0_PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \
IPP_SF(DCP0_PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \
IPP_SF(DCP0_INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \
IPP_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh), \
IPP_SF(DCP0_DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \
IPP_SF(DCP0_DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \
IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \
IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \
IPP_SF(DCP0_DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \
IPP_SF(DCP0_DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \
IPP_SF(DCP0_DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \
IPP_SF(DCP0_DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \
IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \
IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define IPP_DCE60_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
IPP_SF(CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \
IPP_SF(CUR_CONTROL, CURSOR_EN, mask_sh), \
IPP_SF(CUR_CONTROL, CURSOR_MODE, mask_sh), \
IPP_SF(CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \
IPP_SF(CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \
IPP_SF(CUR_POSITION, CURSOR_X_POSITION, mask_sh), \
IPP_SF(CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \
IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \
IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \
IPP_SF(CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \
IPP_SF(CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \
IPP_SF(CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \
IPP_SF(CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \
IPP_SF(CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \
IPP_SF(CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \
IPP_SF(CUR_SIZE, CURSOR_WIDTH, mask_sh), \
IPP_SF(CUR_SIZE, CURSOR_HEIGHT, mask_sh), \
IPP_SF(CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \
IPP_SF(CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \
IPP_SF(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \
IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \
IPP_SF(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \
IPP_SF(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \
IPP_SF(DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \
IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \
IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \
IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \
IPP_SF(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \
IPP_SF(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \
IPP_SF(DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \
IPP_SF(DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh)
#endif
#define IPP_REG_FIELD_LIST(type) \
type CURSOR_UPDATE_LOCK; \
type CURSOR_EN; \
type CURSOR_X_POSITION; \
type CURSOR_Y_POSITION; \
type CURSOR_HOT_SPOT_X; \
type CURSOR_HOT_SPOT_Y; \
type CURSOR_MODE; \
type CURSOR_2X_MAGNIFY; \
type CUR_INV_TRANS_CLAMP; \
type CUR_COLOR1_BLUE; \
type CUR_COLOR1_GREEN; \
type CUR_COLOR1_RED; \
type CUR_COLOR2_BLUE; \
type CUR_COLOR2_GREEN; \
type CUR_COLOR2_RED; \
type CURSOR_WIDTH; \
type CURSOR_HEIGHT; \
type CURSOR_SURFACE_ADDRESS_HIGH; \
type CURSOR_SURFACE_ADDRESS; \
type GRPH_PRESCALE_BYPASS; \
type GRPH_PRESCALE_SCALE_R; \
type GRPH_PRESCALE_BIAS_R; \
type GRPH_PRESCALE_SCALE_G; \
type GRPH_PRESCALE_BIAS_G; \
type GRPH_PRESCALE_SCALE_B; \
type GRPH_PRESCALE_BIAS_B; \
type GRPH_INPUT_GAMMA_MODE; \
type DCP_LUT_MEM_PWR_DIS; \
type DC_LUT_WRITE_EN_MASK; \
type DC_LUT_RW_MODE; \
type DC_LUT_DATA_R_FORMAT; \
type DC_LUT_DATA_G_FORMAT; \
type DC_LUT_DATA_B_FORMAT; \
type DC_LUT_RW_INDEX; \
type DC_LUT_SEQ_COLOR; \
type GRPH_DEGAMMA_MODE; \
type CURSOR_DEGAMMA_MODE; \
type CURSOR2_DEGAMMA_MODE
struct dce_ipp_shift {
IPP_REG_FIELD_LIST(uint8_t);
};
struct dce_ipp_mask {
IPP_REG_FIELD_LIST(uint32_t);
};
struct dce_ipp_registers {
uint32_t CUR_UPDATE;
uint32_t CUR_CONTROL;
uint32_t CUR_POSITION;
uint32_t CUR_HOT_SPOT;
uint32_t CUR_COLOR1;
uint32_t CUR_COLOR2;
uint32_t CUR_SIZE;
uint32_t CUR_SURFACE_ADDRESS_HIGH;
uint32_t CUR_SURFACE_ADDRESS;
uint32_t PRESCALE_GRPH_CONTROL;
uint32_t PRESCALE_VALUES_GRPH_R;
uint32_t PRESCALE_VALUES_GRPH_G;
uint32_t PRESCALE_VALUES_GRPH_B;
uint32_t INPUT_GAMMA_CONTROL;
uint32_t DCFE_MEM_PWR_CTRL;
uint32_t DC_LUT_WRITE_EN_MASK;
uint32_t DC_LUT_RW_MODE;
uint32_t DC_LUT_CONTROL;
uint32_t DC_LUT_RW_INDEX;
uint32_t DC_LUT_SEQ_COLOR;
uint32_t DEGAMMA_CONTROL;
};
struct dce_ipp {
struct input_pixel_processor base;
const struct dce_ipp_registers *regs;
const struct dce_ipp_shift *ipp_shift;
const struct dce_ipp_mask *ipp_mask;
};
void dce_ipp_construct(struct dce_ipp *ipp_dce,
struct dc_context *ctx,
int inst,
const struct dce_ipp_registers *regs,
const struct dce_ipp_shift *ipp_shift,
const struct dce_ipp_mask *ipp_mask);
#if defined(CONFIG_DRM_AMD_DC_SI)
void dce60_ipp_construct(struct dce_ipp *ipp_dce,
struct dc_context *ctx,
int inst,
const struct dce_ipp_registers *regs,
const struct dce_ipp_shift *ipp_shift,
const struct dce_ipp_mask *ipp_mask);
#endif
void dce_ipp_destroy(struct input_pixel_processor **ipp);
#endif /* _DCE_IPP_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,324 @@
/*
* 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 __DC_LINK_ENCODER__DCE110_H__
#define __DC_LINK_ENCODER__DCE110_H__
#include "link_encoder.h"
#define TO_DCE110_LINK_ENC(link_encoder)\
container_of(link_encoder, struct dce110_link_encoder, base)
/* Not found regs in dce120 spec
* BIOS_SCRATCH_2
* DP_DPHY_INTERNAL_CTRL
*/
#define AUX_REG_LIST(id)\
SRI(AUX_CONTROL, DP_AUX, id), \
SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \
SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id)
#define HPD_REG_LIST(id)\
SRI(DC_HPD_CONTROL, HPD, id)
#define LE_COMMON_REG_LIST_BASE(id) \
SR(DMCU_RAM_ACCESS_CTRL), \
SR(DMCU_IRAM_RD_CTRL), \
SR(DMCU_IRAM_RD_DATA), \
SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
SRI(DIG_BE_CNTL, DIG, id), \
SRI(DIG_BE_EN_CNTL, DIG, id), \
SRI(DP_CONFIG, DP, id), \
SRI(DP_DPHY_CNTL, DP, id), \
SRI(DP_DPHY_PRBS_CNTL, DP, id), \
SRI(DP_DPHY_SCRAM_CNTL, DP, id),\
SRI(DP_DPHY_SYM0, DP, id), \
SRI(DP_DPHY_SYM1, DP, id), \
SRI(DP_DPHY_SYM2, DP, id), \
SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \
SRI(DP_LINK_CNTL, DP, id), \
SRI(DP_LINK_FRAMING_CNTL, DP, id), \
SRI(DP_MSE_SAT0, DP, id), \
SRI(DP_MSE_SAT1, DP, id), \
SRI(DP_MSE_SAT2, DP, id), \
SRI(DP_MSE_SAT_UPDATE, DP, id), \
SRI(DP_SEC_CNTL, DP, id), \
SRI(DP_VID_STREAM_CNTL, DP, id), \
SRI(DP_DPHY_FAST_TRAINING, DP, id), \
SRI(DP_SEC_CNTL1, DP, id)
#define LE_COMMON_REG_LIST(id)\
LE_COMMON_REG_LIST_BASE(id), \
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
SR(DCI_MEM_PWR_STATUS)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define LE_DCE60_REG_LIST(id)\
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
SR(DMCU_RAM_ACCESS_CTRL), \
SR(DMCU_IRAM_RD_CTRL), \
SR(DMCU_IRAM_RD_DATA), \
SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
SRI(DIG_BE_CNTL, DIG, id), \
SRI(DIG_BE_EN_CNTL, DIG, id), \
SRI(DP_CONFIG, DP, id), \
SRI(DP_DPHY_CNTL, DP, id), \
SRI(DP_DPHY_PRBS_CNTL, DP, id), \
SRI(DP_DPHY_SYM0, DP, id), \
SRI(DP_DPHY_SYM1, DP, id), \
SRI(DP_DPHY_SYM2, DP, id), \
SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \
SRI(DP_LINK_CNTL, DP, id), \
SRI(DP_LINK_FRAMING_CNTL, DP, id), \
SRI(DP_MSE_SAT0, DP, id), \
SRI(DP_MSE_SAT1, DP, id), \
SRI(DP_MSE_SAT2, DP, id), \
SRI(DP_MSE_SAT_UPDATE, DP, id), \
SRI(DP_SEC_CNTL, DP, id), \
SRI(DP_VID_STREAM_CNTL, DP, id), \
SRI(DP_DPHY_FAST_TRAINING, DP, id), \
SRI(DP_SEC_CNTL1, DP, id)
#endif
#define LE_DCE80_REG_LIST(id)\
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
LE_COMMON_REG_LIST_BASE(id), \
SR(DAC_ENABLE)
#define LE_DCE100_REG_LIST(id)\
LE_COMMON_REG_LIST_BASE(id), \
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
SR(DCI_MEM_PWR_STATUS), \
SR(DAC_ENABLE)
#define LE_DCE110_REG_LIST(id)\
LE_COMMON_REG_LIST_BASE(id), \
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \
SR(DCI_MEM_PWR_STATUS)
#define LE_DCE120_REG_LIST(id)\
LE_COMMON_REG_LIST_BASE(id), \
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \
SR(DCI_MEM_PWR_STATUS)
struct dce110_link_enc_aux_registers {
uint32_t AUX_CONTROL;
uint32_t AUX_DPHY_RX_CONTROL0;
uint32_t AUX_DPHY_RX_CONTROL1;
};
struct dce110_link_enc_hpd_registers {
uint32_t DC_HPD_CONTROL;
};
struct dce110_link_enc_registers {
/* DMCU registers */
uint32_t MASTER_COMM_DATA_REG1;
uint32_t MASTER_COMM_DATA_REG2;
uint32_t MASTER_COMM_DATA_REG3;
uint32_t MASTER_COMM_CMD_REG;
uint32_t MASTER_COMM_CNTL_REG;
uint32_t DMCU_RAM_ACCESS_CTRL;
uint32_t DCI_MEM_PWR_STATUS;
uint32_t DMU_MEM_PWR_CNTL;
uint32_t DMCU_IRAM_RD_CTRL;
uint32_t DMCU_IRAM_RD_DATA;
uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK;
/* Common DP registers */
uint32_t DIG_BE_CNTL;
uint32_t DIG_BE_EN_CNTL;
uint32_t DP_CONFIG;
uint32_t DP_DPHY_CNTL;
uint32_t DP_DPHY_INTERNAL_CTRL;
uint32_t DP_DPHY_PRBS_CNTL;
uint32_t DP_DPHY_SCRAM_CNTL;
uint32_t DP_DPHY_SYM0;
uint32_t DP_DPHY_SYM1;
uint32_t DP_DPHY_SYM2;
uint32_t DP_DPHY_TRAINING_PATTERN_SEL;
uint32_t DP_LINK_CNTL;
uint32_t DP_LINK_FRAMING_CNTL;
uint32_t DP_MSE_SAT0;
uint32_t DP_MSE_SAT1;
uint32_t DP_MSE_SAT2;
uint32_t DP_MSE_SAT_UPDATE;
uint32_t DP_SEC_CNTL;
uint32_t DP_VID_STREAM_CNTL;
uint32_t DP_DPHY_FAST_TRAINING;
uint32_t DP_DPHY_BS_SR_SWAP_CNTL;
uint32_t DP_DPHY_HBR2_PATTERN_CONTROL;
uint32_t DP_SEC_CNTL1;
/* DAC registers */
uint32_t DAC_ENABLE;
};
struct dce110_link_encoder {
struct link_encoder base;
const struct dce110_link_enc_registers *link_regs;
const struct dce110_link_enc_aux_registers *aux_regs;
const struct dce110_link_enc_hpd_registers *hpd_regs;
};
void dce110_link_encoder_construct(
struct dce110_link_encoder *enc110,
const struct encoder_init_data *init_data,
const struct encoder_feature_support *enc_features,
const struct dce110_link_enc_registers *link_regs,
const struct dce110_link_enc_aux_registers *aux_regs,
const struct dce110_link_enc_hpd_registers *hpd_regs);
#if defined(CONFIG_DRM_AMD_DC_SI)
void dce60_link_encoder_construct(
struct dce110_link_encoder *enc110,
const struct encoder_init_data *init_data,
const struct encoder_feature_support *enc_features,
const struct dce110_link_enc_registers *link_regs,
const struct dce110_link_enc_aux_registers *aux_regs,
const struct dce110_link_enc_hpd_registers *hpd_regs);
#endif
bool dce110_link_encoder_validate_dvi_output(
const struct dce110_link_encoder *enc110,
enum signal_type connector_signal,
enum signal_type signal,
const struct dc_crtc_timing *crtc_timing);
bool dce110_link_encoder_validate_dp_output(
const struct dce110_link_encoder *enc110,
const struct dc_crtc_timing *crtc_timing);
bool dce110_link_encoder_validate_wireless_output(
const struct dce110_link_encoder *enc110,
const struct dc_crtc_timing *crtc_timing);
bool dce110_link_encoder_validate_output_with_stream(
struct link_encoder *enc,
const struct dc_stream_state *stream);
/****************** HW programming ************************/
/* initialize HW */ /* why do we initialze aux in here? */
void dce110_link_encoder_hw_init(struct link_encoder *enc);
void dce110_link_encoder_destroy(struct link_encoder **enc);
/* program DIG_MODE in DIG_BE */
/* TODO can this be combined with enable_output? */
void dce110_link_encoder_setup(
struct link_encoder *enc,
enum signal_type signal);
/* enables TMDS PHY output */
/* TODO: still need depth or just pass in adjusted pixel clock? */
void dce110_link_encoder_enable_tmds_output(
struct link_encoder *enc,
enum clock_source_id clock_source,
enum dc_color_depth color_depth,
enum signal_type signal,
uint32_t pixel_clock);
/* enables DP PHY output */
void dce110_link_encoder_enable_dp_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
enum clock_source_id clock_source);
/* enables DP PHY output in MST mode */
void dce110_link_encoder_enable_dp_mst_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
enum clock_source_id clock_source);
/* enables LVDS PHY output */
void dce110_link_encoder_enable_lvds_output(
struct link_encoder *enc,
enum clock_source_id clock_source,
uint32_t pixel_clock);
/* enables analog output from the DAC */
void dce110_link_encoder_enable_analog_output(
struct link_encoder *enc,
uint32_t pixel_clock);
/* disable PHY output */
void dce110_link_encoder_disable_output(
struct link_encoder *enc,
enum signal_type signal);
/* set DP lane settings */
void dce110_link_encoder_dp_set_lane_settings(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
void dce110_link_encoder_dp_set_phy_pattern(
struct link_encoder *enc,
const struct encoder_set_dp_phy_pattern_param *param);
/* programs DP MST VC payload allocation */
void dce110_link_encoder_update_mst_stream_allocation_table(
struct link_encoder *enc,
const struct link_mst_stream_allocation_table *table);
void dce110_link_encoder_connect_dig_be_to_fe(
struct link_encoder *enc,
enum engine_id engine,
bool connect);
unsigned int dce110_get_dig_frontend(struct link_encoder *enc);
void dce110_link_encoder_set_dp_phy_pattern_training_pattern(
struct link_encoder *enc,
uint32_t index);
void dce110_link_encoder_enable_hpd(struct link_encoder *enc);
void dce110_link_encoder_disable_hpd(struct link_encoder *enc);
void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,
bool exit_link_training_required);
void dce110_psr_program_secondary_packet(struct link_encoder *enc,
unsigned int sdp_transmit_line_num_deadline);
bool dce110_is_dig_enabled(struct link_encoder *enc);
void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings);
bool dce110_get_hpd_state(struct link_encoder *enc);
bool dce110_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
#endif /* __DC_LINK_ENCODER__DCE110_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,467 @@
/*
* Copyright 2016 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_MEM_INPUT_H__
#define __DCE_MEM_INPUT_H__
#include "dc_hw_types.h"
#include "mem_input.h"
#define TO_DCE_MEM_INPUT(mem_input)\
container_of(mem_input, struct dce_mem_input, base)
#define MI_DCE_BASE_REG_LIST(id)\
SRI(GRPH_ENABLE, DCP, id),\
SRI(GRPH_CONTROL, DCP, id),\
SRI(GRPH_X_START, DCP, id),\
SRI(GRPH_Y_START, DCP, id),\
SRI(GRPH_X_END, DCP, id),\
SRI(GRPH_Y_END, DCP, id),\
SRI(GRPH_PITCH, DCP, id),\
SRI(HW_ROTATION, DCP, id),\
SRI(GRPH_SWAP_CNTL, DCP, id),\
SRI(PRESCALE_GRPH_CONTROL, DCP, id),\
SRI(GRPH_UPDATE, DCP, id),\
SRI(GRPH_FLIP_CONTROL, DCP, id),\
SRI(GRPH_PRIMARY_SURFACE_ADDRESS, DCP, id),\
SRI(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, DCP, id),\
SRI(GRPH_SECONDARY_SURFACE_ADDRESS, DCP, id),\
SRI(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, DCP, id),\
SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\
SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\
SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\
SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\
SRI(DMIF_BUFFER_CONTROL, PIPE, id)
#define MI_DCE_PTE_REG_LIST(id)\
SRI(DVMM_PTE_CONTROL, DCP, id),\
SRI(DVMM_PTE_ARB_CONTROL, DCP, id)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define MI_DCE6_REG_LIST(id)\
SRI(GRPH_ENABLE, DCP, id),\
SRI(GRPH_CONTROL, DCP, id),\
SRI(GRPH_X_START, DCP, id),\
SRI(GRPH_Y_START, DCP, id),\
SRI(GRPH_X_END, DCP, id),\
SRI(GRPH_Y_END, DCP, id),\
SRI(GRPH_PITCH, DCP, id),\
SRI(GRPH_SWAP_CNTL, DCP, id),\
SRI(PRESCALE_GRPH_CONTROL, DCP, id),\
SRI(GRPH_UPDATE, DCP, id),\
SRI(GRPH_FLIP_CONTROL, DCP, id),\
SRI(GRPH_PRIMARY_SURFACE_ADDRESS, DCP, id),\
SRI(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, DCP, id),\
SRI(GRPH_SECONDARY_SURFACE_ADDRESS, DCP, id),\
SRI(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, DCP, id),\
SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\
SRI(DPG_PIPE_ARBITRATION_CONTROL3, DMIF_PG, id),\
SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id),\
SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\
SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\
SRI(DMIF_BUFFER_CONTROL, PIPE, id)
#endif
#define MI_DCE8_REG_LIST(id)\
MI_DCE_BASE_REG_LIST(id),\
SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id)
#define MI_DCE11_2_REG_LIST(id)\
MI_DCE8_REG_LIST(id),\
SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id)
#define MI_DCE11_REG_LIST(id)\
MI_DCE11_2_REG_LIST(id),\
MI_DCE_PTE_REG_LIST(id)
#define MI_DCE12_REG_LIST(id)\
MI_DCE_BASE_REG_LIST(id),\
MI_DCE_PTE_REG_LIST(id),\
SRI(GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, DCP, id),\
SRI(DPG_PIPE_STUTTER_CONTROL2, DMIF_PG, id),\
SRI(DPG_PIPE_LOW_POWER_CONTROL, DMIF_PG, id),\
SR(DCHUB_FB_LOCATION),\
SR(DCHUB_AGP_BASE),\
SR(DCHUB_AGP_BOT),\
SR(DCHUB_AGP_TOP)
struct dce_mem_input_registers {
/* DCP */
uint32_t GRPH_ENABLE;
uint32_t GRPH_CONTROL;
uint32_t GRPH_X_START;
uint32_t GRPH_Y_START;
uint32_t GRPH_X_END;
uint32_t GRPH_Y_END;
uint32_t GRPH_PITCH;
uint32_t HW_ROTATION;
uint32_t GRPH_SWAP_CNTL;
uint32_t PRESCALE_GRPH_CONTROL;
uint32_t GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT;
uint32_t DVMM_PTE_CONTROL;
uint32_t DVMM_PTE_ARB_CONTROL;
uint32_t GRPH_UPDATE;
uint32_t GRPH_FLIP_CONTROL;
uint32_t GRPH_PRIMARY_SURFACE_ADDRESS;
uint32_t GRPH_PRIMARY_SURFACE_ADDRESS_HIGH;
uint32_t GRPH_SECONDARY_SURFACE_ADDRESS;
uint32_t GRPH_SECONDARY_SURFACE_ADDRESS_HIGH;
/* DMIF_PG */
uint32_t DPG_PIPE_ARBITRATION_CONTROL1;
#if defined(CONFIG_DRM_AMD_DC_SI)
uint32_t DPG_PIPE_ARBITRATION_CONTROL3;
#endif
uint32_t DPG_WATERMARK_MASK_CONTROL;
uint32_t DPG_PIPE_URGENCY_CONTROL;
uint32_t DPG_PIPE_URGENT_LEVEL_CONTROL;
uint32_t DPG_PIPE_NB_PSTATE_CHANGE_CONTROL;
uint32_t DPG_PIPE_LOW_POWER_CONTROL;
uint32_t DPG_PIPE_STUTTER_CONTROL;
uint32_t DPG_PIPE_STUTTER_CONTROL2;
/* DCI */
uint32_t DMIF_BUFFER_CONTROL;
/* MC_HUB */
uint32_t MC_HUB_RDREQ_DMIF_LIMIT;
/*DCHUB*/
uint32_t DCHUB_FB_LOCATION;
uint32_t DCHUB_AGP_BASE;
uint32_t DCHUB_AGP_BOT;
uint32_t DCHUB_AGP_TOP;
};
/* Set_Filed_for_Block */
#define SFB(blk_name, reg_name, field_name, post_fix)\
.field_name = blk_name ## reg_name ## __ ## field_name ## post_fix
#if defined(CONFIG_DRM_AMD_DC_SI)
#define MI_GFX6_TILE_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_BANK_WIDTH, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_PIPE_CONFIG, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_ARRAY_MODE, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh)
#endif
#define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_BANK_WIDTH, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_MICRO_TILE_MODE, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_PIPE_CONFIG, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_ARRAY_MODE, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh)
#define MI_DCP_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\
SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\
SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\
SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\
SFB(blk, GRPH_Y_END, GRPH_Y_END, mask_sh),\
SFB(blk, GRPH_PITCH, GRPH_PITCH, mask_sh),\
SFB(blk, HW_ROTATION, GRPH_ROTATION_ANGLE, mask_sh),\
SFB(blk, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR, mask_sh),\
SFB(blk, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh),\
SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\
SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_SURFACE_ADDRESS, mask_sh),\
SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\
SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS, GRPH_PRIMARY_SURFACE_ADDRESS, mask_sh),\
SFB(blk, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, mask_sh),\
SFB(blk, GRPH_UPDATE, GRPH_UPDATE_LOCK, mask_sh),\
SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define MI_DCP_MASK_SH_LIST_DCE6(mask_sh, blk)\
SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\
SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\
SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\
SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\
SFB(blk, GRPH_Y_END, GRPH_Y_END, mask_sh),\
SFB(blk, GRPH_PITCH, GRPH_PITCH, mask_sh),\
SFB(blk, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR, mask_sh),\
SFB(blk, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh),\
SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\
SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_SURFACE_ADDRESS, mask_sh),\
SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\
SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS, GRPH_PRIMARY_SURFACE_ADDRESS, mask_sh),\
SFB(blk, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, mask_sh),\
SFB(blk, GRPH_UPDATE, GRPH_UPDATE_LOCK, mask_sh),\
SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh)
#endif
#define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh)
#define MI_DCP_PTE_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, DVMM_PTE_CONTROL, DVMM_PAGE_WIDTH, mask_sh),\
SFB(blk, DVMM_PTE_CONTROL, DVMM_PAGE_HEIGHT, mask_sh),\
SFB(blk, DVMM_PTE_CONTROL, DVMM_MIN_PTE_BEFORE_FLIP, mask_sh),\
SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK, mask_sh),\
SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define MI_DMIF_PG_MASK_SH_LIST_DCE6(mask_sh, blk)\
SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\
SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\
SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh)
#define MI_DMIF_PG_MASK_SH_DCE6(mask_sh, blk)\
SFB(blk, DPG_PIPE_ARBITRATION_CONTROL3, URGENCY_WATERMARK_MASK, mask_sh),\
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh)
#define MI_DCE6_MASK_SH_LIST(mask_sh)\
MI_DCP_MASK_SH_LIST_DCE6(mask_sh, ),\
MI_DMIF_PG_MASK_SH_LIST_DCE6(mask_sh, ),\
MI_DMIF_PG_MASK_SH_DCE6(mask_sh, ),\
MI_GFX6_TILE_MASK_SH_LIST(mask_sh, )
#endif
#define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\
SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\
SFB(blk, DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\
SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\
SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh)
#define MI_DMIF_PG_MASK_SH_DCE(mask_sh, blk)\
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\
SFB(blk, DPG_WATERMARK_MASK_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh)
#define MI_DCE8_MASK_SH_LIST(mask_sh)\
MI_DCP_MASK_SH_LIST(mask_sh, ),\
MI_DMIF_PG_MASK_SH_LIST(mask_sh, ),\
MI_DMIF_PG_MASK_SH_DCE(mask_sh, ),\
MI_GFX8_TILE_MASK_SH_LIST(mask_sh, )
#define MI_DCE11_2_MASK_SH_LIST(mask_sh)\
MI_DCE8_MASK_SH_LIST(mask_sh),\
MI_DCP_DCE11_MASK_SH_LIST(mask_sh, )
#define MI_DCE11_MASK_SH_LIST(mask_sh)\
MI_DCE11_2_MASK_SH_LIST(mask_sh),\
MI_DCP_PTE_MASK_SH_LIST(mask_sh, )
#define MI_GFX9_TILE_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_SW_MODE, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_SE_ENABLE, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_NUM_SHADER_ENGINES, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_NUM_PIPES, mask_sh),\
SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh)
#define MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\
SFB(blk, DPG_PIPE_STUTTER_CONTROL2, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_STUTTER_CONTROL2, STUTTER_ENTER_SELF_REFRESH_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_URGENT_LEVEL_CONTROL, URGENT_LEVEL_LOW_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_URGENT_LEVEL_CONTROL, URGENT_LEVEL_HIGH_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\
SFB(blk, DPG_WATERMARK_MASK_CONTROL, PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\
SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_ENABLE, mask_sh),\
SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\
SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\
SFB(blk, DPG_PIPE_LOW_POWER_CONTROL, PSTATE_CHANGE_WATERMARK, mask_sh)
#define MI_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\
SF(DCHUB_FB_LOCATION, FB_TOP, mask_sh),\
SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\
SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\
SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\
SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh)
#define MI_DCE12_MASK_SH_LIST(mask_sh)\
MI_DCP_MASK_SH_LIST(mask_sh, DCP0_),\
SF(DCP0_GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_DFQ_ENABLE, mask_sh),\
MI_DCP_DCE11_MASK_SH_LIST(mask_sh, DCP0_),\
MI_DCP_PTE_MASK_SH_LIST(mask_sh, DCP0_),\
MI_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\
MI_DCE12_DMIF_PG_MASK_SH_LIST(mask_sh, DMIF_PG0_),\
MI_GFX9_TILE_MASK_SH_LIST(mask_sh, DCP0_),\
MI_GFX9_DCHUB_MASK_SH_LIST(mask_sh)
#define MI_REG_FIELD_LIST(type) \
type GRPH_ENABLE; \
type GRPH_X_START; \
type GRPH_Y_START; \
type GRPH_X_END; \
type GRPH_Y_END; \
type GRPH_PITCH; \
type GRPH_ROTATION_ANGLE; \
type GRPH_RED_CROSSBAR; \
type GRPH_BLUE_CROSSBAR; \
type GRPH_PRESCALE_SELECT; \
type GRPH_PRESCALE_R_SIGN; \
type GRPH_PRESCALE_G_SIGN; \
type GRPH_PRESCALE_B_SIGN; \
type GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT; \
type DVMM_PAGE_WIDTH; \
type DVMM_PAGE_HEIGHT; \
type DVMM_MIN_PTE_BEFORE_FLIP; \
type DVMM_PTE_REQ_PER_CHUNK; \
type DVMM_MAX_PTE_REQ_OUTSTANDING; \
type GRPH_DEPTH; \
type GRPH_FORMAT; \
type GRPH_NUM_BANKS; \
type GRPH_BANK_WIDTH;\
type GRPH_BANK_HEIGHT;\
type GRPH_MACRO_TILE_ASPECT;\
type GRPH_TILE_SPLIT;\
type GRPH_MICRO_TILE_MODE;\
type GRPH_PIPE_CONFIG;\
type GRPH_ARRAY_MODE;\
type GRPH_COLOR_EXPANSION_MODE;\
type GRPH_SW_MODE; \
type GRPH_SE_ENABLE; \
type GRPH_NUM_SHADER_ENGINES; \
type GRPH_NUM_PIPES; \
type GRPH_SECONDARY_SURFACE_ADDRESS_HIGH; \
type GRPH_SECONDARY_SURFACE_ADDRESS; \
type GRPH_SECONDARY_DFQ_ENABLE; \
type GRPH_PRIMARY_SURFACE_ADDRESS_HIGH; \
type GRPH_PRIMARY_SURFACE_ADDRESS; \
type GRPH_SURFACE_UPDATE_PENDING; \
type GRPH_SURFACE_UPDATE_H_RETRACE_EN; \
type GRPH_UPDATE_LOCK; \
type PIXEL_DURATION; \
type URGENCY_WATERMARK_MASK; \
type PSTATE_CHANGE_WATERMARK_MASK; \
type NB_PSTATE_CHANGE_WATERMARK_MASK; \
type STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK; \
type URGENCY_LOW_WATERMARK; \
type URGENCY_HIGH_WATERMARK; \
type URGENT_LEVEL_LOW_WATERMARK;\
type URGENT_LEVEL_HIGH_WATERMARK;\
type NB_PSTATE_CHANGE_ENABLE; \
type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST; \
type NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \
type NB_PSTATE_CHANGE_WATERMARK; \
type PSTATE_CHANGE_ENABLE; \
type PSTATE_CHANGE_URGENT_DURING_REQUEST; \
type PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \
type PSTATE_CHANGE_WATERMARK; \
type STUTTER_ENABLE; \
type STUTTER_IGNORE_FBC; \
type STUTTER_EXIT_SELF_REFRESH_WATERMARK; \
type STUTTER_ENTER_SELF_REFRESH_WATERMARK; \
type DMIF_BUFFERS_ALLOCATED; \
type DMIF_BUFFERS_ALLOCATION_COMPLETED; \
type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\
type FB_BASE; \
type FB_TOP; \
type AGP_BASE; \
type AGP_TOP; \
type AGP_BOT; \
struct dce_mem_input_shift {
MI_REG_FIELD_LIST(uint8_t)
};
struct dce_mem_input_mask {
MI_REG_FIELD_LIST(uint32_t)
};
struct dce_mem_input_wa {
uint8_t single_head_rdreq_dmif_limit;
};
struct dce_mem_input {
struct mem_input base;
const struct dce_mem_input_registers *regs;
const struct dce_mem_input_shift *shifts;
const struct dce_mem_input_mask *masks;
struct dce_mem_input_wa wa;
};
void dce_mem_input_construct(
struct dce_mem_input *dce_mi,
struct dc_context *ctx,
int inst,
const struct dce_mem_input_registers *regs,
const struct dce_mem_input_shift *mi_shift,
const struct dce_mem_input_mask *mi_mask);
#if defined(CONFIG_DRM_AMD_DC_SI)
void dce60_mem_input_construct(
struct dce_mem_input *dce_mi,
struct dc_context *ctx,
int inst,
const struct dce_mem_input_registers *regs,
const struct dce_mem_input_shift *mi_shift,
const struct dce_mem_input_mask *mi_mask);
#endif
void dce112_mem_input_construct(
struct dce_mem_input *dce_mi,
struct dc_context *ctx,
int inst,
const struct dce_mem_input_registers *regs,
const struct dce_mem_input_shift *mi_shift,
const struct dce_mem_input_mask *mi_mask);
void dce120_mem_input_construct(
struct dce_mem_input *dce_mi,
struct dc_context *ctx,
int inst,
const struct dce_mem_input_registers *regs,
const struct dce_mem_input_shift *mi_shift,
const struct dce_mem_input_mask *mi_mask);
#endif /*__DCE_MEM_INPUT_H__*/
@@ -0,0 +1,769 @@
/*
* 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 "dm_services.h"
#include "basics/conversion.h"
#include "dce_opp.h"
#include "reg_helper.h"
#define REG(reg)\
(opp110->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
opp110->opp_shift->field_name, opp110->opp_mask->field_name
#define CTX \
opp110->base.ctx
enum {
MAX_PWL_ENTRY = 128,
MAX_REGIONS_NUMBER = 16
};
enum {
MAX_LUT_ENTRY = 256,
MAX_NUMBER_OF_ENTRIES = 256
};
enum {
OUTPUT_CSC_MATRIX_SIZE = 12
};
/*
*****************************************************************************
* Function: regamma_config_regions_and_segments
*
* build regamma curve by using predefined hw points
* uses interface parameters ,like EDID coeff.
*
* @param : parameters interface parameters
* @return void
*
* @note
*
* @see
*
*****************************************************************************
*/
/*
* set_truncation
* 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
* 2) enable truncation
* 3) HW remove 12bit FMT support for DCE11 power saving reason.
*/
static void set_truncation(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
/*Disable truncation*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 0,
FMT_TRUNCATE_DEPTH, 0,
FMT_TRUNCATE_MODE, 0);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
/* 8bpc trunc on YCbCr422*/
if (params->flags.TRUNCATE_DEPTH == 1)
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH, 1,
FMT_TRUNCATE_MODE, 0);
else if (params->flags.TRUNCATE_DEPTH == 2)
/* 10bpc trunc on YCbCr422*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH, 2,
FMT_TRUNCATE_MODE, 0);
return;
}
/* on other format-to do */
if (params->flags.TRUNCATE_ENABLED == 0)
return;
/*Set truncation depth and Enable truncation*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH,
params->flags.TRUNCATE_DEPTH,
FMT_TRUNCATE_MODE,
params->flags.TRUNCATE_MODE);
}
#if defined(CONFIG_DRM_AMD_DC_SI)
/*
* dce60_set_truncation
* 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
* 2) enable truncation
* 3) HW remove 12bit FMT support for DCE11 power saving reason.
*/
static void dce60_set_truncation(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
/* DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL reg */
/*Disable truncation*/
REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 0,
FMT_TRUNCATE_DEPTH, 0);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
/* 8bpc trunc on YCbCr422*/
if (params->flags.TRUNCATE_DEPTH == 1)
REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH, 1);
else if (params->flags.TRUNCATE_DEPTH == 2)
/* 10bpc trunc on YCbCr422*/
REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH, 2);
return;
}
/* on other format-to do */
if (params->flags.TRUNCATE_ENABLED == 0)
return;
/*Set truncation depth and Enable truncation*/
REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
FMT_TRUNCATE_EN, 1,
FMT_TRUNCATE_DEPTH,
params->flags.TRUNCATE_DEPTH);
}
#endif
/*
* set_spatial_dither
* 1) set spatial dithering mode: pattern of seed
* 2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp
* 3) set random seed
* 4) set random mode
* lfsr is reset every frame or not reset
* RGB dithering method
* 0: RGB data are all dithered with x^28+x^3+1
* 1: R data is dithered with x^28+x^3+1
* G data is dithered with x^28+X^9+1
* B data is dithered with x^28+x^13+1
* enable high pass filter or not
* 5) enable spatical dithering
*/
static void set_spatial_dither(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
/*Disable spatial (random) dithering*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_EN, 0,
FMT_SPATIAL_DITHER_DEPTH, 0,
FMT_SPATIAL_DITHER_MODE, 0);
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_HIGHPASS_RANDOM_ENABLE, 0,
FMT_FRAME_RANDOM_ENABLE, 0,
FMT_RGB_RANDOM_ENABLE, 0);
REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN, 0);
if (params->flags.SPATIAL_DITHER_ENABLED == 0)
return;
/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
if (params->flags.FRAME_RANDOM == 1) {
if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
params->flags.SPATIAL_DITHER_DEPTH == 1) {
REG_UPDATE_2(FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
} else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
REG_UPDATE_2(FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
} else
return;
} else {
REG_UPDATE_2(FMT_CONTROL,
FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
}
}
/* Set seed for random values for
* spatial dithering for R,G,B channels
*/
REG_UPDATE(FMT_DITHER_RAND_R_SEED,
FMT_RAND_R_SEED, params->r_seed_value);
REG_UPDATE(FMT_DITHER_RAND_G_SEED,
FMT_RAND_G_SEED, params->g_seed_value);
REG_UPDATE(FMT_DITHER_RAND_B_SEED,
FMT_RAND_B_SEED, params->b_seed_value);
/* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
* offset for the R/Cr channel, lower 4LSB
* is forced to zeros. Typically set to 0
* RGB and 0x80000 YCbCr.
*/
/* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
* offset for the G/Y channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB
* and 0x80000 YCbCr.
*/
/* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
* offset for the B/Cb channel, lower 4LSB is
* forced to zeros. Typically set to 0 RGB and
* 0x80000 YCbCr.
*/
/* Disable High pass filter
* Reset only at startup
* Set RGB data dithered with x^28+x^3+1
*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
/* Set spatial dithering bit depth
* Set spatial dithering mode
* (default is Seed patterrn AAAA...)
* Enable spatial dithering
*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
FMT_SPATIAL_DITHER_EN, 1);
}
/*
* SetTemporalDither (Frame Modulation)
* 1) set temporal dither depth
* 2) select pattern: from hard-coded pattern or programmable pattern
* 3) select optimized strips for BGR or RGB LCD sub-pixel
* 4) set s matrix
* 5) set t matrix
* 6) set grey level for 0.25, 0.5, 0.75
* 7) enable temporal dithering
*/
static void set_temporal_dither(
struct dce110_opp *opp110,
const struct bit_depth_reduction_params *params)
{
/*Disable temporal (frame modulation) dithering first*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN, 0,
FMT_TEMPORAL_DITHER_RESET, 0,
FMT_TEMPORAL_DITHER_OFFSET, 0);
REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH, 0,
FMT_TEMPORAL_LEVEL, 0);
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL, 0,
FMT_50FRC_SEL, 0,
FMT_75FRC_SEL, 0);
/* no 10bpc dither on DCE11*/
if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
params->flags.FRAME_MODULATION_DEPTH == 2)
return;
/* Set temporal dithering depth*/
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
FMT_TEMPORAL_DITHER_RESET, 0,
FMT_TEMPORAL_DITHER_OFFSET, 0);
/*Select legacy pattern based on FRC and Temporal level*/
if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
/*Set s matrix*/
REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
/*Set t matrix*/
REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
}
/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
FMT_25FRC_SEL, params->flags.FRC25,
FMT_50FRC_SEL, params->flags.FRC50,
FMT_75FRC_SEL, params->flags.FRC75);
/*Enable bit reduction by temporal (frame modulation) dithering*/
REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
FMT_TEMPORAL_DITHER_EN, 1);
}
/*
* Set Clamping
* 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
* 1 for 8 bpc
* 2 for 10 bpc
* 3 for 12 bpc
* 7 for programable
* 2) Enable clamp if Limited range requested
*/
void dce110_opp_set_clamping(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 0,
FMT_CLAMP_COLOR_FORMAT, 0);
switch (params->clamping_level) {
case CLAMPING_FULL_RANGE:
break;
case CLAMPING_LIMITED_RANGE_8BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 1);
break;
case CLAMPING_LIMITED_RANGE_10BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 2);
break;
case CLAMPING_LIMITED_RANGE_12BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 3);
break;
case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
/*Set clamp control*/
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 7);
/*set the defaults*/
REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
FMT_CLAMP_LOWER_R, 0x10,
FMT_CLAMP_UPPER_R, 0xFEF);
REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
FMT_CLAMP_LOWER_G, 0x10,
FMT_CLAMP_UPPER_G, 0xFEF);
REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
FMT_CLAMP_LOWER_B, 0x10,
FMT_CLAMP_UPPER_B, 0xFEF);
break;
default:
break;
}
}
#if defined(CONFIG_DRM_AMD_DC_SI)
/*
* Set Clamping for DCE6 parts
* 1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
* 1 for 8 bpc
* 2 for 10 bpc
* 3 for 12 bpc
* 7 for programable
* 2) Enable clamp if Limited range requested
*/
static void dce60_opp_set_clamping(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 0,
FMT_CLAMP_COLOR_FORMAT, 0);
switch (params->clamping_level) {
case CLAMPING_FULL_RANGE:
break;
case CLAMPING_LIMITED_RANGE_8BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 1);
break;
case CLAMPING_LIMITED_RANGE_10BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 2);
break;
case CLAMPING_LIMITED_RANGE_12BPC:
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 3);
break;
case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
/*Set clamp control*/
REG_SET_2(FMT_CLAMP_CNTL, 0,
FMT_CLAMP_DATA_EN, 1,
FMT_CLAMP_COLOR_FORMAT, 7);
/* DCE6 does have FMT_CLAMP_COMPONENT_{R,G,B} registers */
break;
default:
break;
}
}
#endif
/*
* set_pixel_encoding
*
* Set Pixel Encoding
* 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
* 1: YCbCr 4:2:2
*/
static void set_pixel_encoding(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
REG_UPDATE_3(FMT_CONTROL,
FMT_PIXEL_ENCODING, 0,
FMT_SUBSAMPLING_MODE, 0,
FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
else
REG_UPDATE_2(FMT_CONTROL,
FMT_PIXEL_ENCODING, 0,
FMT_SUBSAMPLING_MODE, 0);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
REG_UPDATE_2(FMT_CONTROL,
FMT_PIXEL_ENCODING, 1,
FMT_SUBSAMPLING_ORDER, 0);
}
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
REG_UPDATE_3(FMT_CONTROL,
FMT_PIXEL_ENCODING, 2,
FMT_SUBSAMPLING_MODE, 2,
FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
}
}
#if defined(CONFIG_DRM_AMD_DC_SI)
/*
* dce60_set_pixel_encoding
* DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL reg
* Set Pixel Encoding
* 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
* 1: YCbCr 4:2:2
*/
static void dce60_set_pixel_encoding(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params)
{
if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
REG_UPDATE_2(FMT_CONTROL,
FMT_PIXEL_ENCODING, 0,
FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
else
REG_UPDATE(FMT_CONTROL,
FMT_PIXEL_ENCODING, 0);
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
REG_UPDATE(FMT_CONTROL,
FMT_PIXEL_ENCODING, 1);
}
if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
REG_UPDATE_2(FMT_CONTROL,
FMT_PIXEL_ENCODING, 2,
FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
}
}
#endif
void dce110_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
set_truncation(opp110, params);
set_spatial_dither(opp110, params);
set_temporal_dither(opp110, params);
}
#if defined(CONFIG_DRM_AMD_DC_SI)
static void dce60_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
dce60_set_truncation(opp110, params);
set_spatial_dither(opp110, params);
set_temporal_dither(opp110, params);
}
#endif
void dce110_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
dce110_opp_set_clamping(opp110, params);
set_pixel_encoding(opp110, params);
}
#if defined(CONFIG_DRM_AMD_DC_SI)
static void dce60_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
dce60_opp_set_clamping(opp110, params);
dce60_set_pixel_encoding(opp110, params);
}
#endif
static void program_formatter_420_memory(struct output_pixel_processor *opp)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
uint32_t fmt_mem_cntl_value;
/* Program source select*/
/* Use HW default source select for FMT_MEMORYx_CONTROL */
/* Use that value for FMT_SRC_SELECT as well*/
REG_GET(CONTROL,
FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
REG_UPDATE(FMT_CONTROL,
FMT_SRC_SELECT, fmt_mem_cntl_value);
/* Turn on the memory */
REG_UPDATE(CONTROL,
FMT420_MEM0_PWR_FORCE, 0);
}
void dce110_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal)
{
(void)color_sp;
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
FMT_DYNAMIC_EXP_EN, 0,
FMT_DYNAMIC_EXP_MODE, 0);
/*00 - 10-bit -> 12-bit dynamic expansion*/
/*01 - 8-bit -> 12-bit dynamic expansion*/
if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
signal == SIGNAL_TYPE_DISPLAY_PORT ||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
switch (color_dpth) {
case COLOR_DEPTH_888:
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
FMT_DYNAMIC_EXP_EN, 1,
FMT_DYNAMIC_EXP_MODE, 1);
break;
case COLOR_DEPTH_101010:
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
FMT_DYNAMIC_EXP_EN, 1,
FMT_DYNAMIC_EXP_MODE, 0);
break;
case COLOR_DEPTH_121212:
REG_UPDATE_2(
FMT_DYNAMIC_EXP_CNTL,
FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
FMT_DYNAMIC_EXP_MODE, 0);
break;
default:
break;
}
}
}
static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
{
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
/* clear previous phase lock status*/
REG_UPDATE(FMT_CONTROL,
FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
/* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
}
void dce110_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping)
{
/* dithering is affected by <CrtcSourceSelect>, hence should be
* programmed afterwards */
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_420_memory(opp);
dce110_opp_program_bit_depth_reduction(
opp,
fmt_bit_depth);
dce110_opp_program_clamping_and_pixel_encoding(
opp,
clamping);
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_reset_dig_resync_fifo(opp);
return;
}
#if defined(CONFIG_DRM_AMD_DC_SI)
static void dce60_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping)
{
/* dithering is affected by <CrtcSourceSelect>, hence should be
* programmed afterwards */
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_420_memory(opp);
dce60_opp_program_bit_depth_reduction(
opp,
fmt_bit_depth);
dce60_opp_program_clamping_and_pixel_encoding(
opp,
clamping);
if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
program_formatter_reset_dig_resync_fifo(opp);
return;
}
#endif
/*****************************************/
/* Constructor, Destructor */
/*****************************************/
static const struct opp_funcs funcs = {
.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
.opp_destroy = dce110_opp_destroy,
.opp_program_fmt = dce110_opp_program_fmt,
.opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
};
#if defined(CONFIG_DRM_AMD_DC_SI)
static const struct opp_funcs dce60_opp_funcs = {
.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
.opp_destroy = dce110_opp_destroy,
.opp_program_fmt = dce60_opp_program_fmt,
.opp_program_bit_depth_reduction = dce60_opp_program_bit_depth_reduction
};
#endif
void dce110_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce_opp_registers *regs,
const struct dce_opp_shift *opp_shift,
const struct dce_opp_mask *opp_mask)
{
opp110->base.funcs = &funcs;
opp110->base.ctx = ctx;
opp110->base.inst = inst;
opp110->regs = regs;
opp110->opp_shift = opp_shift;
opp110->opp_mask = opp_mask;
}
#if defined(CONFIG_DRM_AMD_DC_SI)
void dce60_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce_opp_registers *regs,
const struct dce_opp_shift *opp_shift,
const struct dce_opp_mask *opp_mask)
{
opp110->base.funcs = &dce60_opp_funcs;
opp110->base.ctx = ctx;
opp110->base.inst = inst;
opp110->regs = regs;
opp110->opp_shift = opp_shift;
opp110->opp_mask = opp_mask;
}
#endif
void dce110_opp_destroy(struct output_pixel_processor **opp)
{
if (*opp)
kfree(FROM_DCE11_OPP(*opp));
*opp = NULL;
}
@@ -0,0 +1,358 @@
/* 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 __DC_OPP_DCE_H__
#define __DC_OPP_DCE_H__
#include "dc_types.h"
#include "opp.h"
#include "core_types.h"
#define FROM_DCE11_OPP(opp)\
container_of(opp, struct dce110_opp, base)
enum dce110_opp_reg_type {
DCE110_OPP_REG_DCP = 0,
DCE110_OPP_REG_DCFE,
DCE110_OPP_REG_FMT,
DCE110_OPP_REG_MAX
};
#define OPP_COMMON_REG_LIST_BASE(id) \
SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \
SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \
SRI(FMT_CONTROL, FMT, id), \
SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \
SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \
SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \
SRI(FMT_CLAMP_CNTL, FMT, id), \
SRI(FMT_CLAMP_COMPONENT_R, FMT, id), \
SRI(FMT_CLAMP_COMPONENT_G, FMT, id), \
SRI(FMT_CLAMP_COMPONENT_B, FMT, id)
#define OPP_DCE_80_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id)
#define OPP_DCE_100_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id)
#define OPP_DCE_110_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id)
#define OPP_DCE_112_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, FMT, id), \
SRI(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, FMT, id), \
SRI(CONTROL, FMT_MEMORY, id)
#define OPP_DCE_120_REG_LIST(id) \
OPP_COMMON_REG_LIST_BASE(id), \
SRI(CONTROL, FMT_MEMORY, id)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define OPP_DCE_60_REG_LIST(id) \
SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \
SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \
SRI(FMT_CONTROL, FMT, id), \
SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \
SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \
SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \
SRI(FMT_CLAMP_CNTL, FMT, id)
#endif
#define OPP_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\
OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\
OPP_SF(FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\
OPP_SF(FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SRC_SELECT, mask_sh),\
OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\
OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_LOWER_R, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_R, FMT_CLAMP_UPPER_R, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_LOWER_G, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_G, FMT_CLAMP_UPPER_G, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_LOWER_B, mask_sh),\
OPP_SF(FMT_CLAMP_COMPONENT_B, FMT_CLAMP_UPPER_B, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_110(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_100(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh),\
OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\
OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_80(mask_sh)\
OPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)
#define OPP_COMMON_MASK_SH_LIST_DCE_120(mask_sh)\
OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\
OPP_SF(FMT0_FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT0_FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh),\
OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\
OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\
OPP_SF(FMT0_FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\
OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_SOURCE_SEL, mask_sh),\
OPP_SF(FMT_MEMORY0_CONTROL, FMT420_MEM0_PWR_FORCE, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_SRC_SELECT, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED_CLEAR, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_COMPONENT_R, FMT_CLAMP_LOWER_R, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_COMPONENT_R, FMT_CLAMP_UPPER_R, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_COMPONENT_G, FMT_CLAMP_LOWER_G, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_COMPONENT_G, FMT_CLAMP_UPPER_G, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_COMPONENT_B, FMT_CLAMP_LOWER_B, mask_sh),\
OPP_SF(FMT0_FMT_CLAMP_COMPONENT_B, FMT_CLAMP_UPPER_B, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh),\
OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define OPP_COMMON_MASK_SH_LIST_DCE_60(mask_sh)\
OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\
OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\
OPP_SF(FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\
OPP_SF(FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\
OPP_SF(FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\
OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\
OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\
OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\
OPP_SF(FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh)
#endif
#define OPP_REG_FIELD_LIST(type) \
type FMT_DYNAMIC_EXP_EN; \
type FMT_DYNAMIC_EXP_MODE; \
type FMT_TRUNCATE_EN; \
type FMT_TRUNCATE_DEPTH; \
type FMT_TRUNCATE_MODE; \
type FMT_SPATIAL_DITHER_EN; \
type FMT_SPATIAL_DITHER_DEPTH; \
type FMT_SPATIAL_DITHER_MODE; \
type FMT_TEMPORAL_DITHER_EN; \
type FMT_TEMPORAL_DITHER_RESET; \
type FMT_TEMPORAL_DITHER_OFFSET; \
type FMT_TEMPORAL_DITHER_DEPTH; \
type FMT_TEMPORAL_LEVEL; \
type FMT_25FRC_SEL; \
type FMT_50FRC_SEL; \
type FMT_75FRC_SEL; \
type FMT_HIGHPASS_RANDOM_ENABLE; \
type FMT_FRAME_RANDOM_ENABLE; \
type FMT_RGB_RANDOM_ENABLE; \
type FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX; \
type FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP; \
type FMT_STEREOSYNC_OVERRIDE; \
type FMT_RAND_R_SEED; \
type FMT_RAND_G_SEED; \
type FMT_RAND_B_SEED; \
type FMT420_MEM0_SOURCE_SEL; \
type FMT420_MEM0_PWR_FORCE; \
type FMT_SRC_SELECT; \
type FMT_420_PIXEL_PHASE_LOCKED_CLEAR; \
type FMT_420_PIXEL_PHASE_LOCKED; \
type FMT_CLAMP_DATA_EN; \
type FMT_CLAMP_COLOR_FORMAT; \
type FMT_CLAMP_LOWER_R; \
type FMT_CLAMP_UPPER_R; \
type FMT_CLAMP_LOWER_G; \
type FMT_CLAMP_UPPER_G; \
type FMT_CLAMP_LOWER_B; \
type FMT_CLAMP_UPPER_B; \
type FMT_PIXEL_ENCODING; \
type FMT_SUBSAMPLING_ORDER; \
type FMT_SUBSAMPLING_MODE; \
type FMT_CBCR_BIT_REDUCTION_BYPASS;\
struct dce_opp_shift {
OPP_REG_FIELD_LIST(uint8_t)
};
struct dce_opp_mask {
OPP_REG_FIELD_LIST(uint32_t)
};
struct dce_opp_registers {
uint32_t FMT_DYNAMIC_EXP_CNTL;
uint32_t FMT_BIT_DEPTH_CONTROL;
uint32_t FMT_CONTROL;
uint32_t FMT_DITHER_RAND_R_SEED;
uint32_t FMT_DITHER_RAND_G_SEED;
uint32_t FMT_DITHER_RAND_B_SEED;
uint32_t FMT_TEMPORAL_DITHER_PATTERN_CONTROL;
uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX;
uint32_t FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX;
uint32_t CONTROL;
uint32_t FMT_CLAMP_CNTL;
uint32_t FMT_CLAMP_COMPONENT_R;
uint32_t FMT_CLAMP_COMPONENT_G;
uint32_t FMT_CLAMP_COMPONENT_B;
};
/* OPP RELATED */
#define TO_DCE110_OPP(opp)\
container_of(opp, struct dce110_opp, base)
struct dce110_opp {
struct output_pixel_processor base;
const struct dce_opp_registers *regs;
const struct dce_opp_shift *opp_shift;
const struct dce_opp_mask *opp_mask;
};
void dce110_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce_opp_registers *regs,
const struct dce_opp_shift *opp_shift,
const struct dce_opp_mask *opp_mask);
#if defined(CONFIG_DRM_AMD_DC_SI)
void dce60_opp_construct(struct dce110_opp *opp110,
struct dc_context *ctx,
uint32_t inst,
const struct dce_opp_registers *regs,
const struct dce_opp_shift *opp_shift,
const struct dce_opp_mask *opp_mask);
#endif
void dce110_opp_destroy(struct output_pixel_processor **opp);
/* FORMATTER RELATED */
void dce110_opp_program_bit_depth_reduction(
struct output_pixel_processor *opp,
const struct bit_depth_reduction_params *params);
void dce110_opp_program_clamping_and_pixel_encoding(
struct output_pixel_processor *opp,
const struct clamping_and_pixel_encoding_params *params);
void dce110_opp_set_dyn_expansion(
struct output_pixel_processor *opp,
enum dc_color_space color_sp,
enum dc_color_depth color_dpth,
enum signal_type signal);
void dce110_opp_program_fmt(
struct output_pixel_processor *opp,
struct bit_depth_reduction_params *fmt_bit_depth,
struct clamping_and_pixel_encoding_params *clamping);
void dce110_opp_set_clamping(
struct dce110_opp *opp110,
const struct clamping_and_pixel_encoding_params *params);
#endif
@@ -0,0 +1,294 @@
/*
* 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 "reg_helper.h"
#include "core_types.h"
#include "dc_dmub_srv.h"
#include "panel_cntl.h"
#include "dce_panel_cntl.h"
#include "atom.h"
#define TO_DCE_PANEL_CNTL(panel_cntl)\
container_of(panel_cntl, struct dce_panel_cntl, base)
#define CTX \
dce_panel_cntl->base.ctx
#define DC_LOGGER \
dce_panel_cntl->base.ctx->logger
#define REG(reg)\
dce_panel_cntl->regs->reg
#undef FN
#define FN(reg_name, field_name) \
dce_panel_cntl->shift->field_name, dce_panel_cntl->mask->field_name
static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl)
{
uint64_t current_backlight;
uint32_t bl_period, bl_int_count;
uint32_t bl_pwm, fractional_duty_cycle_en;
uint32_t bl_period_mask, bl_pwm_mask;
struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl);
REG_READ(BL_PWM_PERIOD_CNTL);
REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period);
REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, &bl_int_count);
REG_READ(BL_PWM_CNTL);
REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, (uint32_t *)(&bl_pwm));
REG_GET(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, &fractional_duty_cycle_en);
if (bl_int_count == 0)
bl_int_count = 16;
bl_period_mask = (1 << bl_int_count) - 1;
bl_period &= bl_period_mask;
bl_pwm_mask = bl_period_mask << (16 - bl_int_count);
if (fractional_duty_cycle_en == 0)
bl_pwm &= bl_pwm_mask;
else
bl_pwm &= 0xFFFF;
current_backlight = (uint64_t)bl_pwm << (1 + bl_int_count);
if (bl_period == 0)
bl_period = 0xFFFF;
current_backlight = div_u64(current_backlight, bl_period);
current_backlight = (current_backlight + 1) >> 1;
return (uint32_t)(current_backlight);
}
static uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl)
{
struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl);
uint32_t value;
uint32_t current_backlight;
/* It must not be 0, so we have to restore them
* Bios bug w/a - period resets to zero,
* restoring to cache values which is always correct
*/
REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value);
if (panel_cntl->stored_backlight_registers.BL_PWM_CNTL != 0) {
REG_WRITE(BL_PWM_CNTL,
panel_cntl->stored_backlight_registers.BL_PWM_CNTL);
REG_WRITE(BL_PWM_CNTL2,
panel_cntl->stored_backlight_registers.BL_PWM_CNTL2);
REG_WRITE(BL_PWM_PERIOD_CNTL,
panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL);
REG_UPDATE(PWRSEQ_REF_DIV,
BL_PWM_REF_DIV,
panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
} else if ((value != 0) && (value != 1)) {
panel_cntl->stored_backlight_registers.BL_PWM_CNTL =
REG_READ(BL_PWM_CNTL);
panel_cntl->stored_backlight_registers.BL_PWM_CNTL2 =
REG_READ(BL_PWM_CNTL2);
panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL =
REG_READ(BL_PWM_PERIOD_CNTL);
REG_GET(PWRSEQ_REF_DIV, BL_PWM_REF_DIV,
&panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
} else {
/* TODO: Note: This should not really happen since VBIOS
* should have initialized PWM registers on boot.
*/
REG_WRITE(BL_PWM_CNTL, 0x8000FA00);
REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0);
}
// Have driver take backlight control
// TakeBacklightControl(true)
value = REG_READ(BIOS_SCRATCH_2);
value |= ATOM_S2_VRI_BRIGHT_ENABLE;
REG_WRITE(BIOS_SCRATCH_2, value);
// Enable the backlight output
REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
// Unlock group 2 backlight registers
REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
BL_PWM_GRP1_REG_LOCK, 0);
current_backlight = dce_get_16_bit_backlight_from_pwm(panel_cntl);
return current_backlight;
}
static bool dce_is_panel_backlight_on(struct panel_cntl *panel_cntl)
{
struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl);
uint32_t blon, blon_ovrd, pwrseq_target_state;
REG_GET_2(PWRSEQ_CNTL, LVTMA_BLON, &blon, LVTMA_BLON_OVRD, &blon_ovrd);
REG_GET(PWRSEQ_CNTL, LVTMA_PWRSEQ_TARGET_STATE, &pwrseq_target_state);
if (blon_ovrd)
return blon;
else
return pwrseq_target_state;
}
static bool dce_is_panel_powered_on(struct panel_cntl *panel_cntl)
{
struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl);
uint32_t pwr_seq_state, dig_on, dig_on_ovrd;
REG_GET(PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state);
REG_GET_2(PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd);
return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1);
}
static void dce_store_backlight_level(struct panel_cntl *panel_cntl)
{
struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl);
panel_cntl->stored_backlight_registers.BL_PWM_CNTL =
REG_READ(BL_PWM_CNTL);
panel_cntl->stored_backlight_registers.BL_PWM_CNTL2 =
REG_READ(BL_PWM_CNTL2);
panel_cntl->stored_backlight_registers.BL_PWM_PERIOD_CNTL =
REG_READ(BL_PWM_PERIOD_CNTL);
REG_GET(PWRSEQ_REF_DIV, BL_PWM_REF_DIV,
&panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
}
static void dce_driver_set_backlight(struct panel_cntl *panel_cntl,
uint32_t backlight_pwm_u16_16)
{
uint32_t backlight_16bit;
uint32_t masked_pwm_period;
uint8_t bit_count;
uint64_t active_duty_cycle;
uint32_t pwm_period_bitcnt;
struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl);
/*
* 1. Find 16 bit backlight active duty cycle, where 0 <= backlight
* active duty cycle <= backlight period
*/
/* 1.1 Apply bitmask for backlight period value based on value of BITCNT
*/
REG_GET_2(BL_PWM_PERIOD_CNTL,
BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt,
BL_PWM_PERIOD, &masked_pwm_period);
if (pwm_period_bitcnt == 0)
bit_count = 16;
else
bit_count = (uint8_t)pwm_period_bitcnt;
/* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */
masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1);
/* 1.2 Calculate integer active duty cycle required upper 16 bits
* contain integer component, lower 16 bits contain fractional component
* of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24
*/
active_duty_cycle = backlight_pwm_u16_16 * (uint64_t)masked_pwm_period;
/* 1.3 Calculate 16 bit active duty cycle from integer and fractional
* components shift by bitCount then mask 16 bits and add rounding bit
* from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0
*/
backlight_16bit = (uint32_t)(active_duty_cycle >> bit_count);
backlight_16bit &= 0xFFFF;
backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1;
/*
* 2. Program register with updated value
*/
/* 2.1 Lock group 2 backlight registers */
REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK,
BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1,
BL_PWM_GRP1_REG_LOCK, 1);
// 2.2 Write new active duty cycle
REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit);
/* 2.3 Unlock group 2 backlight registers */
REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
BL_PWM_GRP1_REG_LOCK, 0);
/* 3 Wait for pending bit to be cleared */
REG_WAIT(BL_PWM_GRP1_REG_LOCK,
BL_PWM_GRP1_REG_UPDATE_PENDING, 0,
1, 10000);
}
static void dce_panel_cntl_destroy(struct panel_cntl **panel_cntl)
{
struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(*panel_cntl);
kfree(dce_panel_cntl);
*panel_cntl = NULL;
}
static const struct panel_cntl_funcs dce_link_panel_cntl_funcs = {
.destroy = dce_panel_cntl_destroy,
.hw_init = dce_panel_cntl_hw_init,
.is_panel_backlight_on = dce_is_panel_backlight_on,
.is_panel_powered_on = dce_is_panel_powered_on,
.store_backlight_level = dce_store_backlight_level,
.driver_set_backlight = dce_driver_set_backlight,
.get_current_backlight = dce_get_16_bit_backlight_from_pwm,
};
void dce_panel_cntl_construct(
struct dce_panel_cntl *dce_panel_cntl,
const struct panel_cntl_init_data *init_data,
const struct dce_panel_cntl_registers *regs,
const struct dce_panel_cntl_shift *shift,
const struct dce_panel_cntl_mask *mask)
{
struct panel_cntl *base = &dce_panel_cntl->base;
base->stored_backlight_registers.BL_PWM_CNTL = 0;
base->stored_backlight_registers.BL_PWM_CNTL2 = 0;
base->stored_backlight_registers.BL_PWM_PERIOD_CNTL = 0;
base->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV = 0;
dce_panel_cntl->regs = regs;
dce_panel_cntl->shift = shift;
dce_panel_cntl->mask = mask;
dce_panel_cntl->base.funcs = &dce_link_panel_cntl_funcs;
dce_panel_cntl->base.ctx = init_data->ctx;
dce_panel_cntl->base.inst = init_data->inst;
dce_panel_cntl->base.pwrseq_inst = 0;
}
@@ -0,0 +1,129 @@
/*
* 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 __DC_PANEL_CNTL__DCE_H__
#define __DC_PANEL_CNTL__DCE_H__
#include "panel_cntl.h"
/* set register offset with instance */
#define DCE_PANEL_CNTL_SR(reg_name, block)\
.reg_name = mm ## block ## _ ## reg_name
#define DCE_PANEL_CNTL_REG_LIST()\
DCE_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \
DCE_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \
DCE_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \
SR(BL_PWM_CNTL), \
SR(BL_PWM_CNTL2), \
SR(BL_PWM_PERIOD_CNTL), \
SR(BL_PWM_GRP1_REG_LOCK), \
SR(BIOS_SCRATCH_2)
#define DCN_PANEL_CNTL_SR(reg_name, block)\
.reg_name = BASE(mm ## block ## _ ## reg_name ## _BASE_IDX) + \
mm ## block ## _ ## reg_name
#define DCN_PANEL_CNTL_REG_LIST()\
DCN_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \
DCN_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \
DCN_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \
SR(BL_PWM_CNTL), \
SR(BL_PWM_CNTL2), \
SR(BL_PWM_PERIOD_CNTL), \
SR(BL_PWM_GRP1_REG_LOCK), \
NBIO_SR(BIOS_SCRATCH_2)
#define DCE_PANEL_CNTL_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define DCE_PANEL_CNTL_MASK_SH_LIST(mask_sh) \
DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_BLON_OVRD, mask_sh),\
DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, mask_sh),\
DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON_OVRD, mask_sh),\
DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_PWRSEQ_TARGET_STATE, mask_sh), \
DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh), \
DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_CNTL, BL_PWM_EN, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, mask_sh), \
DCE_PANEL_CNTL_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, mask_sh)
#define DCE_PANEL_CNTL_REG_FIELD_LIST(type) \
type LVTMA_BLON;\
type LVTMA_BLON_OVRD;\
type LVTMA_DIGON;\
type LVTMA_DIGON_OVRD;\
type LVTMA_PWRSEQ_TARGET_STATE; \
type LVTMA_PWRSEQ_TARGET_STATE_R; \
type BL_PWM_REF_DIV; \
type BL_PWM_EN; \
type BL_ACTIVE_INT_FRAC_CNT; \
type BL_PWM_FRACTIONAL_EN; \
type BL_PWM_PERIOD; \
type BL_PWM_PERIOD_BITCNT; \
type BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN; \
type BL_PWM_GRP1_REG_LOCK; \
type BL_PWM_GRP1_REG_UPDATE_PENDING
struct dce_panel_cntl_shift {
DCE_PANEL_CNTL_REG_FIELD_LIST(uint8_t);
};
struct dce_panel_cntl_mask {
DCE_PANEL_CNTL_REG_FIELD_LIST(uint32_t);
};
struct dce_panel_cntl_registers {
uint32_t PWRSEQ_CNTL;
uint32_t PWRSEQ_STATE;
uint32_t BL_PWM_CNTL;
uint32_t BL_PWM_CNTL2;
uint32_t BL_PWM_PERIOD_CNTL;
uint32_t BL_PWM_GRP1_REG_LOCK;
uint32_t PWRSEQ_REF_DIV;
uint32_t BIOS_SCRATCH_2;
};
struct dce_panel_cntl {
struct panel_cntl base;
const struct dce_panel_cntl_registers *regs;
const struct dce_panel_cntl_shift *shift;
const struct dce_panel_cntl_mask *mask;
};
void dce_panel_cntl_construct(
struct dce_panel_cntl *panel_cntl,
const struct panel_cntl_init_data *init_data,
const struct dce_panel_cntl_registers *regs,
const struct dce_panel_cntl_shift *shift,
const struct dce_panel_cntl_mask *mask);
#endif /* __DC_PANEL_CNTL__DCE_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,25 @@
/*
* Copyright 2012-16 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
*
*/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,749 @@
/*
* 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 __DC_STREAM_ENCODER_DCE110_H__
#define __DC_STREAM_ENCODER_DCE110_H__
#include "stream_encoder.h"
#define DCE110STRENC_FROM_STRENC(stream_encoder)\
container_of(stream_encoder, struct dce110_stream_encoder, base)
#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK
#define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L
#define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L
#define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004
#define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008
#endif
#define SE_COMMON_REG_LIST_DCE_BASE(id) \
SE_COMMON_REG_LIST_BASE(id),\
SRI(AFMT_AVI_INFO0, DIG, id), \
SRI(AFMT_AVI_INFO1, DIG, id), \
SRI(AFMT_AVI_INFO2, DIG, id), \
SRI(AFMT_AVI_INFO3, DIG, id)
#define SE_COMMON_REG_LIST_BASE(id) \
SRI(AFMT_GENERIC_0, DIG, id), \
SRI(AFMT_GENERIC_1, DIG, id), \
SRI(AFMT_GENERIC_2, DIG, id), \
SRI(AFMT_GENERIC_3, DIG, id), \
SRI(AFMT_GENERIC_4, DIG, id), \
SRI(AFMT_GENERIC_5, DIG, id), \
SRI(AFMT_GENERIC_6, DIG, id), \
SRI(AFMT_GENERIC_7, DIG, id), \
SRI(AFMT_GENERIC_HDR, DIG, id), \
SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \
SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \
SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \
SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \
SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \
SRI(AFMT_60958_0, DIG, id), \
SRI(AFMT_60958_1, DIG, id), \
SRI(AFMT_60958_2, DIG, id), \
SRI(DIG_FE_CNTL, DIG, id), \
SR(DAC_SOURCE_SELECT), \
SRI(HDMI_CONTROL, DIG, id), \
SRI(HDMI_GC, DIG, id), \
SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \
SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \
SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \
SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \
SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\
SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\
SRI(HDMI_ACR_32_0, DIG, id),\
SRI(HDMI_ACR_32_1, DIG, id),\
SRI(HDMI_ACR_44_0, DIG, id),\
SRI(HDMI_ACR_44_1, DIG, id),\
SRI(HDMI_ACR_48_0, DIG, id),\
SRI(HDMI_ACR_48_1, DIG, id),\
SRI(TMDS_CNTL, DIG, id), \
SRI(DP_MSE_RATE_CNTL, DP, id), \
SRI(DP_MSE_RATE_UPDATE, DP, id), \
SRI(DP_PIXEL_FORMAT, DP, id), \
SRI(DP_SEC_CNTL, DP, id), \
SRI(DP_STEER_FIFO, DP, id), \
SRI(DP_VID_M, DP, id), \
SRI(DP_VID_N, DP, id), \
SRI(DP_VID_STREAM_CNTL, DP, id), \
SRI(DP_VID_TIMING, DP, id), \
SRI(DP_SEC_AUD_N, DP, id), \
SRI(DP_SEC_TIMESTAMP, DP, id)
#define SE_COMMON_REG_LIST(id)\
SE_COMMON_REG_LIST_DCE_BASE(id), \
SRI(AFMT_CNTL, DIG, id), \
SRI(DP_MSA_MISC, DP, id)
#define SE_DCN_REG_LIST(id)\
SE_COMMON_REG_LIST_BASE(id),\
SRI(AFMT_CNTL, DIG, id),\
SRI(AFMT_VBI_PACKET_CONTROL1, DIG, id),\
SRI(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \
SRI(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \
SRI(DP_DB_CNTL, DP, id), \
SRI(DP_MSA_MISC, DP, id), \
SRI(DP_MSA_COLORIMETRY, DP, id), \
SRI(DP_MSA_TIMING_PARAM1, DP, id), \
SRI(DP_MSA_TIMING_PARAM2, DP, id), \
SRI(DP_MSA_TIMING_PARAM3, DP, id), \
SRI(DP_MSA_TIMING_PARAM4, DP, id), \
SRI(HDMI_DB_CONTROL, DIG, id)
#define SE_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\
SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\
SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\
SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\
SE_SF(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\
SE_SF(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\
SE_SF(DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\
SE_SF(DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\
SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
SE_SF(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\
SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
SE_SF(HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\
SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\
SE_SF(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\
SE_SF(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\
SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\
SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\
SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\
SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\
SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\
SE_SF(DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\
SE_SF(DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\
SE_SF(DP_VID_N, DP_VID_N, mask_sh),\
SE_SF(DP_VID_M, DP_VID_M, mask_sh),\
SE_SF(DIG_FE_CNTL, DIG_START, mask_sh),\
SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\
SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
SE_SF(AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\
SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\
SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\
SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\
SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\
SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\
SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\
SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\
SE_SF(HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
SE_SF(HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
SE_SF(HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
SE_SF(HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
SE_SF(HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
SE_SF(HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
SE_SF(AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\
SE_SF(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\
SE_SF(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\
SE_SF(DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\
SE_SF(DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
SE_SF(DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\
SE_SF(DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh)
#define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\
SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\
SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\
SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\
SE_SF(DIG0_AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\
SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\
SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\
SE_SF(DIG0_HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\
SE_SF(DIG0_HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\
SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
SE_SF(DIG0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\
SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\
SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\
SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\
SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\
SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\
SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\
SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\
SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\
SE_SF(DIG0_DIG_FE_CNTL, DIG_START, mask_sh),\
SE_SF(DIG0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\
SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\
SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\
SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\
SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\
SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\
SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\
SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\
SE_SF(DIG0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\
SE_SF(DIG0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\
SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\
SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\
SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\
SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\
SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\
SE_SF(DIG0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\
SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\
SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
SE_SF(DIG0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\
SE_SF(DIG0_AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
SE_SF(DIG0_DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
SE_SF(DIG0_DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\
SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh)
#define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
SE_SF(DAC_SOURCE_SELECT, DAC_SOURCE_SELECT, mask_sh)
#define SE_COMMON_MASK_SH_LIST_DCE110(mask_sh)\
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\
SE_SF(DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh)
#define SE_COMMON_MASK_SH_LIST_DCE112(mask_sh)\
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh)
#define SE_COMMON_MASK_SH_LIST_DCE120(mask_sh)\
SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\
SE_SF(DP0_DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\
SE_SF(DIG0_HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\
SE_SF(DIG0_AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\
SE_SF(DP0_DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh)
#define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\
SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_LOCK_STATUS, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_CONFLICT_CLR, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE_PENDING, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_FRAME_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_FRAME_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\
SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\
SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\
SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\
SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\
SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\
SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\
SE_SF(DP0_DP_VID_TIMING, DP_VID_N_MUL, mask_sh)
struct dce_stream_encoder_shift {
uint8_t AFMT_GENERIC_INDEX;
uint8_t AFMT_GENERIC0_UPDATE;
uint8_t AFMT_GENERIC2_UPDATE;
uint8_t AFMT_GENERIC_HB0;
uint8_t AFMT_GENERIC_HB1;
uint8_t AFMT_GENERIC_HB2;
uint8_t AFMT_GENERIC_HB3;
uint8_t AFMT_GENERIC_LOCK_STATUS;
uint8_t AFMT_GENERIC_CONFLICT;
uint8_t AFMT_GENERIC_CONFLICT_CLR;
uint8_t AFMT_GENERIC0_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC1_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC2_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC3_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC4_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC5_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC6_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC7_FRAME_UPDATE_PENDING;
uint8_t AFMT_GENERIC0_FRAME_UPDATE;
uint8_t AFMT_GENERIC1_FRAME_UPDATE;
uint8_t AFMT_GENERIC2_FRAME_UPDATE;
uint8_t AFMT_GENERIC3_FRAME_UPDATE;
uint8_t AFMT_GENERIC4_FRAME_UPDATE;
uint8_t AFMT_GENERIC5_FRAME_UPDATE;
uint8_t AFMT_GENERIC6_FRAME_UPDATE;
uint8_t AFMT_GENERIC7_FRAME_UPDATE;
uint8_t HDMI_GENERIC0_CONT;
uint8_t HDMI_GENERIC0_SEND;
uint8_t HDMI_GENERIC0_LINE;
uint8_t HDMI_GENERIC1_CONT;
uint8_t HDMI_GENERIC1_SEND;
uint8_t HDMI_GENERIC1_LINE;
uint8_t DP_PIXEL_ENCODING;
uint8_t DP_COMPONENT_DEPTH;
uint8_t DP_DYN_RANGE;
uint8_t DP_YCBCR_RANGE;
uint8_t HDMI_PACKET_GEN_VERSION;
uint8_t HDMI_KEEPOUT_MODE;
uint8_t HDMI_DEEP_COLOR_ENABLE;
uint8_t HDMI_CLOCK_CHANNEL_RATE;
uint8_t HDMI_DEEP_COLOR_DEPTH;
uint8_t HDMI_GC_CONT;
uint8_t HDMI_GC_SEND;
uint8_t HDMI_NULL_SEND;
uint8_t HDMI_DATA_SCRAMBLE_EN;
uint8_t HDMI_ACP_SEND;
uint8_t HDMI_AUDIO_INFO_SEND;
uint8_t AFMT_AUDIO_INFO_UPDATE;
uint8_t HDMI_AUDIO_INFO_LINE;
uint8_t HDMI_GC_AVMUTE;
uint8_t DP_MSE_RATE_X;
uint8_t DP_MSE_RATE_Y;
uint8_t DP_MSE_RATE_UPDATE_PENDING;
uint8_t AFMT_AVI_INFO_VERSION;
uint8_t HDMI_AVI_INFO_SEND;
uint8_t HDMI_AVI_INFO_CONT;
uint8_t HDMI_AVI_INFO_LINE;
uint8_t DP_SEC_GSP0_ENABLE;
uint8_t DP_SEC_STREAM_ENABLE;
uint8_t DP_SEC_GSP1_ENABLE;
uint8_t DP_SEC_GSP2_ENABLE;
uint8_t DP_SEC_GSP3_ENABLE;
uint8_t DP_SEC_GSP4_ENABLE;
uint8_t DP_SEC_GSP5_ENABLE;
uint8_t DP_SEC_GSP6_ENABLE;
uint8_t DP_SEC_GSP7_ENABLE;
uint8_t DP_SEC_AVI_ENABLE;
uint8_t DP_SEC_MPG_ENABLE;
uint8_t DP_VID_STREAM_DIS_DEFER;
uint8_t DP_VID_STREAM_ENABLE;
uint8_t DP_VID_STREAM_STATUS;
uint8_t DP_STEER_FIFO_RESET;
uint8_t DP_VID_M_N_GEN_EN;
uint8_t DP_VID_N;
uint8_t DP_VID_M;
uint8_t DIG_START;
uint8_t AFMT_AUDIO_SRC_SELECT;
uint8_t AFMT_AUDIO_CHANNEL_ENABLE;
uint8_t HDMI_AUDIO_PACKETS_PER_LINE;
uint8_t HDMI_AUDIO_DELAY_EN;
uint8_t AFMT_60958_CS_UPDATE;
uint8_t AFMT_AUDIO_LAYOUT_OVRD;
uint8_t AFMT_60958_OSF_OVRD;
uint8_t HDMI_ACR_AUTO_SEND;
uint8_t HDMI_ACR_SOURCE;
uint8_t HDMI_ACR_AUDIO_PRIORITY;
uint8_t HDMI_ACR_CTS_32;
uint8_t HDMI_ACR_N_32;
uint8_t HDMI_ACR_CTS_44;
uint8_t HDMI_ACR_N_44;
uint8_t HDMI_ACR_CTS_48;
uint8_t HDMI_ACR_N_48;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_L;
uint8_t AFMT_60958_CS_CLOCK_ACCURACY;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_R;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_2;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_3;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_4;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_5;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_6;
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_7;
uint8_t DP_SEC_AUD_N;
uint8_t DP_SEC_TIMESTAMP_MODE;
uint8_t DP_SEC_ASP_ENABLE;
uint8_t DP_SEC_ATP_ENABLE;
uint8_t DP_SEC_AIP_ENABLE;
uint8_t DP_SEC_ACM_ENABLE;
uint8_t AFMT_AUDIO_SAMPLE_SEND;
uint8_t AFMT_AUDIO_CLOCK_EN;
uint8_t TMDS_PIXEL_ENCODING;
uint8_t TMDS_COLOR_FORMAT;
uint8_t DIG_STEREOSYNC_SELECT;
uint8_t DIG_STEREOSYNC_GATE_EN;
uint8_t DP_DB_DISABLE;
uint8_t DP_MSA_MISC0;
uint8_t DP_MSA_HTOTAL;
uint8_t DP_MSA_VTOTAL;
uint8_t DP_MSA_HSTART;
uint8_t DP_MSA_VSTART;
uint8_t DP_MSA_HSYNCWIDTH;
uint8_t DP_MSA_HSYNCPOLARITY;
uint8_t DP_MSA_VSYNCWIDTH;
uint8_t DP_MSA_VSYNCPOLARITY;
uint8_t DP_MSA_HWIDTH;
uint8_t DP_MSA_VHEIGHT;
uint8_t HDMI_DB_DISABLE;
uint8_t DP_VID_N_MUL;
uint8_t DP_VID_M_DOUBLE_VALUE_EN;
uint8_t DIG_SOURCE_SELECT;
uint8_t DAC_SOURCE_SELECT;
};
struct dce_stream_encoder_mask {
uint32_t AFMT_GENERIC_INDEX;
uint32_t AFMT_GENERIC0_UPDATE;
uint32_t AFMT_GENERIC2_UPDATE;
uint32_t AFMT_GENERIC_HB0;
uint32_t AFMT_GENERIC_HB1;
uint32_t AFMT_GENERIC_HB2;
uint32_t AFMT_GENERIC_HB3;
uint32_t AFMT_GENERIC_LOCK_STATUS;
uint32_t AFMT_GENERIC_CONFLICT;
uint32_t AFMT_GENERIC_CONFLICT_CLR;
uint32_t AFMT_GENERIC0_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC1_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC2_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC3_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC4_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC5_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC6_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC7_FRAME_UPDATE_PENDING;
uint32_t AFMT_GENERIC0_FRAME_UPDATE;
uint32_t AFMT_GENERIC1_FRAME_UPDATE;
uint32_t AFMT_GENERIC2_FRAME_UPDATE;
uint32_t AFMT_GENERIC3_FRAME_UPDATE;
uint32_t AFMT_GENERIC4_FRAME_UPDATE;
uint32_t AFMT_GENERIC5_FRAME_UPDATE;
uint32_t AFMT_GENERIC6_FRAME_UPDATE;
uint32_t AFMT_GENERIC7_FRAME_UPDATE;
uint32_t HDMI_GENERIC0_CONT;
uint32_t HDMI_GENERIC0_SEND;
uint32_t HDMI_GENERIC0_LINE;
uint32_t HDMI_GENERIC1_CONT;
uint32_t HDMI_GENERIC1_SEND;
uint32_t HDMI_GENERIC1_LINE;
uint32_t DP_PIXEL_ENCODING;
uint32_t DP_COMPONENT_DEPTH;
uint32_t DP_DYN_RANGE;
uint32_t DP_YCBCR_RANGE;
uint32_t HDMI_PACKET_GEN_VERSION;
uint32_t HDMI_KEEPOUT_MODE;
uint32_t HDMI_DEEP_COLOR_ENABLE;
uint32_t HDMI_CLOCK_CHANNEL_RATE;
uint32_t HDMI_DEEP_COLOR_DEPTH;
uint32_t HDMI_GC_CONT;
uint32_t HDMI_GC_SEND;
uint32_t HDMI_NULL_SEND;
uint32_t HDMI_DATA_SCRAMBLE_EN;
uint32_t HDMI_ACP_SEND;
uint32_t HDMI_AUDIO_INFO_SEND;
uint32_t AFMT_AUDIO_INFO_UPDATE;
uint32_t HDMI_AUDIO_INFO_LINE;
uint32_t HDMI_GC_AVMUTE;
uint32_t DP_MSE_RATE_X;
uint32_t DP_MSE_RATE_Y;
uint32_t DP_MSE_RATE_UPDATE_PENDING;
uint32_t AFMT_AVI_INFO_VERSION;
uint32_t HDMI_AVI_INFO_SEND;
uint32_t HDMI_AVI_INFO_CONT;
uint32_t HDMI_AVI_INFO_LINE;
uint32_t DP_SEC_GSP0_ENABLE;
uint32_t DP_SEC_STREAM_ENABLE;
uint32_t DP_SEC_GSP1_ENABLE;
uint32_t DP_SEC_GSP2_ENABLE;
uint32_t DP_SEC_GSP3_ENABLE;
uint32_t DP_SEC_GSP4_ENABLE;
uint32_t DP_SEC_GSP5_ENABLE;
uint32_t DP_SEC_GSP6_ENABLE;
uint32_t DP_SEC_GSP7_ENABLE;
uint32_t DP_SEC_AVI_ENABLE;
uint32_t DP_SEC_MPG_ENABLE;
uint32_t DP_VID_STREAM_DIS_DEFER;
uint32_t DP_VID_STREAM_ENABLE;
uint32_t DP_VID_STREAM_STATUS;
uint32_t DP_STEER_FIFO_RESET;
uint32_t DP_VID_M_N_GEN_EN;
uint32_t DP_VID_N;
uint32_t DP_VID_M;
uint32_t DIG_START;
uint32_t AFMT_AUDIO_SRC_SELECT;
uint32_t AFMT_AUDIO_CHANNEL_ENABLE;
uint32_t HDMI_AUDIO_PACKETS_PER_LINE;
uint32_t HDMI_AUDIO_DELAY_EN;
uint32_t AFMT_60958_CS_UPDATE;
uint32_t AFMT_AUDIO_LAYOUT_OVRD;
uint32_t AFMT_60958_OSF_OVRD;
uint32_t HDMI_ACR_AUTO_SEND;
uint32_t HDMI_ACR_SOURCE;
uint32_t HDMI_ACR_AUDIO_PRIORITY;
uint32_t HDMI_ACR_CTS_32;
uint32_t HDMI_ACR_N_32;
uint32_t HDMI_ACR_CTS_44;
uint32_t HDMI_ACR_N_44;
uint32_t HDMI_ACR_CTS_48;
uint32_t HDMI_ACR_N_48;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_L;
uint32_t AFMT_60958_CS_CLOCK_ACCURACY;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_R;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_2;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_3;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_4;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_5;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_6;
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_7;
uint32_t DP_SEC_AUD_N;
uint32_t DP_SEC_TIMESTAMP_MODE;
uint32_t DP_SEC_ASP_ENABLE;
uint32_t DP_SEC_ATP_ENABLE;
uint32_t DP_SEC_AIP_ENABLE;
uint32_t DP_SEC_ACM_ENABLE;
uint32_t AFMT_AUDIO_SAMPLE_SEND;
uint32_t AFMT_AUDIO_CLOCK_EN;
uint32_t TMDS_PIXEL_ENCODING;
uint32_t DIG_STEREOSYNC_SELECT;
uint32_t DIG_STEREOSYNC_GATE_EN;
uint32_t TMDS_COLOR_FORMAT;
uint32_t DP_DB_DISABLE;
uint32_t DP_MSA_MISC0;
uint32_t DP_MSA_HTOTAL;
uint32_t DP_MSA_VTOTAL;
uint32_t DP_MSA_HSTART;
uint32_t DP_MSA_VSTART;
uint32_t DP_MSA_HSYNCWIDTH;
uint32_t DP_MSA_HSYNCPOLARITY;
uint32_t DP_MSA_VSYNCWIDTH;
uint32_t DP_MSA_VSYNCPOLARITY;
uint32_t DP_MSA_HWIDTH;
uint32_t DP_MSA_VHEIGHT;
uint32_t HDMI_DB_DISABLE;
uint32_t DP_VID_N_MUL;
uint32_t DP_VID_M_DOUBLE_VALUE_EN;
uint32_t DIG_SOURCE_SELECT;
uint32_t DAC_SOURCE_SELECT;
};
struct dce110_stream_enc_registers {
uint32_t AFMT_CNTL;
uint32_t AFMT_AVI_INFO0;
uint32_t AFMT_AVI_INFO1;
uint32_t AFMT_AVI_INFO2;
uint32_t AFMT_AVI_INFO3;
uint32_t AFMT_GENERIC_0;
uint32_t AFMT_GENERIC_1;
uint32_t AFMT_GENERIC_2;
uint32_t AFMT_GENERIC_3;
uint32_t AFMT_GENERIC_4;
uint32_t AFMT_GENERIC_5;
uint32_t AFMT_GENERIC_6;
uint32_t AFMT_GENERIC_7;
uint32_t AFMT_GENERIC_HDR;
uint32_t AFMT_INFOFRAME_CONTROL0;
uint32_t AFMT_VBI_PACKET_CONTROL;
uint32_t AFMT_VBI_PACKET_CONTROL1;
uint32_t AFMT_AUDIO_PACKET_CONTROL;
uint32_t AFMT_AUDIO_PACKET_CONTROL2;
uint32_t AFMT_AUDIO_SRC_CONTROL;
uint32_t AFMT_60958_0;
uint32_t AFMT_60958_1;
uint32_t AFMT_60958_2;
uint32_t DIG_FE_CNTL;
uint32_t DAC_SOURCE_SELECT;
uint32_t DP_MSE_RATE_CNTL;
uint32_t DP_MSE_RATE_UPDATE;
uint32_t DP_PIXEL_FORMAT;
uint32_t DP_SEC_CNTL;
uint32_t DP_STEER_FIFO;
uint32_t DP_VID_M;
uint32_t DP_VID_N;
uint32_t DP_VID_STREAM_CNTL;
uint32_t DP_VID_TIMING;
uint32_t DP_SEC_AUD_N;
uint32_t DP_SEC_TIMESTAMP;
uint32_t HDMI_CONTROL;
uint32_t HDMI_GC;
uint32_t HDMI_GENERIC_PACKET_CONTROL0;
uint32_t HDMI_GENERIC_PACKET_CONTROL1;
uint32_t HDMI_GENERIC_PACKET_CONTROL2;
uint32_t HDMI_GENERIC_PACKET_CONTROL3;
uint32_t HDMI_INFOFRAME_CONTROL0;
uint32_t HDMI_INFOFRAME_CONTROL1;
uint32_t HDMI_VBI_PACKET_CONTROL;
uint32_t HDMI_AUDIO_PACKET_CONTROL;
uint32_t HDMI_ACR_PACKET_CONTROL;
uint32_t HDMI_ACR_32_0;
uint32_t HDMI_ACR_32_1;
uint32_t HDMI_ACR_44_0;
uint32_t HDMI_ACR_44_1;
uint32_t HDMI_ACR_48_0;
uint32_t HDMI_ACR_48_1;
uint32_t TMDS_CNTL;
uint32_t DP_DB_CNTL;
uint32_t DP_MSA_MISC;
uint32_t DP_MSA_COLORIMETRY;
uint32_t DP_MSA_TIMING_PARAM1;
uint32_t DP_MSA_TIMING_PARAM2;
uint32_t DP_MSA_TIMING_PARAM3;
uint32_t DP_MSA_TIMING_PARAM4;
uint32_t HDMI_DB_CONTROL;
};
struct dce110_stream_encoder {
struct stream_encoder base;
const struct dce110_stream_enc_registers *regs;
const struct dce_stream_encoder_shift *se_shift;
const struct dce_stream_encoder_mask *se_mask;
};
void dce110_stream_encoder_construct(
struct dce110_stream_encoder *enc110,
struct dc_context *ctx,
struct dc_bios *bp,
enum engine_id eng_id,
const struct dce110_stream_enc_registers *regs,
const struct dce_stream_encoder_shift *se_shift,
const struct dce_stream_encoder_mask *se_mask);
void dce110_analog_stream_encoder_construct(
struct dce110_stream_encoder *enc110,
struct dc_context *ctx,
struct dc_bios *bp,
enum engine_id eng_id,
const struct dce110_stream_enc_registers *regs,
const struct dce_stream_encoder_shift *se_shift,
const struct dce_stream_encoder_mask *se_mask);
void dce110_se_audio_mute_control(
struct stream_encoder *enc, bool mute);
void dce110_se_dp_audio_setup(
struct stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info);
void dce110_se_dp_audio_enable(
struct stream_encoder *enc);
void dce110_se_dp_audio_disable(
struct stream_encoder *enc);
void dce110_se_hdmi_audio_setup(
struct stream_encoder *enc,
unsigned int az_inst,
struct audio_info *info,
struct audio_crtc_info *audio_crtc_info);
void dce110_se_hdmi_audio_disable(
struct stream_encoder *enc);
#endif /* __DC_STREAM_ENCODER_DCE110_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,699 @@
/*
* Copyright 2012-16 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_DCE_TRANSFORM_H_
#define _DCE_DCE_TRANSFORM_H_
#include "transform.h"
#define TO_DCE_TRANSFORM(transform)\
container_of(transform, struct dce_transform, base)
#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
#define LB_BITS_PER_ENTRY 144
#define XFM_COMMON_REG_LIST_DCE_BASE(id) \
SRI(LB_DATA_FORMAT, LB, id), \
SRI(GAMUT_REMAP_CONTROL, DCP, id), \
SRI(GAMUT_REMAP_C11_C12, DCP, id), \
SRI(GAMUT_REMAP_C13_C14, DCP, id), \
SRI(GAMUT_REMAP_C21_C22, DCP, id), \
SRI(GAMUT_REMAP_C23_C24, DCP, id), \
SRI(GAMUT_REMAP_C31_C32, DCP, id), \
SRI(GAMUT_REMAP_C33_C34, DCP, id), \
SRI(OUTPUT_CSC_C11_C12, DCP, id), \
SRI(OUTPUT_CSC_C13_C14, DCP, id), \
SRI(OUTPUT_CSC_C21_C22, DCP, id), \
SRI(OUTPUT_CSC_C23_C24, DCP, id), \
SRI(OUTPUT_CSC_C31_C32, DCP, id), \
SRI(OUTPUT_CSC_C33_C34, DCP, id), \
SRI(OUTPUT_CSC_CONTROL, DCP, id), \
SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \
SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \
SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \
SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \
SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \
SRI(REGAMMA_LUT_INDEX, DCP, id), \
SRI(REGAMMA_LUT_DATA, DCP, id), \
SRI(REGAMMA_CONTROL, DCP, id), \
SRI(DENORM_CONTROL, DCP, id), \
SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \
SRI(OUT_ROUND_CONTROL, DCP, id), \
SRI(OUT_CLAMP_CONTROL_R_CR, DCP, id), \
SRI(OUT_CLAMP_CONTROL_G_Y, DCP, id), \
SRI(OUT_CLAMP_CONTROL_B_CB, DCP, id), \
SRI(SCL_MODE, SCL, id), \
SRI(SCL_TAP_CONTROL, SCL, id), \
SRI(SCL_CONTROL, SCL, id), \
SRI(SCL_BYPASS_CONTROL, SCL, id), \
SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \
SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \
SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \
SRI(SCL_HORZ_FILTER_CONTROL, SCL, id), \
SRI(SCL_COEF_RAM_SELECT, SCL, id), \
SRI(SCL_COEF_RAM_TAP_DATA, SCL, id), \
SRI(VIEWPORT_START, SCL, id), \
SRI(VIEWPORT_SIZE, SCL, id), \
SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \
SRI(SCL_VERT_FILTER_SCALE_RATIO, SCL, id), \
SRI(SCL_HORZ_FILTER_INIT, SCL, id), \
SRI(SCL_VERT_FILTER_INIT, SCL, id), \
SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \
SRI(LB_MEMORY_CTRL, LB, id), \
SRI(SCL_UPDATE, SCL, id), \
SRI(SCL_F_SHARP_CONTROL, SCL, id)
#define XFM_COMMON_REG_LIST_DCE80(id) \
XFM_COMMON_REG_LIST_DCE_BASE(id), \
SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id)
#define XFM_COMMON_REG_LIST_DCE100(id) \
XFM_COMMON_REG_LIST_DCE_BASE(id), \
SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \
SRI(DCFE_MEM_PWR_STATUS, CRTC, id)
#define XFM_COMMON_REG_LIST_DCE110(id) \
XFM_COMMON_REG_LIST_DCE_BASE(id), \
SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \
SRI(DCFE_MEM_PWR_STATUS, DCFE, id)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define XFM_COMMON_REG_LIST_DCE60_BASE(id) \
SRI(DATA_FORMAT, LB, id), \
SRI(GAMUT_REMAP_CONTROL, DCP, id), \
SRI(GAMUT_REMAP_C11_C12, DCP, id), \
SRI(GAMUT_REMAP_C13_C14, DCP, id), \
SRI(GAMUT_REMAP_C21_C22, DCP, id), \
SRI(GAMUT_REMAP_C23_C24, DCP, id), \
SRI(GAMUT_REMAP_C31_C32, DCP, id), \
SRI(GAMUT_REMAP_C33_C34, DCP, id), \
SRI(OUTPUT_CSC_C11_C12, DCP, id), \
SRI(OUTPUT_CSC_C13_C14, DCP, id), \
SRI(OUTPUT_CSC_C21_C22, DCP, id), \
SRI(OUTPUT_CSC_C23_C24, DCP, id), \
SRI(OUTPUT_CSC_C31_C32, DCP, id), \
SRI(OUTPUT_CSC_C33_C34, DCP, id), \
SRI(OUTPUT_CSC_CONTROL, DCP, id), \
SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \
SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \
SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \
SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \
SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \
SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \
SRI(REGAMMA_LUT_INDEX, DCP, id), \
SRI(REGAMMA_LUT_DATA, DCP, id), \
SRI(REGAMMA_CONTROL, DCP, id), \
SRI(DENORM_CONTROL, DCP, id), \
SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \
SRI(OUT_ROUND_CONTROL, DCP, id), \
SRI(SCL_TAP_CONTROL, SCL, id), \
SRI(SCL_CONTROL, SCL, id), \
SRI(SCL_BYPASS_CONTROL, SCL, id), \
SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \
SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \
SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \
SRI(SCL_HORZ_FILTER_CONTROL, SCL, id), \
SRI(SCL_COEF_RAM_SELECT, SCL, id), \
SRI(SCL_COEF_RAM_TAP_DATA, SCL, id), \
SRI(VIEWPORT_START, SCL, id), \
SRI(VIEWPORT_SIZE, SCL, id), \
SRI(SCL_SCALER_ENABLE, SCL, id), \
SRI(SCL_HORZ_FILTER_INIT_RGB_LUMA, SCL, id), \
SRI(SCL_HORZ_FILTER_INIT_CHROMA, SCL, id), \
SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \
SRI(SCL_VERT_FILTER_SCALE_RATIO, SCL, id), \
SRI(SCL_VERT_FILTER_INIT, SCL, id), \
SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \
SRI(DC_LB_MEMORY_SPLIT, LB, id), \
SRI(DC_LB_MEM_SIZE, LB, id), \
SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id), \
SRI(SCL_UPDATE, SCL, id), \
SRI(SCL_F_SHARP_CONTROL, SCL, id)
#define XFM_COMMON_REG_LIST_DCE60(id) \
XFM_COMMON_REG_LIST_DCE60_BASE(id), \
SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id)
#endif
#define XFM_SF(reg_name, field_name, post_fix)\
.field_name = reg_name ## __ ## field_name ## post_fix
#define XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \
XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \
XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \
XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \
XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \
XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \
XFM_SF(OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \
XFM_SF(DENORM_CONTROL, DENORM_MODE, mask_sh), \
XFM_SF(LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \
XFM_SF(LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \
XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \
XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \
XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \
XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \
XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \
XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \
XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \
XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \
XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \
XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \
XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \
XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \
XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \
XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\
XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\
XFM_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\
XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\
XFM_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\
XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
XFM_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\
XFM_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\
XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \
XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \
XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \
XFM_SF(SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \
XFM_SF(SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \
XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \
XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \
XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \
XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \
XFM_SF(VIEWPORT_START, VIEWPORT_X_START, mask_sh), \
XFM_SF(VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \
XFM_SF(VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \
XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \
XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \
XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \
XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \
XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \
XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \
XFM_SF(SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \
XFM_SF(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \
XFM_SF(LB_DATA_FORMAT, ALPHA_EN, mask_sh)
#define XFM_COMMON_MASK_SH_LIST_DCE80(mask_sh) \
XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh)
#define XFM_COMMON_MASK_SH_LIST_DCE110(mask_sh) \
XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \
XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \
XFM_SF(DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\
XFM_SF(DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\
XFM_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\
XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_SI)
#define XFM_COMMON_MASK_SH_LIST_DCE60(mask_sh) \
XFM_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh), \
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\
OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh)
#define XFM_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh) \
XFM_SF(OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \
XFM_SF(DENORM_CONTROL, DENORM_MODE, mask_sh), \
XFM_SF(DATA_FORMAT, INTERLEAVE_EN, mask_sh), \
XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \
XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \
XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \
XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \
XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \
XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \
XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \
XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \
XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \
XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \
XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \
XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \
XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \
XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\
XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\
XFM_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\
XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\
XFM_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\
XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\
XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
XFM_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\
XFM_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\
XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \
XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \
XFM_SF(SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \
XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \
XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \
XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \
XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \
XFM_SF(VIEWPORT_START, VIEWPORT_X_START, mask_sh), \
XFM_SF(VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \
XFM_SF(VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \
XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \
XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_INIT_RGB_LUMA, SCL_H_INIT_INT_RGB_Y, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_INIT_RGB_LUMA, SCL_H_INIT_FRAC_RGB_Y, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_INIT_CHROMA, SCL_H_INIT_INT_CBCR, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_INIT_CHROMA, SCL_H_INIT_FRAC_CBCR, mask_sh), \
XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \
XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \
XFM_SF(SCL_HORZ_FILTER_CONTROL, SCL_H_FILTER_PICK_NEAREST, mask_sh), \
XFM_SF(SCL_VERT_FILTER_CONTROL, SCL_V_FILTER_PICK_NEAREST, mask_sh), \
XFM_SF(DC_LB_MEMORY_SPLIT, DC_LB_MEMORY_CONFIG, mask_sh), \
XFM_SF(DC_LB_MEM_SIZE, DC_LB_MEM_SIZE, mask_sh)
#endif
#define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \
XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \
XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \
XFM_SF(DCP0_OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \
XFM_SF(DCP0_OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \
XFM_SF(DCP0_OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \
XFM_SF(DCP0_OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \
XFM_SF(DCP0_OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \
XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \
XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \
XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \
XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \
XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \
XFM_SF(DCP0_DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \
XFM_SF(DCP0_DENORM_CONTROL, DENORM_MODE, mask_sh), \
XFM_SF(LB0_LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \
XFM_SF(LB0_LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \
XFM_SF(DCP0_GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \
XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\
XFM_SF(DCP0_OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\
XFM_SF(DCP0_OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\
XFM_SF(DCP0_REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
XFM_SF(DCP0_REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\
XFM_SF(DCP0_REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\
XFM_SF(SCL0_SCL_MODE, SCL_MODE, mask_sh), \
XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \
XFM_SF(SCL0_SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \
XFM_SF(SCL0_SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \
XFM_SF(SCL0_SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \
XFM_SF(SCL0_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \
XFM_SF(SCL0_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \
XFM_SF(SCL0_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \
XFM_SF(SCL0_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \
XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \
XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \
XFM_SF(SCL0_SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \
XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \
XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \
XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \
XFM_SF(SCL0_SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \
XFM_SF(SCL0_VIEWPORT_START, VIEWPORT_X_START, mask_sh), \
XFM_SF(SCL0_VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \
XFM_SF(SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \
XFM_SF(SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \
XFM_SF(SCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \
XFM_SF(SCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \
XFM_SF(SCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \
XFM_SF(SCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \
XFM_SF(SCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \
XFM_SF(SCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \
XFM_SF(LB0_LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \
XFM_SF(LB0_LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \
XFM_SF(SCL0_SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \
XFM_SF(SCL0_SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \
XFM_SF(SCL0_SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \
XFM_SF(LB0_LB_DATA_FORMAT, ALPHA_EN, mask_sh), \
XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \
XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_REGAMMA_MEM_PWR_DIS, mask_sh),\
XFM_SF(DCFE0_DCFE_MEM_PWR_CTRL, DCP_LUT_MEM_PWR_DIS, mask_sh),\
XFM_SF(DCFE0_DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \
XFM_SF(SCL0_SCL_MODE, SCL_PSCL_EN, mask_sh)
#define XFM_REG_FIELD_LIST(type) \
type OUT_CLAMP_MIN_B_CB; \
type OUT_CLAMP_MAX_B_CB; \
type OUT_CLAMP_MIN_G_Y; \
type OUT_CLAMP_MAX_G_Y; \
type OUT_CLAMP_MIN_R_CR; \
type OUT_CLAMP_MAX_R_CR; \
type OUT_ROUND_TRUNC_MODE; \
type DCP_SPATIAL_DITHER_EN; \
type DCP_SPATIAL_DITHER_MODE; \
type DCP_SPATIAL_DITHER_DEPTH; \
type DCP_FRAME_RANDOM_ENABLE; \
type DCP_RGB_RANDOM_ENABLE; \
type DCP_HIGHPASS_RANDOM_ENABLE; \
type DENORM_MODE; \
type INTERLEAVE_EN; \
type PIXEL_DEPTH; \
type PIXEL_EXPAN_MODE; \
type GAMUT_REMAP_C11; \
type GAMUT_REMAP_C12; \
type GAMUT_REMAP_C13; \
type GAMUT_REMAP_C14; \
type GAMUT_REMAP_C21; \
type GAMUT_REMAP_C22; \
type GAMUT_REMAP_C23; \
type GAMUT_REMAP_C24; \
type GAMUT_REMAP_C31; \
type GAMUT_REMAP_C32; \
type GAMUT_REMAP_C33; \
type GAMUT_REMAP_C34; \
type GRPH_GAMUT_REMAP_MODE; \
type OUTPUT_CSC_C11; \
type OUTPUT_CSC_C12; \
type OUTPUT_CSC_GRPH_MODE; \
type DCP_REGAMMA_MEM_PWR_DIS; \
type DCP_LUT_MEM_PWR_DIS; \
type REGAMMA_LUT_LIGHT_SLEEP_DIS; \
type DCP_LUT_LIGHT_SLEEP_DIS; \
type REGAMMA_CNTLA_EXP_REGION_START; \
type REGAMMA_CNTLA_EXP_REGION_START_SEGMENT; \
type REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE; \
type REGAMMA_CNTLA_EXP_REGION_END; \
type REGAMMA_CNTLA_EXP_REGION_END_BASE; \
type REGAMMA_CNTLA_EXP_REGION_END_SLOPE; \
type REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET; \
type REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS; \
type REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET; \
type REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS; \
type DCP_REGAMMA_MEM_PWR_STATE; \
type REGAMMA_LUT_MEM_PWR_STATE; \
type REGAMMA_LUT_WRITE_EN_MASK; \
type GRPH_REGAMMA_MODE; \
type SCL_MODE; \
type SCL_BYPASS_MODE; \
type SCL_PSCL_EN; \
type SCL_H_NUM_OF_TAPS; \
type SCL_V_NUM_OF_TAPS; \
type SCL_BOUNDARY_MODE; \
type EXT_OVERSCAN_LEFT; \
type EXT_OVERSCAN_RIGHT; \
type EXT_OVERSCAN_TOP; \
type EXT_OVERSCAN_BOTTOM; \
type SCL_COEFF_MEM_PWR_DIS; \
type SCL_COEFF_MEM_PWR_STATE; \
type SCL_C_RAM_FILTER_TYPE; \
type SCL_C_RAM_PHASE; \
type SCL_C_RAM_TAP_PAIR_IDX; \
type SCL_C_RAM_EVEN_TAP_COEF_EN; \
type SCL_C_RAM_EVEN_TAP_COEF; \
type SCL_C_RAM_ODD_TAP_COEF_EN; \
type SCL_C_RAM_ODD_TAP_COEF; \
type VIEWPORT_X_START; \
type VIEWPORT_Y_START; \
type VIEWPORT_HEIGHT; \
type VIEWPORT_WIDTH; \
type SCL_H_SCALE_RATIO; \
type SCL_V_SCALE_RATIO; \
type SCL_H_INIT_INT; \
type SCL_H_INIT_FRAC; \
type SCL_H_INIT_INT_RGB_Y; \
type SCL_H_INIT_FRAC_RGB_Y; \
type SCL_H_INIT_INT_CBCR; \
type SCL_H_INIT_FRAC_CBCR; \
type SCL_V_INIT_INT; \
type SCL_V_INIT_FRAC; \
type DC_LB_MEMORY_CONFIG; \
type DC_LB_MEM_SIZE; \
type LB_MEMORY_CONFIG; \
type LB_MEMORY_SIZE; \
type SCL_V_2TAP_HARDCODE_COEF_EN; \
type SCL_H_2TAP_HARDCODE_COEF_EN; \
type SCL_V_FILTER_PICK_NEAREST; \
type SCL_H_FILTER_PICK_NEAREST; \
type SCL_COEF_UPDATE_COMPLETE; \
type ALPHA_EN
struct dce_transform_shift {
XFM_REG_FIELD_LIST(uint8_t);
};
struct dce_transform_mask {
XFM_REG_FIELD_LIST(uint32_t);
};
struct dce_transform_registers {
#if defined(CONFIG_DRM_AMD_DC_SI)
uint32_t DATA_FORMAT;
#endif
uint32_t LB_DATA_FORMAT;
uint32_t GAMUT_REMAP_CONTROL;
uint32_t GAMUT_REMAP_C11_C12;
uint32_t GAMUT_REMAP_C13_C14;
uint32_t GAMUT_REMAP_C21_C22;
uint32_t GAMUT_REMAP_C23_C24;
uint32_t GAMUT_REMAP_C31_C32;
uint32_t GAMUT_REMAP_C33_C34;
uint32_t OUTPUT_CSC_C11_C12;
uint32_t OUTPUT_CSC_C13_C14;
uint32_t OUTPUT_CSC_C21_C22;
uint32_t OUTPUT_CSC_C23_C24;
uint32_t OUTPUT_CSC_C31_C32;
uint32_t OUTPUT_CSC_C33_C34;
uint32_t OUTPUT_CSC_CONTROL;
uint32_t DCFE_MEM_LIGHT_SLEEP_CNTL;
uint32_t REGAMMA_CNTLA_START_CNTL;
uint32_t REGAMMA_CNTLA_SLOPE_CNTL;
uint32_t REGAMMA_CNTLA_END_CNTL1;
uint32_t REGAMMA_CNTLA_END_CNTL2;
uint32_t REGAMMA_CNTLA_REGION_0_1;
uint32_t REGAMMA_CNTLA_REGION_2_3;
uint32_t REGAMMA_CNTLA_REGION_4_5;
uint32_t REGAMMA_CNTLA_REGION_6_7;
uint32_t REGAMMA_CNTLA_REGION_8_9;
uint32_t REGAMMA_CNTLA_REGION_10_11;
uint32_t REGAMMA_CNTLA_REGION_12_13;
uint32_t REGAMMA_CNTLA_REGION_14_15;
uint32_t REGAMMA_LUT_WRITE_EN_MASK;
uint32_t REGAMMA_LUT_INDEX;
uint32_t REGAMMA_LUT_DATA;
uint32_t REGAMMA_CONTROL;
uint32_t DENORM_CONTROL;
uint32_t DCP_SPATIAL_DITHER_CNTL;
uint32_t OUT_ROUND_CONTROL;
uint32_t OUT_CLAMP_CONTROL_R_CR;
uint32_t OUT_CLAMP_CONTROL_G_Y;
uint32_t OUT_CLAMP_CONTROL_B_CB;
uint32_t SCL_MODE;
uint32_t SCL_TAP_CONTROL;
uint32_t SCL_CONTROL;
uint32_t SCL_BYPASS_CONTROL;
uint32_t EXT_OVERSCAN_LEFT_RIGHT;
uint32_t EXT_OVERSCAN_TOP_BOTTOM;
uint32_t SCL_VERT_FILTER_CONTROL;
uint32_t SCL_HORZ_FILTER_CONTROL;
uint32_t DCFE_MEM_PWR_CTRL;
uint32_t DCFE_MEM_PWR_STATUS;
uint32_t SCL_COEF_RAM_SELECT;
uint32_t SCL_COEF_RAM_TAP_DATA;
uint32_t VIEWPORT_START;
uint32_t VIEWPORT_SIZE;
uint32_t SCL_HORZ_FILTER_SCALE_RATIO;
uint32_t SCL_VERT_FILTER_SCALE_RATIO;
uint32_t SCL_HORZ_FILTER_INIT;
#if defined(CONFIG_DRM_AMD_DC_SI)
uint32_t SCL_SCALER_ENABLE;
uint32_t SCL_HORZ_FILTER_INIT_RGB_LUMA;
uint32_t SCL_HORZ_FILTER_INIT_CHROMA;
#endif
uint32_t SCL_VERT_FILTER_INIT;
uint32_t SCL_AUTOMATIC_MODE_CONTROL;
#if defined(CONFIG_DRM_AMD_DC_SI)
uint32_t DC_LB_MEMORY_SPLIT;
uint32_t DC_LB_MEM_SIZE;
#endif
uint32_t LB_MEMORY_CTRL;
uint32_t SCL_UPDATE;
uint32_t SCL_F_SHARP_CONTROL;
};
struct init_int_and_frac {
uint32_t integer;
uint32_t fraction;
};
struct scl_ratios_inits {
uint32_t h_int_scale_ratio;
uint32_t v_int_scale_ratio;
struct init_int_and_frac h_init;
struct init_int_and_frac v_init;
};
#if defined(CONFIG_DRM_AMD_DC_SI)
struct sclh_ratios_inits {
uint32_t h_int_scale_ratio;
uint32_t v_int_scale_ratio;
struct init_int_and_frac h_init_luma;
struct init_int_and_frac h_init_chroma;
struct init_int_and_frac v_init;
};
#endif
enum ram_filter_type {
FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */
FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */
FILTER_TYPE_RGB_Y_HORIZONTAL = 2, /* 1 - RGB/Y Horizontal filter */
FILTER_TYPE_CBCR_HORIZONTAL = 3, /* 3 - CbCr Horizontal filter */
FILTER_TYPE_ALPHA_VERTICAL = 4, /* 4 - Alpha Vertical filter. */
FILTER_TYPE_ALPHA_HORIZONTAL = 5, /* 5 - Alpha Horizontal filter. */
};
struct dce_transform {
struct transform base;
const struct dce_transform_registers *regs;
const struct dce_transform_shift *xfm_shift;
const struct dce_transform_mask *xfm_mask;
const uint16_t *filter_v;
const uint16_t *filter_h;
const uint16_t *filter_v_c;
const uint16_t *filter_h_c;
int lb_pixel_depth_supported;
int lb_memory_size;
int lb_bits_per_entry;
bool prescaler_on;
};
void dce_transform_construct(struct dce_transform *xfm_dce,
struct dc_context *ctx,
uint32_t inst,
const struct dce_transform_registers *regs,
const struct dce_transform_shift *xfm_shift,
const struct dce_transform_mask *xfm_mask);
#if defined(CONFIG_DRM_AMD_DC_SI)
void dce60_transform_construct(struct dce_transform *xfm_dce,
struct dc_context *ctx,
uint32_t inst,
const struct dce_transform_registers *regs,
const struct dce_transform_shift *xfm_shift,
const struct dce_transform_mask *xfm_mask);
#endif
bool dce_transform_get_optimal_number_of_taps(
struct transform *xfm,
struct scaler_data *scl_data,
const struct scaling_taps *in_taps);
void dce110_opp_set_csc_adjustment(
struct transform *xfm,
const struct out_csc_color_matrix *tbl_entry);
void dce110_opp_set_csc_default(
struct transform *xfm,
const struct default_adjustment *default_adjust);
/* REGAMMA RELATED */
void dce110_opp_power_on_regamma_lut(
struct transform *xfm,
bool power_on);
void dce110_opp_program_regamma_pwl(
struct transform *xfm,
const struct pwl_params *params);
void dce110_opp_set_regamma_mode(struct transform *xfm,
enum opp_regamma mode);
#endif /* _DCE_DCE_TRANSFORM_H_ */
@@ -0,0 +1,245 @@
/*
* Copyright 2019 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_abm.h"
#include "dmub_abm_lcd.h"
#include "dc.h"
#include "core_types.h"
#include "dmub_cmd.h"
#include "dc_dmub_srv.h"
#include "dmub/dmub_srv.h"
#define TO_DMUB_ABM(abm)\
container_of(abm, struct dce_abm, base)
#define ABM_FEATURE_NO_SUPPORT 0
#define ABM_LCD_SUPPORT 1
static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst)
{
struct dc_context *dc = abm->ctx;
struct dc_link *edp_links[MAX_NUM_EDP];
unsigned int i, edp_num;
unsigned int ret = ABM_FEATURE_NO_SUPPORT;
dc_get_edp_links(dc->dc, edp_links, &edp_num);
for (i = 0; i < edp_num; i++) {
if (panel_inst == i)
break;
}
if (i < edp_num) {
ret = ABM_LCD_SUPPORT;
}
return ret;
}
static void dmub_abm_init_ex(struct abm *abm, uint32_t backlight, uint32_t user_level)
{
dmub_abm_init(abm, backlight, user_level);
}
static unsigned int dmub_abm_get_current_backlight_ex(struct abm *abm)
{
dc_allow_idle_optimizations(abm->ctx->dc, false);
return dmub_abm_get_current_backlight(abm);
}
static unsigned int dmub_abm_get_target_backlight_ex(struct abm *abm)
{
dc_allow_idle_optimizations(abm->ctx->dc, false);
return dmub_abm_get_target_backlight(abm);
}
static bool dmub_abm_set_level_ex(struct abm *abm, uint32_t level)
{
bool ret = false;
unsigned int feature_support, i;
uint8_t panel_mask0 = 0;
for (i = 0; i < MAX_NUM_EDP; i++) {
feature_support = abm_feature_support(abm, i);
if (feature_support == ABM_LCD_SUPPORT)
panel_mask0 |= (0x01 << i);
}
if (panel_mask0)
ret = dmub_abm_set_level(abm, level, panel_mask0);
return ret;
}
static bool dmub_abm_init_config_ex(struct abm *abm,
const char *src,
unsigned int bytes,
unsigned int inst)
{
unsigned int feature_support;
feature_support = abm_feature_support(abm, inst);
if (feature_support == ABM_LCD_SUPPORT)
dmub_abm_init_config(abm, src, bytes, inst);
return true;
}
static bool dmub_abm_set_pause_ex(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
{
bool ret = false;
unsigned int feature_support;
feature_support = abm_feature_support(abm, panel_inst);
if (feature_support == ABM_LCD_SUPPORT)
ret = dmub_abm_set_pause(abm, pause, panel_inst, stream_inst);
return ret;
}
/*****************************************************************************
* dmub_abm_save_restore_ex() - calls dmub_abm_save_restore for preserving DMUB's
* Varibright states for LCD only. OLED is TBD
* @abm: used to check get dc context
* @panel_inst: panel instance index
* @pData: contains command to pause/un-pause abm and abm parameters
*
*
***************************************************************************/
static bool dmub_abm_save_restore_ex(
struct abm *abm,
unsigned int panel_inst,
struct abm_save_restore *pData)
{
bool ret = false;
unsigned int feature_support;
struct dc_context *dc = abm->ctx;
feature_support = abm_feature_support(abm, panel_inst);
if (feature_support == ABM_LCD_SUPPORT)
ret = dmub_abm_save_restore(dc, panel_inst, pData);
return ret;
}
static bool dmub_abm_set_pipe_ex(struct abm *abm,
uint32_t otg_inst,
uint32_t option,
uint32_t panel_inst,
uint32_t pwrseq_inst)
{
bool ret = false;
unsigned int feature_support;
feature_support = abm_feature_support(abm, panel_inst);
if (feature_support == ABM_LCD_SUPPORT)
ret = dmub_abm_set_pipe(abm, otg_inst, option, panel_inst, pwrseq_inst);
return ret;
}
static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm,
unsigned int backlight_pwm_u16_16,
unsigned int frame_ramp,
unsigned int controller_id,
unsigned int panel_inst)
{
(void)controller_id;
bool ret = false;
unsigned int feature_support;
feature_support = abm_feature_support(abm, panel_inst);
if (feature_support == ABM_LCD_SUPPORT)
ret = dmub_abm_set_backlight_level(abm, backlight_pwm_u16_16, frame_ramp, panel_inst);
return ret;
}
static const struct abm_funcs abm_funcs = {
.abm_init = dmub_abm_init_ex,
.set_abm_level = dmub_abm_set_level_ex,
.get_current_backlight = dmub_abm_get_current_backlight_ex,
.get_target_backlight = dmub_abm_get_target_backlight_ex,
.init_abm_config = dmub_abm_init_config_ex,
.set_abm_pause = dmub_abm_set_pause_ex,
.save_restore = dmub_abm_save_restore_ex,
.set_pipe_ex = dmub_abm_set_pipe_ex,
.set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm_ex,
};
static void dmub_abm_construct(
struct dce_abm *abm_dce,
struct dc_context *ctx,
const struct dce_abm_registers *regs,
const struct dce_abm_shift *abm_shift,
const struct dce_abm_mask *abm_mask)
{
struct abm *base = &abm_dce->base;
base->ctx = ctx;
base->funcs = &abm_funcs;
base->dmcu_is_running = false;
abm_dce->regs = regs;
abm_dce->abm_shift = abm_shift;
abm_dce->abm_mask = abm_mask;
}
struct abm *dmub_abm_create(
struct dc_context *ctx,
const struct dce_abm_registers *regs,
const struct dce_abm_shift *abm_shift,
const struct dce_abm_mask *abm_mask)
{
if (ctx->dc->caps.dmcub_support) {
struct dce_abm *abm_dce = kzalloc_obj(*abm_dce);
if (abm_dce == NULL) {
BREAK_TO_DEBUGGER();
return NULL;
}
dmub_abm_construct(abm_dce, ctx, regs, abm_shift, abm_mask);
return &abm_dce->base;
}
return NULL;
}
void dmub_abm_destroy(struct abm **abm)
{
struct dce_abm *abm_dce = TO_DMUB_ABM(*abm);
kfree(abm_dce);
*abm = NULL;
}
@@ -0,0 +1,40 @@
/*
* Copyright 2019 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_ABM_H__
#define __DMUB_ABM_H__
#include "abm.h"
#include "dce_abm.h"
struct abm *dmub_abm_create(
struct dc_context *ctx,
const struct dce_abm_registers *regs,
const struct dce_abm_shift *abm_shift,
const struct dce_abm_mask *abm_mask);
void dmub_abm_destroy(struct abm **abm);
#endif
@@ -0,0 +1,319 @@
/*
* Copyright 2019 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_abm.h"
#include "dmub_abm_lcd.h"
#include "dce_abm.h"
#include "dc.h"
#include "dc_dmub_srv.h"
#include "dmub/dmub_srv.h"
#include "core_types.h"
#include "dm_services.h"
#include "reg_helper.h"
#include "fixed31_32.h"
#include "atom.h"
#define TO_DMUB_ABM(abm)\
container_of(abm, struct dce_abm, base)
#define REG(reg) \
(dce_abm->regs->reg)
#undef FN
#define FN(reg_name, field_name) \
dce_abm->abm_shift->field_name, dce_abm->abm_mask->field_name
#define CTX \
dce_abm->base.ctx
#define DISABLE_ABM_IMMEDIATELY 255
static void dmub_abm_enable_fractional_pwm(struct dc_context *dc)
{
union dmub_rb_cmd cmd;
uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0;
uint32_t edp_id_count = dc->dc_edp_id_count;
unsigned int i;
uint8_t panel_mask = 0;
for (i = 0; i < edp_id_count; i++)
panel_mask |= 0x01 << i;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM;
cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC;
cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm;
cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask;
cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level)
{
struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x3);
REG_WRITE(DC_ABM1_HG_SAMPLE_RATE, 0x1);
REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x3);
REG_WRITE(DC_ABM1_LS_SAMPLE_RATE, 0x1);
REG_WRITE(BL1_PWM_BL_UPDATE_SAMPLE_RATE, 0x1);
REG_SET_3(DC_ABM1_HG_MISC_CTRL, 0,
ABM1_HG_NUM_OF_BINS_SEL, 0,
ABM1_HG_VMAX_SEL, 1,
ABM1_HG_BIN_BITWIDTH_SIZE_SEL, 0);
REG_SET_3(DC_ABM1_IPCSC_COEFF_SEL, 0,
ABM1_IPCSC_COEFF_SEL_R, 2,
ABM1_IPCSC_COEFF_SEL_G, 4,
ABM1_IPCSC_COEFF_SEL_B, 2);
REG_UPDATE(BL1_PWM_CURRENT_ABM_LEVEL,
BL1_PWM_CURRENT_ABM_LEVEL, backlight);
REG_UPDATE(BL1_PWM_TARGET_ABM_LEVEL,
BL1_PWM_TARGET_ABM_LEVEL, backlight);
REG_UPDATE(BL1_PWM_USER_LEVEL,
BL1_PWM_USER_LEVEL, user_level);
REG_UPDATE_2(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES,
ABM1_LS_MIN_PIXEL_VALUE_THRES, 0,
ABM1_LS_MAX_PIXEL_VALUE_THRES, 1000);
REG_SET_3(DC_ABM1_HGLS_REG_READ_PROGRESS, 0,
ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, 1,
ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, 1,
ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1);
dmub_abm_enable_fractional_pwm(abm->ctx);
}
unsigned int dmub_abm_get_current_backlight(struct abm *abm)
{
struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
unsigned int backlight = REG_READ(BL1_PWM_CURRENT_ABM_LEVEL);
/* return backlight in hardware format which is unsigned 17 bits, with
* 1 bit integer and 16 bit fractional
*/
return backlight;
}
unsigned int dmub_abm_get_target_backlight(struct abm *abm)
{
struct dce_abm *dce_abm = TO_DMUB_ABM(abm);
unsigned int backlight = REG_READ(BL1_PWM_TARGET_ABM_LEVEL);
/* return backlight in hardware format which is unsigned 17 bits, with
* 1 bit integer and 16 bit fractional
*/
return backlight;
}
bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_set_level.header.type = DMUB_CMD__ABM;
cmd.abm_set_level.header.sub_type = DMUB_CMD__ABM_SET_LEVEL;
cmd.abm_set_level.abm_set_level_data.level = level;
cmd.abm_set_level.abm_set_level_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask;
cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
void dmub_abm_init_config(struct abm *abm,
const char *src,
unsigned int bytes,
unsigned int inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
uint8_t panel_mask = 0x01 << inst;
// TODO: Optimize by only reading back final 4 bytes
dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
// Copy iramtable into cw7
memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes);
memset(&cmd, 0, sizeof(cmd));
// Fw will copy from cw7 to fw_state
cmd.abm_init_config.header.type = DMUB_CMD__ABM;
cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG;
cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
cmd.abm_init_config.abm_init_config_data.bytes = (uint16_t)bytes;
cmd.abm_init_config.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
cmd.abm_init_config.abm_init_config_data.panel_mask = panel_mask;
cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
{
(void)stream_inst;
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
uint8_t panel_mask = 0x01 << panel_inst;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_pause.header.type = DMUB_CMD__ABM;
cmd.abm_pause.header.sub_type = DMUB_CMD__ABM_PAUSE;
cmd.abm_pause.abm_pause_data.enable = pause;
cmd.abm_pause.abm_pause_data.panel_mask = panel_mask;
cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
/*****************************************************************************
* dmub_abm_save_restore() - dmub interface for abm save+pause and restore+
* un-pause
* @dc: dc context
* @panel_inst: panel instance index
* @pData: contains command to pause/un-pause abm and exchange abm parameters
*
* When called Pause will get abm data and store in pData, and un-pause will
* set/apply abm data stored in pData.
*
*****************************************************************************/
bool dmub_abm_save_restore(
struct dc_context *dc,
unsigned int panel_inst,
struct abm_save_restore *pData)
{
union dmub_rb_cmd cmd;
uint8_t panel_mask = 0x01 << panel_inst;
unsigned int bytes = sizeof(struct abm_save_restore);
// TODO: Optimize by only reading back final 4 bytes
dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
// Copy iramtable into cw7
memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)pData, bytes);
memset(&cmd, 0, sizeof(cmd));
cmd.abm_save_restore.header.type = DMUB_CMD__ABM;
cmd.abm_save_restore.header.sub_type = DMUB_CMD__ABM_SAVE_RESTORE;
cmd.abm_save_restore.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr;
cmd.abm_save_restore.abm_init_config_data.bytes = (uint16_t)bytes;
cmd.abm_save_restore.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
cmd.abm_save_restore.abm_init_config_data.panel_mask = panel_mask;
cmd.abm_save_restore.header.payload_bytes =
sizeof(struct dmub_rb_cmd_abm_save_restore) - sizeof(struct dmub_cmd_header);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
// Copy iramtable data into local structure
memcpy((void *)pData, dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, bytes);
return true;
}
bool dmub_abm_set_pipe(struct abm *abm,
uint32_t otg_inst,
uint32_t option,
uint32_t panel_inst,
uint32_t pwrseq_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
uint8_t ramping_boundary = 0xFF;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_set_pipe.header.type = DMUB_CMD__ABM;
cmd.abm_set_pipe.header.sub_type = DMUB_CMD__ABM_SET_PIPE;
cmd.abm_set_pipe.abm_set_pipe_data.otg_inst = (uint8_t)otg_inst;
cmd.abm_set_pipe.abm_set_pipe_data.pwrseq_inst = (uint8_t)pwrseq_inst;
cmd.abm_set_pipe.abm_set_pipe_data.set_pipe_option = (uint8_t)option;
cmd.abm_set_pipe.abm_set_pipe_data.panel_inst = (uint8_t)panel_inst;
cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary;
cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
bool dmub_abm_set_backlight_level(struct abm *abm,
unsigned int backlight_pwm_u16_16,
unsigned int frame_ramp,
unsigned int panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_set_backlight.header.type = DMUB_CMD__ABM;
cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT;
cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp;
cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16;
cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1;
cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst);
cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
bool dmub_abm_set_event(struct abm *abm, unsigned int scaling_enable, unsigned int scaling_strength_map,
unsigned int panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
memset(&cmd, 0, sizeof(cmd));
cmd.abm_set_event.header.type = DMUB_CMD__ABM;
cmd.abm_set_event.header.sub_type = DMUB_CMD__ABM_SET_EVENT;
cmd.abm_set_event.abm_set_event_data.vb_scaling_enable = (uint8_t)scaling_enable;
cmd.abm_set_event.abm_set_event_data.vb_scaling_strength_mapping = scaling_strength_map;
cmd.abm_set_event.abm_set_event_data.panel_mask = (1<<panel_inst);
cmd.abm_set_event.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_event_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
@@ -0,0 +1,54 @@
/*
* Copyright 2019 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_ABM_LCD_H__
#define __DMUB_ABM_LCD_H__
#include "abm.h"
struct abm_save_restore;
void dmub_abm_init(struct abm *abm, uint32_t backlight, uint32_t user_level);
bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask);
unsigned int dmub_abm_get_current_backlight(struct abm *abm);
unsigned int dmub_abm_get_target_backlight(struct abm *abm);
void dmub_abm_init_config(struct abm *abm,
const char *src,
unsigned int bytes,
unsigned int inst);
bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst);
bool dmub_abm_save_restore(
struct dc_context *dc,
unsigned int panel_inst,
struct abm_save_restore *pData);
bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, uint32_t option, uint32_t panel_inst, uint32_t pwrseq_inst);
bool dmub_abm_set_backlight_level(struct abm *abm,
unsigned int backlight_pwm_u16_16,
unsigned int frame_ramp,
unsigned int panel_inst);
bool dmub_abm_set_event(struct abm *abm, unsigned int scaling_enable, unsigned int scaling_strength_map,
unsigned int panel_inst);
#endif
@@ -0,0 +1,125 @@
/*
* Copyright 2019 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_hw_lock_mgr.h"
#include "dc_dmub_srv.h"
#include "dc_types.h"
#include "core_types.h"
static bool dmub_hw_lock_has_inbox0_lock(const struct dc *dc)
{
return dc->ctx && dc->ctx->dmub_srv &&
dc->hwss.dmub_hw_control_lock &&
dc->hwss.dmub_hw_control_lock_fast &&
dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support;
}
void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv,
bool lock,
union dmub_hw_lock_flags *hw_locks,
struct dmub_hw_lock_inst_flags *inst_flags)
{
union dmub_rb_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.lock_hw.header.type = DMUB_CMD__HW_LOCK;
cmd.lock_hw.header.sub_type = 0;
cmd.lock_hw.header.payload_bytes = sizeof(struct dmub_cmd_lock_hw_data);
cmd.lock_hw.lock_hw_data.client = HW_LOCK_CLIENT_DRIVER;
cmd.lock_hw.lock_hw_data.lock = lock;
cmd.lock_hw.lock_hw_data.hw_locks.u8All = hw_locks->u8All;
memcpy(&cmd.lock_hw.lock_hw_data.inst_flags, inst_flags, sizeof(struct dmub_hw_lock_inst_flags));
if (!lock)
cmd.lock_hw.lock_hw_data.should_release = 1;
dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
union dmub_inbox0_cmd_lock_hw hw_lock_cmd)
{
union dmub_inbox0_data_register data = { 0 };
data.inbox0_cmd_lock_hw = hw_lock_cmd;
dc_dmub_srv_clear_inbox0_ack(dmub_srv);
dc_dmub_srv_send_inbox0_cmd(dmub_srv, data);
dc_dmub_srv_wait_for_inbox0_ack(dmub_srv);
}
bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct dc_link *link)
{
if (!link)
return false;
if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
return true;
if (link->replay_settings.replay_feature_enabled && dc_is_embedded_signal(link->connector_signal))
return true;
if (link->psr_settings.psr_version == DC_PSR_VERSION_1) {
struct dc_link *edp_links[MAX_NUM_EDP];
unsigned int edp_num;
dc_get_edp_links(dc, edp_links, &edp_num);
if (edp_num == 1)
return true;
}
return false;
}
bool dmub_hw_lock_mgr_does_context_require_lock(const struct dc *dc, const struct dc_state *context)
{
if (!context)
return false;
for (int i = 0; i < context->stream_count; i++) {
const struct dc_link *link = context->streams[i]->link;
if (dmub_hw_lock_mgr_does_link_require_lock(dc, link))
return true;
}
return false;
}
bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link)
{
/* ASIC doesn't support DMUB */
if (!dc->ctx->dmub_srv)
return false;
if (dc->ctx->dce_version >= DCN_VERSION_4_01)
return false;
if (dmub_hw_lock_has_inbox0_lock(dc))
return false;
return dmub_hw_lock_mgr_does_link_require_lock(dc, link);
}
bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link)
{
return dmub_hw_lock_has_inbox0_lock(dc) && dmub_hw_lock_mgr_does_link_require_lock(dc, link);
}
@@ -0,0 +1,83 @@
/*
* Copyright 2012-16 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_HW_LOCK_MGR_H_
#define _DMUB_HW_LOCK_MGR_H_
#include "dc_dmub_srv.h"
#include "core_types.h"
void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv,
bool lock,
union dmub_hw_lock_flags *hw_locks,
struct dmub_hw_lock_inst_flags *inst_flags);
void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
union dmub_inbox0_cmd_lock_hw hw_lock_cmd);
/**
* should_use_dmub_inbox1_lock() - Checks if the DMCUB hardware lock via inbox1 should be used.
*
* @dc: pointer to DC object
* @link: optional pointer to the link object to check for enabled link features
*
* Return: true if the inbox1 lock should be used, false otherwise
*/
bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link);
/**
* dmub_hw_lock_mgr_does_link_require_lock() - Returns true if the link has a feature that needs the HW lock.
*
* @dc: Pointer to DC object
* @link: The link to check
*
* Return: true if the link has a feature that needs the HW lock, false otherwise
*/
bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct dc_link *link);
/**
* dmub_hw_lock_mgr_does_context_require_lock() - Returns true if the context has any stream that needs the HW lock.
*
* @dc: Pointer to DC object
* @context: The context to check
*
* Return: true if the context has any stream that needs the HW lock, false otherwise
*/
bool dmub_hw_lock_mgr_does_context_require_lock(const struct dc *dc, const struct dc_state *context);
/**
* should_use_dmub_inbox0_lock_for_link() - Checks if the inbox0 interlock with DMU should be used.
*
* Is not functionally equivalent to inbox1 as DMUB will not own programming of the relevant locking
* registers.
*
* @dc: pointer to DC object
* @link: optional pointer to the link object to check for enabled link features
*
* Return: true if the inbox0 lock should be used, false otherwise
*/
bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link);
#endif /*_DMUB_HW_LOCK_MGR_H_ */
@@ -0,0 +1,52 @@
/*
* Copyright 2020 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*/
#include "dc.h"
#include "dc_dmub_srv.h"
#include "dmub_outbox.h"
#include "dmub/inc/dmub_cmd.h"
/*
* Function: dmub_enable_outbox_notification
*
* @brief
* Sends inbox cmd to dmub for enabling outbox notifications to x86.
*
* @param
* [in] dmub_srv: dmub_srv structure
*/
void dmub_enable_outbox_notification(struct dc_dmub_srv *dmub_srv)
{
union dmub_rb_cmd cmd;
memset(&cmd, 0x0, sizeof(cmd));
cmd.outbox1_enable.header.type = DMUB_CMD__OUTBOX1_ENABLE;
cmd.outbox1_enable.header.sub_type = 0;
cmd.outbox1_enable.header.payload_bytes =
sizeof(cmd.outbox1_enable) -
sizeof(cmd.outbox1_enable.header);
cmd.outbox1_enable.enable = true;
dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
@@ -0,0 +1,33 @@
/*
* Copyright 2020 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_OUTBOX_H_
#define _DMUB_OUTBOX_H_
struct dc_dmub_srv;
void dmub_enable_outbox_notification(struct dc_dmub_srv *dmub_srv);
#endif /* _DMUB_OUTBOX_H_ */
@@ -0,0 +1,510 @@
/*
* Copyright 2019 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_psr.h"
#include "dc.h"
#include "dc_dmub_srv.h"
#include "dmub/dmub_srv.h"
#include "core_types.h"
#define DC_TRACE_LEVEL_MESSAGE(...) do {} while (0) /* do nothing */
#define MAX_PIPES 6
static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3};
static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5};
static const uint8_t DP_SINK_DEVICE_STR_ID_3[] = {0x42, 0x61, 0x6c, 0x73, 0x61};
/*
* Convert dmcub psr state to dmcu psr state.
*/
static enum dc_psr_state convert_psr_state(uint32_t raw_state)
{
enum dc_psr_state state = PSR_STATE0;
if (raw_state == 0)
state = PSR_STATE0;
else if (raw_state == 0x10)
state = PSR_STATE1;
else if (raw_state == 0x11)
state = PSR_STATE1a;
else if (raw_state == 0x20)
state = PSR_STATE2;
else if (raw_state == 0x21)
state = PSR_STATE2a;
else if (raw_state == 0x22)
state = PSR_STATE2b;
else if (raw_state == 0x30)
state = PSR_STATE3;
else if (raw_state == 0x31)
state = PSR_STATE3Init;
else if (raw_state == 0x40)
state = PSR_STATE4;
else if (raw_state == 0x41)
state = PSR_STATE4a;
else if (raw_state == 0x42)
state = PSR_STATE4b;
else if (raw_state == 0x43)
state = PSR_STATE4c;
else if (raw_state == 0x44)
state = PSR_STATE4d;
else if (raw_state == 0x50)
state = PSR_STATE5;
else if (raw_state == 0x51)
state = PSR_STATE5a;
else if (raw_state == 0x52)
state = PSR_STATE5b;
else if (raw_state == 0x53)
state = PSR_STATE5c;
else if (raw_state == 0x4A)
state = PSR_STATE4_FULL_FRAME;
else if (raw_state == 0x4B)
state = PSR_STATE4a_FULL_FRAME;
else if (raw_state == 0x4C)
state = PSR_STATE4b_FULL_FRAME;
else if (raw_state == 0x4D)
state = PSR_STATE4c_FULL_FRAME;
else if (raw_state == 0x4E)
state = PSR_STATE4_FULL_FRAME_POWERUP;
else if (raw_state == 0x4F)
state = PSR_STATE4_FULL_FRAME_HW_LOCK;
else if (raw_state == 0x60)
state = PSR_STATE_HWLOCK_MGR;
else if (raw_state == 0x61)
state = PSR_STATE_POLLVUPDATE;
else if (raw_state == 0x62)
state = PSR_STATE_RELEASE_HWLOCK_MGR_FULL_FRAME;
else
state = PSR_STATE_INVALID;
return state;
}
/*
* Get PSR state from firmware.
*/
static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst)
{
uint32_t raw_state = 0;
uint32_t retry_count = 0;
do {
// Send gpint command and wait for ack
if (dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_PSR_STATE, panel_inst, &raw_state,
DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
*state = convert_psr_state(raw_state);
} else {
// Return invalid state when GPINT times out
*state = PSR_STATE_INVALID;
}
} while (++retry_count <= 1000 && *state == PSR_STATE_INVALID);
// Assert if max retry hit
if (retry_count >= 1000 && *state == PSR_STATE_INVALID) {
ASSERT(0);
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
WPP_BIT_FLAG_Firmware_PsrState,
"Unable to get PSR state from FW.");
} else
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
WPP_BIT_FLAG_Firmware_PsrState,
"Got PSR state from FW. PSR state: %d, Retry count: %d",
*state, retry_count);
}
/*
* Set PSR version.
*/
static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream, uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED)
return false;
memset(&cmd, 0, sizeof(cmd));
cmd.psr_set_version.header.type = DMUB_CMD__PSR;
cmd.psr_set_version.header.sub_type = DMUB_CMD__PSR_SET_VERSION;
switch (stream->link->psr_settings.psr_version) {
case DC_PSR_VERSION_1:
cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_1;
break;
case DC_PSR_VERSION_SU_1:
cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_SU_1;
break;
case DC_PSR_VERSION_UNSUPPORTED:
default:
cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED;
break;
}
if (cmd.psr_set_version.psr_set_version_data.version == PSR_VERSION_UNSUPPORTED)
return false;
cmd.psr_set_version.psr_set_version_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst;
cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
/*
* Enable/Disable PSR.
*/
static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
uint32_t retry_count;
enum dc_psr_state state = PSR_STATE0;
memset(&cmd, 0, sizeof(cmd));
cmd.psr_enable.header.type = DMUB_CMD__PSR;
cmd.psr_enable.data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
cmd.psr_enable.data.panel_inst = panel_inst;
if (enable)
cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_ENABLE;
else
cmd.psr_enable.header.sub_type = DMUB_CMD__PSR_DISABLE;
cmd.psr_enable.header.payload_bytes = 0; // Send header only
dc_wake_and_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
/* Below loops 1000 x 500us = 500 ms.
* Exit PSR may need to wait 1-2 frames to power up. Timeout after at
* least a few frames. Should never hit the max retry assert below.
*/
if (wait) {
for (retry_count = 0; retry_count <= 1000; retry_count++) {
dmub_psr_get_state(dmub, &state, panel_inst);
if (enable) {
if (state != PSR_STATE0)
break;
} else {
if (state == PSR_STATE0)
break;
}
/* must *not* be fsleep - this can be called from high irq levels */
udelay(500);
}
/* assert if max retry hit */
if (retry_count >= 1000)
ASSERT(0);
}
}
/*
* Set PSR level.
*/
static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
enum dc_psr_state state = PSR_STATE0;
struct dc_context *dc = dmub->ctx;
dmub_psr_get_state(dmub, &state, panel_inst);
if (state == PSR_STATE0)
return;
memset(&cmd, 0, sizeof(cmd));
cmd.psr_set_level.header.type = DMUB_CMD__PSR;
cmd.psr_set_level.header.sub_type = DMUB_CMD__PSR_SET_LEVEL;
cmd.psr_set_level.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_level_data);
cmd.psr_set_level.psr_set_level_data.psr_level = psr_level;
cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* Set PSR vtotal requirement for FreeSync PSR.
*/
static void dmub_psr_set_sink_vtotal_in_psr_active(struct dmub_psr *dmub,
uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
memset(&cmd, 0, sizeof(cmd));
cmd.psr_set_vtotal.header.type = DMUB_CMD__PSR;
cmd.psr_set_vtotal.header.sub_type = DMUB_CMD__SET_SINK_VTOTAL_IN_PSR_ACTIVE;
cmd.psr_set_vtotal.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_vtotal_data);
cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_idle = psr_vtotal_idle;
cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_su = psr_vtotal_su;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* Set PSR power optimization flags.
*/
static void dmub_psr_set_power_opt(struct dmub_psr *dmub, unsigned int power_opt, uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
memset(&cmd, 0, sizeof(cmd));
cmd.psr_set_power_opt.header.type = DMUB_CMD__PSR;
cmd.psr_set_power_opt.header.sub_type = DMUB_CMD__SET_PSR_POWER_OPT;
cmd.psr_set_power_opt.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_power_opt_data);
cmd.psr_set_power_opt.psr_set_power_opt_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt;
cmd.psr_set_power_opt.psr_set_power_opt_data.panel_inst = panel_inst;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* Setup PSR by programming phy registers and sending psr hw context values to firmware.
*/
static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
struct dc_link *link,
struct psr_context *psr_context,
uint8_t panel_inst)
{
union dmub_rb_cmd cmd = { 0 };
struct dc_context *dc = dmub->ctx;
struct dmub_cmd_psr_copy_settings_data *copy_settings_data
= &cmd.psr_copy_settings.psr_copy_settings_data;
struct pipe_ctx *pipe_ctx = NULL;
struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
int i = 0;
for (i = 0; i < MAX_PIPES; i++) {
if (res_ctx->pipe_ctx[i].stream &&
res_ctx->pipe_ctx[i].stream->link == link &&
res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
pipe_ctx = &res_ctx->pipe_ctx[i];
//TODO: refactor for multi edp support
break;
}
}
if (!pipe_ctx)
return false;
// First, set the psr version
if (!dmub_psr_set_version(dmub, pipe_ctx->stream, panel_inst))
return false;
// Program DP DPHY fast training registers
link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc,
psr_context->psrExitLinkTrainingRequired);
// Program DP_SEC_CNTL1 register to set transmission GPS0 line num and priority to high
link->link_enc->funcs->psr_program_secondary_packet(link->link_enc,
psr_context->sdpTransmitLineNumDeadline);
memset(&cmd, 0, sizeof(cmd));
cmd.psr_copy_settings.header.type = DMUB_CMD__PSR;
cmd.psr_copy_settings.header.sub_type = DMUB_CMD__PSR_COPY_SETTINGS;
cmd.psr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_psr_copy_settings_data);
// Hw insts
copy_settings_data->dpphy_inst = psr_context->transmitterId;
copy_settings_data->aux_inst = psr_context->channel;
copy_settings_data->digfe_inst = psr_context->engineId;
copy_settings_data->digbe_inst = psr_context->transmitterId;
copy_settings_data->mpcc_inst = pipe_ctx->plane_res.mpcc_inst;
if (pipe_ctx->plane_res.dpp)
copy_settings_data->dpp_inst = (uint8_t)pipe_ctx->plane_res.dpp->inst;
else
copy_settings_data->dpp_inst = 0;
if (pipe_ctx->stream_res.opp)
copy_settings_data->opp_inst = (uint8_t)pipe_ctx->stream_res.opp->inst;
else
copy_settings_data->opp_inst = 0;
if (pipe_ctx->stream_res.tg)
copy_settings_data->otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst;
else
copy_settings_data->otg_inst = 0;
// Misc
copy_settings_data->use_phy_fsm = link->ctx->dc->debug.psr_power_use_phy_fsm;
copy_settings_data->psr_level = (uint16_t)psr_context->psr_level.u32all;
copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations;
copy_settings_data->multi_disp_optimizations_en = psr_context->allow_multi_disp_optimizations;
copy_settings_data->frame_delay = (uint8_t)psr_context->frame_delay;
copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq;
copy_settings_data->init_sdp_deadline = (uint16_t)psr_context->sdpTransmitLineNumDeadline;
copy_settings_data->debug.u32All = 0;
copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR;
copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1;
copy_settings_data->debug.bitfields.force_full_frame_update = 0;
copy_settings_data->debug.bitfields.enable_ips_visual_confirm = dc->dc->debug.enable_ips_visual_confirm;
if (psr_context->su_granularity_required == 0)
copy_settings_data->su_y_granularity = 0;
else
copy_settings_data->su_y_granularity = psr_context->su_y_granularity;
copy_settings_data->line_capture_indication = 0;
copy_settings_data->line_time_in_us = psr_context->line_time_in_us;
copy_settings_data->rate_control_caps = psr_context->rate_control_caps;
copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled);
copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us;
copy_settings_data->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
copy_settings_data->panel_inst = panel_inst;
copy_settings_data->dsc_enable_status = (pipe_ctx->stream->timing.flags.DSC == 1);
/**
* WA for PSRSU+DSC on specific TCON, if DSC is enabled, force PSRSU as ffu mode(full frame update)
* Note that PSRSU+DSC is still under development.
*/
if (copy_settings_data->dsc_enable_status &&
link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 &&
!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1,
sizeof(DP_SINK_DEVICE_STR_ID_1)))
link->psr_settings.force_ffu_mode = 1;
copy_settings_data->force_ffu_mode = link->psr_settings.force_ffu_mode || psr_context->os_request_force_ffu;
if (((link->dpcd_caps.fec_cap.bits.FEC_CAPABLE &&
!link->dc->debug.disable_fec) &&
(link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
!link->panel_config.dsc.disable_dsc_edp &&
link->dc->caps.edp_dsc_support)) &&
link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 &&
(!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1,
sizeof(DP_SINK_DEVICE_STR_ID_1)) ||
!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_2,
sizeof(DP_SINK_DEVICE_STR_ID_2))))
copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 1;
else
copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 0;
if (link->psr_settings.psr_version == DC_PSR_VERSION_1 &&
link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_0022B9 &&
!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_3,
sizeof(DP_SINK_DEVICE_STR_ID_3))) {
copy_settings_data->poweroff_before_vertical_line = 16;
}
//WA for PSR1 on specific TCON, require frame delay for frame re-lock
copy_settings_data->relock_delay_frame_cnt = 0;
if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
copy_settings_data->relock_delay_frame_cnt = 2;
copy_settings_data->power_down_phy_before_disable_stream =
link->psr_settings.power_down_phy_before_disable_stream;
copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
/*
* Send command to PSR to force static ENTER and ignore all state changes until exit
*/
static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
memset(&cmd, 0, sizeof(cmd));
cmd.psr_force_static.psr_force_static_data.panel_inst = panel_inst;
cmd.psr_force_static.psr_force_static_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
cmd.psr_force_static.header.type = DMUB_CMD__PSR;
cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC;
cmd.psr_enable.header.payload_bytes = 0;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* Get PSR residency from firmware.
*/
static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency,
uint8_t panel_inst, enum psr_residency_mode mode)
{
uint16_t param = (uint16_t)(panel_inst << 8);
param |= mode;
/* Send gpint command and wait for ack */
dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__PSR_RESIDENCY, param, residency,
DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY);
}
static const struct dmub_psr_funcs psr_funcs = {
.psr_copy_settings = dmub_psr_copy_settings,
.psr_enable = dmub_psr_enable,
.psr_get_state = dmub_psr_get_state,
.psr_set_level = dmub_psr_set_level,
.psr_force_static = dmub_psr_force_static,
.psr_get_residency = dmub_psr_get_residency,
.psr_set_sink_vtotal_in_psr_active = dmub_psr_set_sink_vtotal_in_psr_active,
.psr_set_power_opt = dmub_psr_set_power_opt,
};
/*
* Construct PSR object.
*/
static void dmub_psr_construct(struct dmub_psr *psr, struct dc_context *ctx)
{
psr->ctx = ctx;
psr->funcs = &psr_funcs;
}
/*
* Allocate and initialize PSR object.
*/
struct dmub_psr *dmub_psr_create(struct dc_context *ctx)
{
struct dmub_psr *psr = kzalloc_obj(struct dmub_psr);
if (psr == NULL) {
BREAK_TO_DEBUGGER();
return NULL;
}
dmub_psr_construct(psr, ctx);
return psr;
}
/*
* Deallocate PSR object.
*/
void dmub_psr_destroy(struct dmub_psr **dmub)
{
kfree(*dmub);
*dmub = NULL;
}
@@ -0,0 +1,60 @@
/*
* Copyright 2012-16 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_PSR_H_
#define _DMUB_PSR_H_
#include "dc_types.h"
#include "dmub_cmd.h"
struct dc_link;
struct dmub_psr_funcs;
struct dmub_psr {
struct dc_context *ctx;
const struct dmub_psr_funcs *funcs;
};
struct dmub_psr_funcs {
bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link,
struct psr_context *psr_context, uint8_t panel_inst);
void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait,
uint8_t panel_inst);
void (*psr_get_state)(struct dmub_psr *dmub, enum dc_psr_state *dc_psr_state,
uint8_t panel_inst);
void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level,
uint8_t panel_inst);
void (*psr_force_static)(struct dmub_psr *dmub, uint8_t panel_inst);
void (*psr_get_residency)(struct dmub_psr *dmub, uint32_t *residency,
uint8_t panel_inst, enum psr_residency_mode mode);
void (*psr_set_sink_vtotal_in_psr_active)(struct dmub_psr *dmub,
uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su);
void (*psr_set_power_opt)(struct dmub_psr *dmub, unsigned int power_opt, uint8_t panel_inst);
};
struct dmub_psr *dmub_psr_create(struct dc_context *ctx);
void dmub_psr_destroy(struct dmub_psr **dmub);
#endif /* _DMUB_PSR_H_ */
@@ -0,0 +1,462 @@
// SPDX-License-Identifier: MIT
//
// Copyright 2024 Advanced Micro Devices, Inc.
#include "dc.h"
#include "link_service.h"
#include "dc_dmub_srv.h"
#include "dmub/dmub_srv.h"
#include "core_types.h"
#include "dmub_replay.h"
#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
#define MAX_PIPES 6
#define GPINT_RETRY_NUM 20
static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3};
static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5};
/*
* Get Replay state from firmware.
*/
static void dmub_replay_get_state(struct dmub_replay *dmub, enum replay_state *state, uint8_t panel_inst)
{
uint32_t retry_count = 0;
do {
// Send gpint command and wait for ack
if (!dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_REPLAY_STATE, panel_inst,
(uint32_t *)state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
// Return invalid state when GPINT times out
*state = REPLAY_STATE_INVALID;
}
} while (++retry_count <= 1000 && *state == REPLAY_STATE_INVALID);
// Assert if max retry hit
if (retry_count >= 1000 && *state == REPLAY_STATE_INVALID) {
ASSERT(0);
/* To-do: Add retry fail log */
}
}
/*
* Enable/Disable Replay.
*/
static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait, uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
uint32_t retry_count;
enum replay_state state = REPLAY_STATE_0;
memset(&cmd, 0, sizeof(cmd));
cmd.replay_enable.header.type = DMUB_CMD__REPLAY;
cmd.replay_enable.data.panel_inst = panel_inst;
cmd.replay_enable.header.sub_type = DMUB_CMD__REPLAY_ENABLE;
if (enable)
cmd.replay_enable.data.enable = REPLAY_ENABLE;
else
cmd.replay_enable.data.enable = REPLAY_DISABLE;
cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data);
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
/* Below loops 1000 x 500us = 500 ms.
* Exit REPLAY may need to wait 1-2 frames to power up. Timeout after at
* least a few frames. Should never hit the max retry assert below.
*/
if (wait) {
for (retry_count = 0; retry_count <= 1000; retry_count++) {
dmub_replay_get_state(dmub, &state, panel_inst);
if (enable) {
if (state != REPLAY_STATE_0)
break;
} else {
if (state == REPLAY_STATE_0)
break;
}
/* must *not* be fsleep - this can be called from high irq levels */
udelay(500);
}
/* assert if max retry hit */
if (retry_count >= 1000)
ASSERT(0);
}
}
/*
* Set REPLAY power optimization flags.
*/
static void dmub_replay_set_power_opt(struct dmub_replay *dmub, unsigned int power_opt, uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
memset(&cmd, 0, sizeof(cmd));
cmd.replay_set_power_opt.header.type = DMUB_CMD__REPLAY;
cmd.replay_set_power_opt.header.sub_type = DMUB_CMD__SET_REPLAY_POWER_OPT;
cmd.replay_set_power_opt.header.payload_bytes = sizeof(struct dmub_cmd_replay_set_power_opt_data);
cmd.replay_set_power_opt.replay_set_power_opt_data.power_opt = power_opt;
cmd.replay_set_power_opt.replay_set_power_opt_data.panel_inst = panel_inst;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* Setup Replay by programming phy registers and sending replay hw context values to firmware.
*/
static bool dmub_replay_copy_settings(struct dmub_replay *dmub,
struct dc_link *link,
struct replay_context *replay_context,
uint8_t panel_inst)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
struct dmub_cmd_replay_copy_settings_data *copy_settings_data
= &cmd.replay_copy_settings.replay_copy_settings_data;
struct pipe_ctx *pipe_ctx = NULL;
struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx;
int i = 0;
for (i = 0; i < MAX_PIPES; i++) {
if (res_ctx &&
res_ctx->pipe_ctx[i].stream &&
res_ctx->pipe_ctx[i].stream->link &&
res_ctx->pipe_ctx[i].stream->link == link &&
res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
pipe_ctx = &res_ctx->pipe_ctx[i];
//TODO: refactor for multi edp support
break;
}
}
if (!pipe_ctx)
return false;
memset(&cmd, 0, sizeof(cmd));
cmd.replay_copy_settings.header.type = DMUB_CMD__REPLAY;
cmd.replay_copy_settings.header.sub_type = DMUB_CMD__REPLAY_COPY_SETTINGS;
cmd.replay_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_replay_copy_settings_data);
// HW insts
copy_settings_data->aux_inst = replay_context->aux_inst;
copy_settings_data->digbe_inst = replay_context->digbe_inst;
copy_settings_data->digfe_inst = replay_context->digfe_inst;
if (pipe_ctx->plane_res.dpp)
copy_settings_data->dpp_inst = (uint8_t)pipe_ctx->plane_res.dpp->inst;
else
copy_settings_data->dpp_inst = 0;
if (pipe_ctx->stream_res.tg)
copy_settings_data->otg_inst = (uint8_t)pipe_ctx->stream_res.tg->inst;
else
copy_settings_data->otg_inst = 0;
copy_settings_data->dpphy_inst = link->link_enc->transmitter;
// Misc
copy_settings_data->line_time_in_ns = (uint16_t)replay_context->line_time_in_ns;
copy_settings_data->panel_inst = (uint16_t)panel_inst;
copy_settings_data->debug.u32All = (uint16_t)link->replay_settings.config.debug_flags;
copy_settings_data->pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line;
copy_settings_data->max_deviation_line = (uint16_t)link->dpcd_caps.pr_info.max_deviation_line;
copy_settings_data->smu_optimizations_en = link->replay_settings.replay_smu_opt_enable;
copy_settings_data->replay_timing_sync_supported = link->replay_settings.config.replay_timing_sync_supported;
copy_settings_data->replay_support_fast_resync_in_ultra_sleep_mode = link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode;
copy_settings_data->debug.bitfields.enable_ips_visual_confirm = dc->dc->debug.enable_ips_visual_confirm;
copy_settings_data->flags.u32All = 0;
copy_settings_data->flags.bitfields.fec_enable_status = (link->fec_state == dc_link_fec_enabled);
copy_settings_data->flags.bitfields.dsc_enable_status = (pipe_ctx->stream->timing.flags.DSC == 1);
// WA for PSRSU+DSC on specific TCON, if DSC is enabled, force PSRSU as ffu mode(full frame update)
if (((link->dpcd_caps.fec_cap.bits.FEC_CAPABLE &&
!link->dc->debug.disable_fec) &&
(link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
!link->panel_config.dsc.disable_dsc_edp &&
link->dc->caps.edp_dsc_support)) &&
link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 &&
(!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1,
sizeof(DP_SINK_DEVICE_STR_ID_1)) ||
!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_2,
sizeof(DP_SINK_DEVICE_STR_ID_2))))
copy_settings_data->flags.bitfields.force_wakeup_by_tps3 = 1;
else
copy_settings_data->flags.bitfields.force_wakeup_by_tps3 = 0;
copy_settings_data->flags.bitfields.alpm_mode = (enum dmub_alpm_mode)link->replay_settings.config.alpm_mode;
if (link->replay_settings.config.alpm_mode == DC_ALPM_AUXLESS) {
copy_settings_data->auxless_alpm_data.lfps_setup_ns = (uint16_t)dc->dc->debug.auxless_alpm_lfps_setup_ns;
copy_settings_data->auxless_alpm_data.lfps_period_ns = (uint16_t)dc->dc->debug.auxless_alpm_lfps_period_ns;
copy_settings_data->auxless_alpm_data.lfps_silence_ns = (uint16_t)dc->dc->debug.auxless_alpm_lfps_silence_ns;
copy_settings_data->auxless_alpm_data.lfps_t1_t2_override_us =
(uint16_t)dc->dc->debug.auxless_alpm_lfps_t1t2_us;
copy_settings_data->auxless_alpm_data.lfps_t1_t2_offset_us =
(uint16_t)dc->dc->debug.auxless_alpm_lfps_t1t2_offset_us;
copy_settings_data->auxless_alpm_data.lttpr_count = link->dc->link_srv->dp_get_lttpr_count(link);
}
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
/*
* Set coasting vtotal.
*/
static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
uint32_t coasting_vtotal,
uint8_t panel_inst,
uint16_t frame_skip_number)
{
(void)panel_inst;
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
struct dmub_rb_cmd_replay_set_coasting_vtotal *pCmd = NULL;
pCmd = &(cmd.replay_set_coasting_vtotal);
memset(&cmd, 0, sizeof(cmd));
pCmd->header.type = DMUB_CMD__REPLAY;
pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL;
pCmd->header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data);
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16;
pCmd->replay_set_coasting_vtotal_data.frame_skip_number = frame_skip_number;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* Get Replay residency from firmware.
*/
static void dmub_replay_residency(struct dmub_replay *dmub, uint8_t panel_inst,
uint32_t *residency, const bool is_start, enum pr_residency_mode mode)
{
uint16_t param = (uint16_t)(panel_inst << 8);
uint32_t i = 0;
switch (mode) {
case PR_RESIDENCY_MODE_PHY:
param |= REPLAY_RESIDENCY_FIELD_MODE_PHY;
break;
case PR_RESIDENCY_MODE_ALPM:
param |= REPLAY_RESIDENCY_FIELD_MODE_ALPM;
break;
case PR_RESIDENCY_MODE_IPS2:
param |= REPLAY_RESIDENCY_REVISION_1;
param |= REPLAY_RESIDENCY_FIELD_MODE2_IPS;
break;
case PR_RESIDENCY_MODE_FRAME_CNT:
param |= REPLAY_RESIDENCY_REVISION_1;
param |= REPLAY_RESIDENCY_FIELD_MODE2_FRAME_CNT;
break;
case PR_RESIDENCY_MODE_ENABLEMENT_PERIOD:
param |= REPLAY_RESIDENCY_REVISION_1;
param |= REPLAY_RESIDENCY_FIELD_MODE2_EN_PERIOD;
break;
default:
break;
}
if (is_start)
param |= REPLAY_RESIDENCY_ENABLE;
for (i = 0; i < GPINT_RETRY_NUM; i++) {
// Send gpint command and wait for ack
if (dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__REPLAY_RESIDENCY, param,
residency, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
return;
udelay(100);
}
// it means gpint retry many times
*residency = 0;
}
/*
* Set REPLAY power optimization flags and coasting vtotal.
*/
static void dmub_replay_set_power_opt_and_coasting_vtotal(struct dmub_replay *dmub,
unsigned int power_opt, uint8_t panel_inst, uint32_t coasting_vtotal, uint16_t frame_skip_number)
{
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal *pCmd = NULL;
pCmd = &(cmd.replay_set_power_opt_and_coasting_vtotal);
memset(&cmd, 0, sizeof(cmd));
pCmd->header.type = DMUB_CMD__REPLAY;
pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL;
pCmd->header.payload_bytes =
sizeof(struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal) -
sizeof(struct dmub_cmd_header);
pCmd->replay_set_power_opt_data.power_opt = power_opt;
pCmd->replay_set_power_opt_data.panel_inst = panel_inst;
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);
pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16;
pCmd->replay_set_coasting_vtotal_data.frame_skip_number = frame_skip_number;
dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
/*
* send Replay general cmd to DMUB.
*/
static void dmub_replay_send_cmd(struct dmub_replay *dmub,
enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element)
{
union dmub_rb_cmd cmd;
struct dc_context *ctx = NULL;
if (dmub == NULL || cmd_element == NULL)
return;
ctx = dmub->ctx;
if (ctx != NULL) {
if (msg != Replay_Msg_Not_Support) {
memset(&cmd, 0, sizeof(cmd));
//Header
cmd.replay_set_timing_sync.header.type = DMUB_CMD__REPLAY;
} else
return;
} else
return;
switch (msg) {
case Replay_Set_Timing_Sync_Supported:
//Header
cmd.replay_set_timing_sync.header.sub_type =
DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED;
cmd.replay_set_timing_sync.header.payload_bytes =
sizeof(struct dmub_rb_cmd_replay_set_timing_sync) -
sizeof(struct dmub_cmd_header);
//Cmd Body
cmd.replay_set_timing_sync.replay_set_timing_sync_data.panel_inst =
cmd_element->sync_data.panel_inst;
cmd.replay_set_timing_sync.replay_set_timing_sync_data.timing_sync_supported =
cmd_element->sync_data.timing_sync_supported;
break;
case Replay_Set_Residency_Frameupdate_Timer:
//Header
cmd.replay_set_frameupdate_timer.header.sub_type =
DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER;
cmd.replay_set_frameupdate_timer.header.payload_bytes =
sizeof(struct dmub_rb_cmd_replay_set_frameupdate_timer) -
sizeof(struct dmub_cmd_header);
//Cmd Body
cmd.replay_set_frameupdate_timer.data.panel_inst =
cmd_element->panel_inst;
cmd.replay_set_frameupdate_timer.data.enable =
cmd_element->timer_data.enable;
cmd.replay_set_frameupdate_timer.data.frameupdate_count =
cmd_element->timer_data.frameupdate_count;
break;
case Replay_Set_Pseudo_VTotal:
//Header
cmd.replay_set_pseudo_vtotal.header.sub_type =
DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL;
cmd.replay_set_pseudo_vtotal.header.payload_bytes =
sizeof(struct dmub_rb_cmd_replay_set_pseudo_vtotal) -
sizeof(struct dmub_cmd_header);
//Cmd Body
cmd.replay_set_pseudo_vtotal.data.panel_inst =
cmd_element->pseudo_vtotal_data.panel_inst;
cmd.replay_set_pseudo_vtotal.data.vtotal =
cmd_element->pseudo_vtotal_data.vtotal;
break;
case Replay_Disabled_Adaptive_Sync_SDP:
//Header
cmd.replay_disabled_adaptive_sync_sdp.header.sub_type =
DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP;
cmd.replay_disabled_adaptive_sync_sdp.header.payload_bytes =
sizeof(struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp) -
sizeof(struct dmub_cmd_header);
//Cmd Body
cmd.replay_disabled_adaptive_sync_sdp.data.panel_inst =
cmd_element->disabled_adaptive_sync_sdp_data.panel_inst;
cmd.replay_disabled_adaptive_sync_sdp.data.force_disabled =
cmd_element->disabled_adaptive_sync_sdp_data.force_disabled;
break;
case Replay_Set_General_Cmd:
//Header
cmd.replay_set_general_cmd.header.sub_type =
DMUB_CMD__REPLAY_SET_GENERAL_CMD;
cmd.replay_set_general_cmd.header.payload_bytes =
sizeof(struct dmub_rb_cmd_replay_set_general_cmd) -
sizeof(struct dmub_cmd_header);
//Cmd Body
cmd.replay_set_general_cmd.data.panel_inst =
cmd_element->set_general_cmd_data.panel_inst;
cmd.replay_set_general_cmd.data.subtype =
cmd_element->set_general_cmd_data.subtype;
cmd.replay_set_general_cmd.data.param1 =
cmd_element->set_general_cmd_data.param1;
cmd.replay_set_general_cmd.data.param2 =
cmd_element->set_general_cmd_data.param2;
break;
case Replay_Msg_Not_Support:
default:
return;
break;
}
dc_wake_and_execute_dmub_cmd(ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
static const struct dmub_replay_funcs replay_funcs = {
.replay_copy_settings = dmub_replay_copy_settings,
.replay_enable = dmub_replay_enable,
.replay_get_state = dmub_replay_get_state,
.replay_set_power_opt = dmub_replay_set_power_opt,
.replay_set_coasting_vtotal = dmub_replay_set_coasting_vtotal,
.replay_residency = dmub_replay_residency,
.replay_set_power_opt_and_coasting_vtotal = dmub_replay_set_power_opt_and_coasting_vtotal,
.replay_send_cmd = dmub_replay_send_cmd,
};
/*
* Construct Replay object.
*/
static void dmub_replay_construct(struct dmub_replay *replay, struct dc_context *ctx)
{
replay->ctx = ctx;
replay->funcs = &replay_funcs;
}
/*
* Allocate and initialize Replay object.
*/
struct dmub_replay *dmub_replay_create(struct dc_context *ctx)
{
struct dmub_replay *replay = kzalloc_obj(struct dmub_replay);
if (replay == NULL) {
BREAK_TO_DEBUGGER();
return NULL;
}
dmub_replay_construct(replay, ctx);
return replay;
}
/*
* Deallocate Replay object.
*/
void dmub_replay_destroy(struct dmub_replay **dmub)
{
kfree(*dmub);
*dmub = NULL;
}
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
//
// Copyright 2024 Advanced Micro Devices, Inc.
#ifndef _DMUB_REPLAY_H_
#define _DMUB_REPLAY_H_
#include "dc_types.h"
#include "dmub_cmd.h"
struct dc_link;
struct dmub_replay_funcs;
struct dmub_replay {
struct dc_context *ctx;
const struct dmub_replay_funcs *funcs;
};
struct dmub_replay_funcs {
void (*replay_get_state)(struct dmub_replay *dmub, enum replay_state *state,
uint8_t panel_inst);
void (*replay_enable)(struct dmub_replay *dmub, bool enable, bool wait,
uint8_t panel_inst);
bool (*replay_copy_settings)(struct dmub_replay *dmub, struct dc_link *link,
struct replay_context *replay_context, uint8_t panel_inst);
void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt,
uint8_t panel_inst);
void (*replay_send_cmd)(struct dmub_replay *dmub,
enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_element);
void (*replay_set_coasting_vtotal)(struct dmub_replay *dmub, uint32_t coasting_vtotal,
uint8_t panel_inst, uint16_t frame_skip_number);
void (*replay_residency)(struct dmub_replay *dmub,
uint8_t panel_inst, uint32_t *residency, const bool is_start, const enum pr_residency_mode mode);
void (*replay_set_power_opt_and_coasting_vtotal)(struct dmub_replay *dmub,
unsigned int power_opt, uint8_t panel_inst, uint32_t coasting_vtotal,
uint16_t frame_skip_number);
};
struct dmub_replay *dmub_replay_create(struct dc_context *ctx);
void dmub_replay_destroy(struct dmub_replay **dmub);
#endif /* _DMUB_REPLAY_H_ */