radeon_hd: AtomBIOS version bump. Encoder work.
* Now pulling in latest amdgpu atombios.h headers * Lots of DisplayPort cleanup and removal of legacy stuff * Add obsolete atombios header for things that disappear (amdgpu doesn't support older cards like we do) * Introduce new code to support later encoder tables * Drop radeon-specific encoder service from common dp_info * Tested on HD 5450 hdmi
This commit is contained in:
@@ -28,8 +28,6 @@ typedef struct {
|
|||||||
// Internal State information
|
// Internal State information
|
||||||
uint8 linkStatus[DP_LINK_STATUS_SIZE];
|
uint8 linkStatus[DP_LINK_STATUS_SIZE];
|
||||||
|
|
||||||
bool trainingUseEncoder;
|
|
||||||
|
|
||||||
uint8 trainingAttempts;
|
uint8 trainingAttempts;
|
||||||
uint8 trainingSet[4];
|
uint8 trainingSet[4];
|
||||||
int trainingReadInterval;
|
int trainingReadInterval;
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
#define ENCODER_OBJECT_ID_ALMOND 0x22
|
#define ENCODER_OBJECT_ID_ALMOND 0x22
|
||||||
#define ENCODER_OBJECT_ID_TRAVIS 0x23
|
#define ENCODER_OBJECT_ID_TRAVIS 0x23
|
||||||
#define ENCODER_OBJECT_ID_NUTMEG 0x22
|
#define ENCODER_OBJECT_ID_NUTMEG 0x22
|
||||||
|
#define ENCODER_OBJECT_ID_HDMI_ANX9805 0x26
|
||||||
|
|
||||||
/* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
|
/* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
|
||||||
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13
|
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13
|
||||||
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14
|
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14
|
||||||
@@ -86,6 +88,8 @@
|
|||||||
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 0x20
|
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 0x20
|
||||||
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 0x21
|
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 0x21
|
||||||
#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24
|
#define ENCODER_OBJECT_ID_INTERNAL_VCE 0x24
|
||||||
|
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 0x25
|
||||||
|
#define ENCODER_OBJECT_ID_INTERNAL_AMCLK 0x27
|
||||||
|
|
||||||
#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF
|
#define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF
|
||||||
|
|
||||||
@@ -364,6 +368,14 @@
|
|||||||
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
|
||||||
ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
|
ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define ENCODER_INTERNAL_UNIPHY3_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
|
ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define ENCODER_INTERNAL_UNIPHY3_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
|
||||||
|
ENCODER_OBJECT_ID_INTERNAL_UNIPHY3 << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
|
#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
|
||||||
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
|
ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT)
|
||||||
@@ -388,10 +400,14 @@
|
|||||||
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
ENCODER_OBJECT_ID_NUTMEG << OBJECT_ID_SHIFT)
|
ENCODER_OBJECT_ID_NUTMEG << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
#define ENCODER_VCE_ENUM_ID1 ( GRAPH_OBHECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
|
#define ENCODER_VCE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
|
||||||
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
ENCODER_OBJECT_ID_INTERNAL_VCE << OBJECT_ID_SHIFT)
|
ENCODER_OBJECT_ID_INTERNAL_VCE << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define ENCODER_HDMI_ANX9805_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
|
ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
/****************************************************/
|
/****************************************************/
|
||||||
/* Connector Object ID definition - Shared with BIOS */
|
/* Connector Object ID definition - Shared with BIOS */
|
||||||
/****************************************************/
|
/****************************************************/
|
||||||
@@ -461,6 +477,14 @@
|
|||||||
GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
|
||||||
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
|
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
|
||||||
|
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
|
||||||
|
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
|
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
|
||||||
@@ -473,6 +497,10 @@
|
|||||||
GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
|
||||||
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
|
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
|
||||||
|
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
#define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
#define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
|
CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
|
||||||
@@ -541,6 +569,18 @@
|
|||||||
GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\
|
||||||
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
|
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\
|
||||||
|
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\
|
||||||
|
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
|
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
|
GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\
|
||||||
|
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
|
||||||
|
|
||||||
#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
|
||||||
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
|
||||||
CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
|
CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef _ATOMBIOS_OBSOLETE_H
|
||||||
|
#define _ATOMBIOS_OBSOLETE_H
|
||||||
|
|
||||||
|
|
||||||
|
// atombios.h in radeon linux has some older obsolete things.
|
||||||
|
// atombios.h in amdgpu has these obsolete things removed.
|
||||||
|
// This file contains things removed from amdgpu that we still need.
|
||||||
|
|
||||||
|
|
||||||
|
#define ATOM_S2_CV_DPMS_STATE 0x01000000L
|
||||||
|
#define ATOM_S2_DFP2_DPMS_STATE 0x00800000L
|
||||||
|
#define ATOM_S2_DFP3_DPMS_STATE 0x02000000L
|
||||||
|
#define ATOM_S2_DFP4_DPMS_STATE 0x04000000L
|
||||||
|
#define ATOM_S2_DFP5_DPMS_STATE 0x08000000L
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _ATOMBIOS_OBSOLETE_H */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -405,6 +405,33 @@ dp_get_link_rate(uint32 connectorIndex, display_mode* mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8
|
||||||
|
dp_encoder_service(int action, int linkRate, uint8 lane, uint8 config)
|
||||||
|
{
|
||||||
|
DP_ENCODER_SERVICE_PARAMETERS args;
|
||||||
|
int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
|
||||||
|
|
||||||
|
memset(&args, 0, sizeof(args));
|
||||||
|
args.ucLinkClock = linkRate / 10;
|
||||||
|
args.ucConfig = config;
|
||||||
|
args.ucAction = action;
|
||||||
|
args.ucLaneNum = lane;
|
||||||
|
args.ucStatus = 0;
|
||||||
|
|
||||||
|
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||||
|
return args.ucStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8
|
||||||
|
dp_get_sink_type(uint32 connectorIndex)
|
||||||
|
{
|
||||||
|
dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
|
||||||
|
return dp_encoder_service(ATOM_DP_ACTION_GET_SINK_TYPE, 0, 0,
|
||||||
|
dpInfo->auxPin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dp_setup_connectors()
|
dp_setup_connectors()
|
||||||
{
|
{
|
||||||
@@ -616,80 +643,28 @@ dp_get_adjust_train(dp_info* dp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint8
|
|
||||||
dp_encoder_service(uint32 connectorIndex, int action, int linkRate,
|
|
||||||
uint8 lane)
|
|
||||||
{
|
|
||||||
DP_ENCODER_SERVICE_PARAMETERS args;
|
|
||||||
int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
|
|
||||||
|
|
||||||
memset(&args, 0, sizeof(args));
|
|
||||||
args.ucLinkClock = linkRate;
|
|
||||||
args.ucAction = action;
|
|
||||||
args.ucLaneNum = lane;
|
|
||||||
args.ucConfig = 0;
|
|
||||||
args.ucStatus = 0;
|
|
||||||
|
|
||||||
// We really can't do ATOM_DP_ACTION_GET_SINK_TYPE with the
|
|
||||||
// way I designed this below. Not used though.
|
|
||||||
|
|
||||||
// Calculate encoder_id config
|
|
||||||
if (encoder_pick_dig(connectorIndex))
|
|
||||||
args.ucConfig |= ATOM_DP_CONFIG_DIG2_ENCODER;
|
|
||||||
else
|
|
||||||
args.ucConfig |= ATOM_DP_CONFIG_DIG1_ENCODER;
|
|
||||||
|
|
||||||
if (gConnector[connectorIndex]->encoder.linkEnumeration
|
|
||||||
== GRAPH_OBJECT_ENUM_ID2) {
|
|
||||||
args.ucConfig |= ATOM_DP_CONFIG_LINK_B;
|
|
||||||
} else
|
|
||||||
args.ucConfig |= ATOM_DP_CONFIG_LINK_A;
|
|
||||||
|
|
||||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
|
||||||
|
|
||||||
return args.ucStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dp_set_tp(uint32 connectorIndex, int trainingPattern)
|
dp_set_tp(uint32 connectorIndex, int trainingPattern)
|
||||||
{
|
{
|
||||||
TRACE("%s\n", __func__);
|
TRACE("%s\n", __func__);
|
||||||
|
|
||||||
radeon_shared_info &info = *gInfo->shared_info;
|
|
||||||
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
|
|
||||||
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
||||||
|
|
||||||
int rawTrainingPattern = 0;
|
int rawTrainingPattern = 0;
|
||||||
|
|
||||||
/* set training pattern on the source */
|
/* set training pattern on the source */
|
||||||
if (info.dceMajor >= 4 || !dp->trainingUseEncoder) {
|
TRACE("%s: Training with encoder...\n", __func__);
|
||||||
TRACE("%s: Training with encoder...\n", __func__);
|
switch (trainingPattern) {
|
||||||
switch (trainingPattern) {
|
case DP_TRAIN_PATTERN_1:
|
||||||
case DP_TRAIN_PATTERN_1:
|
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
|
||||||
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
|
break;
|
||||||
break;
|
case DP_TRAIN_PATTERN_2:
|
||||||
case DP_TRAIN_PATTERN_2:
|
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2;
|
||||||
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2;
|
break;
|
||||||
break;
|
case DP_TRAIN_PATTERN_3:
|
||||||
case DP_TRAIN_PATTERN_3:
|
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3;
|
||||||
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern);
|
|
||||||
} else {
|
|
||||||
TRACE("%s: Training with encoder service...\n", __func__);
|
|
||||||
switch (trainingPattern) {
|
|
||||||
case DP_TRAIN_PATTERN_1:
|
|
||||||
rawTrainingPattern = 0;
|
|
||||||
break;
|
|
||||||
case DP_TRAIN_PATTERN_2:
|
|
||||||
rawTrainingPattern = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dp_encoder_service(connectorIndex, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
|
|
||||||
dp->linkRate, rawTrainingPattern);
|
|
||||||
}
|
}
|
||||||
|
encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern);
|
||||||
|
|
||||||
// Enable training pattern on the sink
|
// Enable training pattern on the sink
|
||||||
dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern);
|
||||||
@@ -839,34 +814,6 @@ dp_link_train(uint8 crtcID)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
|
|
||||||
// Table version
|
|
||||||
uint8 tableMajor;
|
|
||||||
uint8 tableMinor;
|
|
||||||
|
|
||||||
dp->trainingUseEncoder = true;
|
|
||||||
if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
|
|
||||||
== B_OK) {
|
|
||||||
if (tableMinor > 1) {
|
|
||||||
// The AtomBIOS DPEncoderService greater then 1.1 can't program the
|
|
||||||
// training pattern properly.
|
|
||||||
dp->trainingUseEncoder = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 linkEnumeration
|
|
||||||
= gConnector[connectorIndex]->encoder.linkEnumeration;
|
|
||||||
|
|
||||||
uint32 dpEncoderID = 0;
|
|
||||||
if (encoder_pick_dig(connectorIndex) > 0)
|
|
||||||
dpEncoderID |= ATOM_DP_CONFIG_DIG2_ENCODER;
|
|
||||||
else
|
|
||||||
dpEncoderID |= ATOM_DP_CONFIG_DIG1_ENCODER;
|
|
||||||
if (linkEnumeration == GRAPH_OBJECT_ENUM_ID2)
|
|
||||||
dpEncoderID |= ATOM_DP_CONFIG_LINK_B;
|
|
||||||
else
|
|
||||||
dpEncoderID |= ATOM_DP_CONFIG_LINK_A;
|
|
||||||
|
|
||||||
dp->trainingReadInterval
|
dp->trainingReadInterval
|
||||||
= dpcd_reg_read(connectorIndex, DP_TRAINING_AUX_RD_INTERVAL);
|
= dpcd_reg_read(connectorIndex, DP_TRAINING_AUX_RD_INTERVAL);
|
||||||
|
|
||||||
@@ -905,13 +852,8 @@ dp_link_train(uint8 crtcID)
|
|||||||
dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox);
|
dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox);
|
||||||
|
|
||||||
// Start link training on source
|
// Start link training on source
|
||||||
if (info.dceMajor >= 4 || !dp->trainingUseEncoder) {
|
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
||||||
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
|
||||||
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
|
|
||||||
} else {
|
|
||||||
dp_encoder_service(connectorIndex, ATOM_DP_ACTION_TRAINING_START,
|
|
||||||
dp->linkRate, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable the training pattern on the sink
|
// Disable the training pattern on the sink
|
||||||
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
||||||
@@ -926,13 +868,8 @@ dp_link_train(uint8 crtcID)
|
|||||||
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
||||||
|
|
||||||
// Disable the training pattern on the source
|
// Disable the training pattern on the source
|
||||||
if (info.dceMajor >= 4 || !dp->trainingUseEncoder) {
|
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
||||||
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
|
||||||
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
|
|
||||||
} else {
|
|
||||||
dp_encoder_service(connectorIndex, ATOM_DP_ACTION_TRAINING_COMPLETE,
|
|
||||||
dp->linkRate, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1055,8 +992,6 @@ debug_dp_info()
|
|||||||
dp->config[DP_DOWNSTREAMPORT_COUNT]
|
dp->config[DP_DOWNSTREAMPORT_COUNT]
|
||||||
& DP_DOWNSTREAMPORT_COUNT_MASK);
|
& DP_DOWNSTREAMPORT_COUNT_MASK);
|
||||||
ERROR(" + Training\n");
|
ERROR(" + Training\n");
|
||||||
ERROR(" - use encoder: %s\n",
|
|
||||||
dp->trainingUseEncoder ? "true" : "false");
|
|
||||||
ERROR(" - attempts: %" B_PRIu8 "\n",
|
ERROR(" - attempts: %" B_PRIu8 "\n",
|
||||||
dp->trainingAttempts);
|
dp->trainingAttempts);
|
||||||
ERROR(" - delay: %d\n",
|
ERROR(" - delay: %d\n",
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ status_t dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address,
|
|||||||
|
|
||||||
uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
|
uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
|
||||||
uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode);
|
uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode);
|
||||||
|
uint8 dp_get_sink_type(uint32 connectorIndex);
|
||||||
|
|
||||||
void dp_setup_connectors();
|
void dp_setup_connectors();
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "accelerant.h"
|
#include "accelerant.h"
|
||||||
#include "accelerant_protos.h"
|
#include "accelerant_protos.h"
|
||||||
|
#include "atombios-obsolete.h"
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
#include "connector.h"
|
#include "connector.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
@@ -1216,6 +1217,7 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
|
|||||||
DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
|
DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
|
||||||
DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
|
DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
|
||||||
DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
|
DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
|
||||||
|
DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 v6;
|
||||||
};
|
};
|
||||||
union digTransmitterControl args;
|
union digTransmitterControl args;
|
||||||
memset(&args, 0, sizeof(args));
|
memset(&args, 0, sizeof(args));
|
||||||
@@ -1576,12 +1578,64 @@ transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock,
|
|||||||
args.v5.asConfig.ucCoherentMode = 1;
|
args.v5.asConfig.ucCoherentMode = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RADEON_HPD_NONE? VVV
|
// TODO: hpd_id, for now RADEON_HPD_NONE.
|
||||||
args.v5.asConfig.ucHPDSel = 0;
|
args.v5.asConfig.ucHPDSel = 0;
|
||||||
|
|
||||||
args.v5.ucDigEncoderSel = 1 << digEncoderID;
|
args.v5.ucDigEncoderSel = 1 << digEncoderID;
|
||||||
args.v5.ucDPLaneSet = laneSet;
|
args.v5.ucDPLaneSet = laneSet;
|
||||||
break;
|
break;
|
||||||
|
case 6:
|
||||||
|
args.v6.ucAction = command;
|
||||||
|
if (isDP) {
|
||||||
|
args.v6.ulSymClock
|
||||||
|
= B_HOST_TO_LENDIAN_INT16(dpClock / 10);
|
||||||
|
} else {
|
||||||
|
args.v6.ulSymClock
|
||||||
|
= B_HOST_TO_LENDIAN_INT16(pixelClock / 10);
|
||||||
|
}
|
||||||
|
switch (encoderObjectID) {
|
||||||
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||||
|
if (linkB)
|
||||||
|
args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYB;
|
||||||
|
else
|
||||||
|
args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYA;
|
||||||
|
break;
|
||||||
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||||
|
if (linkB)
|
||||||
|
args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYD;
|
||||||
|
else
|
||||||
|
args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYC;
|
||||||
|
break;
|
||||||
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||||
|
if (linkB)
|
||||||
|
args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYF;
|
||||||
|
else
|
||||||
|
args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYE;
|
||||||
|
break;
|
||||||
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
|
||||||
|
args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (isDP)
|
||||||
|
args.v6.ucLaneNum = dpLaneCount;
|
||||||
|
else if (pixelClock > 165000)
|
||||||
|
args.v6.ucLaneNum = 8;
|
||||||
|
else
|
||||||
|
args.v6.ucLaneNum = 4;
|
||||||
|
|
||||||
|
args.v6.ucConnObjId = connectorObjectID;
|
||||||
|
|
||||||
|
if (command == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH)
|
||||||
|
args.v6.ucDPLaneSet = laneSet;
|
||||||
|
else {
|
||||||
|
args.v6.ucDigMode
|
||||||
|
= display_get_encoder_mode(connectorIndex);
|
||||||
|
}
|
||||||
|
// TODO: hpd_id, for now RADEON_HPD_NONE.
|
||||||
|
args.v6.ucHPDSel = 0;
|
||||||
|
|
||||||
|
args.v6.ucDigEncoderSel = 1 << digEncoderID;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR("%s: unknown table version\n", __func__);
|
ERROR("%s: unknown table version\n", __func__);
|
||||||
}
|
}
|
||||||
@@ -1806,13 +1860,10 @@ encoder_dpms_set(uint8 crtcID, int mode)
|
|||||||
? ATOM_LCD_BLOFF : ATOM_LCD_BLON;
|
? ATOM_LCD_BLOFF : ATOM_LCD_BLON;
|
||||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||||
}
|
}
|
||||||
encoder_dpms_scratch(crtcID, true);
|
|
||||||
}
|
}
|
||||||
|
if (info.dceMajor < 4)
|
||||||
|
encoder_dpms_scratch(crtcID, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an external encoder exists, we should flip it on as well
|
|
||||||
if (gConnector[connectorIndex]->encoderExternal.valid == true)
|
|
||||||
encoder_dpms_set_external(crtcID, mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1823,43 +1874,45 @@ encoder_dpms_set_dig(uint8 crtcID, int mode)
|
|||||||
|
|
||||||
radeon_shared_info &info = *gInfo->shared_info;
|
radeon_shared_info &info = *gInfo->shared_info;
|
||||||
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
|
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
|
||||||
uint32 connectorFlags = gConnector[connectorIndex]->flags;
|
connector_info* connector = gConnector[connectorIndex];
|
||||||
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
uint32 connectorFlags = connector->flags;
|
||||||
|
pll_info* pll = &connector->encoder.pll;
|
||||||
|
bool hasExternal = connector->encoderExternal.valid;
|
||||||
|
bool travisQuirk = info.dceMajor < 5
|
||||||
|
&& (connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0
|
||||||
|
&& connector->encoderExternal.objectID == ENCODER_OBJECT_ID_TRAVIS;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case B_DPMS_ON:
|
case B_DPMS_ON:
|
||||||
if (info.chipsetID == RADEON_RV710
|
if ((info.dceMajor == 4 && info.dceMinor == 1)
|
||||||
|| info.chipsetID == RADEON_RV730
|
|
||||||
|| (info.chipsetFlags & CHIP_APU) != 0
|
|
||||||
|| info.dceMajor >= 5) {
|
|| info.dceMajor >= 5) {
|
||||||
if (info.dceMajor >= 6) {
|
// Setup encoder
|
||||||
/* We need to call CMD_SETUP before reenabling the encoder,
|
encoder_dig_setup(connectorIndex, pll->pixelClock,
|
||||||
otherwise we never get a picture */
|
ATOM_ENCODER_CMD_SETUP);
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
encoder_dig_setup(connectorIndex, pll->pixelClock,
|
||||||
ATOM_ENCODER_CMD_SETUP);
|
ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
|
||||||
}
|
} else if (info.dceMajor >= 4) {
|
||||||
|
// Setup encoder
|
||||||
|
encoder_dig_setup(connectorIndex, pll->pixelClock,
|
||||||
|
ATOM_ENCODER_CMD_SETUP);
|
||||||
|
} else {
|
||||||
|
// Setup encoder and transmitter
|
||||||
encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE);
|
encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE);
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
||||||
ATOM_TRANSMITTER_ACTION_SETUP);
|
ATOM_TRANSMITTER_ACTION_SETUP);
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
|
||||||
ATOM_TRANSMITTER_ACTION_ENABLE);
|
|
||||||
/* some early dce3.2 boards have a bug in their transmitter
|
|
||||||
control table */
|
|
||||||
if (info.chipsetID != RADEON_RV710
|
|
||||||
&& info.chipsetID != RADEON_RV730)
|
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
|
||||||
ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
|
|
||||||
} else {
|
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
|
||||||
ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (connector->type == VIDEO_CONNECTOR_EDP) {
|
||||||
|
// TODO: If VIDEO_CONNECTOR_EDP, ATOM_TRANSMITTER_ACTION_POWER_ON
|
||||||
|
ERROR("%s: TODO, edp_panel_power!\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable transmitter
|
||||||
|
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
||||||
|
ATOM_TRANSMITTER_ACTION_ENABLE);
|
||||||
|
|
||||||
if (connector_is_dp(connectorIndex)) {
|
if (connector_is_dp(connectorIndex)) {
|
||||||
if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) {
|
|
||||||
ERROR("%s: TODO, edp_panel_power for this card!\n",
|
|
||||||
__func__);
|
|
||||||
// atombios_set_edp_panel_power(connector,
|
|
||||||
// ATOM_TRANSMITTER_ACTION_POWER_ON);
|
|
||||||
}
|
|
||||||
if (info.dceMajor >= 4) {
|
if (info.dceMajor >= 4) {
|
||||||
encoder_dig_setup(connectorIndex, pll->pixelClock,
|
encoder_dig_setup(connectorIndex, pll->pixelClock,
|
||||||
ATOM_ENCODER_CMD_DP_VIDEO_OFF);
|
ATOM_ENCODER_CMD_DP_VIDEO_OFF);
|
||||||
@@ -1878,71 +1931,49 @@ encoder_dpms_set_dig(uint8 crtcID, int mode)
|
|||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock,
|
transmitter_dig_setup(connectorIndex, pll->pixelClock,
|
||||||
0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON);
|
0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON);
|
||||||
}
|
}
|
||||||
|
if (hasExternal)
|
||||||
|
encoder_external_setup(connectorIndex, ATOM_ENABLE);
|
||||||
break;
|
break;
|
||||||
case B_DPMS_STAND_BY:
|
case B_DPMS_STAND_BY:
|
||||||
case B_DPMS_SUSPEND:
|
case B_DPMS_SUSPEND:
|
||||||
case B_DPMS_OFF:
|
case B_DPMS_OFF:
|
||||||
if ((info.chipsetFlags & CHIP_APU) != 0 || info.dceMajor >= 5) {
|
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
|
||||||
ATOM_TRANSMITTER_ACTION_DISABLE);
|
|
||||||
} else {
|
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
|
||||||
ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
|
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
|
||||||
ATOM_TRANSMITTER_ACTION_DISABLE);
|
|
||||||
encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE);
|
|
||||||
}
|
|
||||||
if (connector_is_dp(connectorIndex)) {
|
if (connector_is_dp(connectorIndex)) {
|
||||||
if (info.dceMajor >= 4) {
|
if (info.dceMajor >= 4) {
|
||||||
encoder_dig_setup(connectorIndex, pll->pixelClock,
|
encoder_dig_setup(connectorIndex, pll->pixelClock,
|
||||||
ATOM_ENCODER_CMD_DP_VIDEO_OFF);
|
ATOM_ENCODER_CMD_DP_VIDEO_OFF);
|
||||||
#if 0
|
|
||||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
|
||||||
atombios_set_edp_panel_power(connector,
|
|
||||||
ATOM_TRANSMITTER_ACTION_POWER_OFF);
|
|
||||||
radeon_dig_connector->edp_on = false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (hasExternal)
|
||||||
|
encoder_external_setup(connectorIndex, ATOM_DISABLE);
|
||||||
if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
|
if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) {
|
||||||
transmitter_dig_setup(connectorIndex, pll->pixelClock,
|
transmitter_dig_setup(connectorIndex, pll->pixelClock,
|
||||||
0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF);
|
0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF);
|
||||||
}
|
}
|
||||||
break;
|
if (connector_is_dp(connectorIndex) && !travisQuirk) {
|
||||||
}
|
// If not TRAVIS on < DCE 5, set_rx_power_state D3
|
||||||
}
|
ERROR("%s: TODO: dpms off set_rx_power_state D3\n", __func__);
|
||||||
|
}
|
||||||
|
if (info.dceMajor >= 4) {
|
||||||
void
|
// Disable transmitter
|
||||||
encoder_dpms_set_external(uint8 crtcID, int mode)
|
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
||||||
{
|
ATOM_TRANSMITTER_ACTION_DISABLE);
|
||||||
TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false");
|
} else {
|
||||||
|
// Disable transmitter and encoder
|
||||||
radeon_shared_info &info = *gInfo->shared_info;
|
transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0,
|
||||||
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
|
ATOM_TRANSMITTER_ACTION_DISABLE);
|
||||||
|
encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE);
|
||||||
switch (mode) {
|
}
|
||||||
case B_DPMS_ON:
|
|
||||||
if ((info.chipsetFlags & CHIP_APU) != 0) {
|
|
||||||
encoder_external_setup(connectorIndex,
|
|
||||||
EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
|
|
||||||
encoder_external_setup(connectorIndex,
|
|
||||||
EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
|
|
||||||
} else
|
|
||||||
encoder_external_setup(connectorIndex, ATOM_ENABLE);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case B_DPMS_STAND_BY:
|
|
||||||
case B_DPMS_SUSPEND:
|
|
||||||
case B_DPMS_OFF:
|
|
||||||
if ((info.chipsetFlags & CHIP_APU) != 0) {
|
|
||||||
encoder_external_setup(connectorIndex,
|
|
||||||
EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
|
|
||||||
encoder_external_setup(connectorIndex,
|
|
||||||
EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
|
|
||||||
} else
|
|
||||||
encoder_external_setup(connectorIndex, ATOM_DISABLE);
|
|
||||||
|
|
||||||
|
if (connector_is_dp(connectorIndex)) {
|
||||||
|
if (travisQuirk) {
|
||||||
|
ERROR("%s: TODO: dpms off set_rx_power_state D3\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
if (connector->type == VIDEO_CONNECTOR_EDP) {
|
||||||
|
// TODO: ATOM_TRANSMITTER_ACTION_POWER_OFF
|
||||||
|
ERROR("%s: TODO, edp_panel_power!\n", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ void encoder_dpms_scratch(uint8 crtcID, bool power);
|
|||||||
void encoder_dpms_set(uint8 crtcID, int mode);
|
void encoder_dpms_set(uint8 crtcID, int mode);
|
||||||
void encoder_dpms_set_dig(uint8 crtcID, int mode);
|
void encoder_dpms_set_dig(uint8 crtcID, int mode);
|
||||||
void encoder_dpms_set_dvo(uint8 crtcID, int mode);
|
void encoder_dpms_set_dvo(uint8 crtcID, int mode);
|
||||||
void encoder_dpms_set_external(uint8 crtcID, int mode);
|
|
||||||
|
|
||||||
const char* encoder_name_lookup(uint32 encoderID);
|
const char* encoder_name_lookup(uint32 encoderID);
|
||||||
uint32 encoder_object_lookup(uint32 connectorFlags, uint8 dacID);
|
uint32 encoder_object_lookup(uint32 connectorFlags, uint8 dacID);
|
||||||
|
|||||||
Reference in New Issue
Block a user