Merge branch 'drm-next-4.1' of git://people.freedesktop.org/~agd5f/linux into drm-next
- DP MST support (disabled by default) - non-ATOM aux support (DCE5+) - output csc support for clamped RGB - Lots of new queries for profiling, Gallium HUD, etc. - Misc fixes * 'drm-next-4.1' of git://people.freedesktop.org/~agd5f/linux: (40 commits) drm/radeon: add DisplayPort MST support (v2) drm/radeon: improve encoder picking functions (v2) drm/radeon: export max link rate calculation drm/radeon: add new atombios encoder/transmitter interfaces drm/radeon: add some MST registers radeon/fb: add wrapper functions around fb connector add/remove radeon/cik: add support for short HPD irqs radeon/si: add support for short HPD irqs radeon/evergreen: add support for short HPD irqs radeon: introduce a dp_work handler drm/dp_mst: add a function to retrieve vcpi slots drm/radeon: program auxch directly (v2) drm/radeon: fix doublescan modes (v2) drm/radeon: typo in parameter description drm/radeon: add support for read reg query from radeon info ioctl drm/radeon: add get_allowed_info_register for CIK drm/radeon: add get_allowed_info_register for SI drm/radeon: add get_allowed_info_register for cayman/TN drm/radeon: add get_allowed_info_register for EG/BTC drm/radeon: add get_allowed_info_register for r6xx/r7xx ...
This commit is contained in:
commit
b3ede177c8
@ -2319,6 +2319,19 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
|
||||
|
||||
int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
|
||||
{
|
||||
int slots = 0;
|
||||
port = drm_dp_get_validated_port_ref(mgr, port);
|
||||
if (!port)
|
||||
return slots;
|
||||
|
||||
slots = port->vcpi.num_slots;
|
||||
drm_dp_put_port(port);
|
||||
return slots;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots);
|
||||
|
||||
/**
|
||||
* drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI
|
||||
* @mgr: manager for this port
|
||||
|
@ -81,7 +81,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
|
||||
rv770_smc.o cypress_dpm.o btc_dpm.o sumo_dpm.o sumo_smc.o trinity_dpm.o \
|
||||
trinity_smc.o ni_dpm.o si_smc.o si_dpm.o kv_smc.o kv_dpm.o ci_smc.o \
|
||||
ci_dpm.o dce6_afmt.o radeon_vm.o radeon_ucode.o radeon_ib.o \
|
||||
radeon_sync.o radeon_audio.o
|
||||
radeon_sync.o radeon_audio.o radeon_dp_auxch.o radeon_dp_mst.o
|
||||
|
||||
radeon-$(CONFIG_MMU_NOTIFIER) += radeon_mn.o
|
||||
|
||||
|
@ -330,8 +330,10 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
|
||||
misc |= ATOM_COMPOSITESYNC;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
misc |= ATOM_INTERLACE;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||
misc |= ATOM_DOUBLE_CLOCK_MODE;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
|
||||
|
||||
args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
|
||||
args.ucCRTC = radeon_crtc->crtc_id;
|
||||
@ -374,8 +376,10 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
|
||||
misc |= ATOM_COMPOSITESYNC;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
misc |= ATOM_INTERLACE;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||
misc |= ATOM_DOUBLE_CLOCK_MODE;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
|
||||
|
||||
args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
|
||||
args.ucCRTC = radeon_crtc->crtc_id;
|
||||
@ -606,6 +610,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
||||
}
|
||||
}
|
||||
|
||||
if (radeon_encoder->is_mst_encoder) {
|
||||
struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
|
||||
struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv;
|
||||
|
||||
dp_clock = dig_connector->dp_clock;
|
||||
}
|
||||
|
||||
/* use recommended ref_div for ss */
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
||||
if (radeon_crtc->ss_enabled) {
|
||||
@ -952,7 +963,9 @@ static bool atombios_crtc_prepare_pll(struct drm_crtc *crtc, struct drm_display_
|
||||
radeon_crtc->bpc = 8;
|
||||
radeon_crtc->ss_enabled = false;
|
||||
|
||||
if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
|
||||
if (radeon_encoder->is_mst_encoder) {
|
||||
radeon_dp_mst_prepare_pll(crtc, mode);
|
||||
} else if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
|
||||
(radeon_encoder_get_dp_bridge_encoder_id(radeon_crtc->encoder) != ENCODER_OBJECT_ID_NONE)) {
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
struct drm_connector *connector =
|
||||
@ -2069,6 +2082,12 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
radeon_crtc->connector = NULL;
|
||||
return false;
|
||||
}
|
||||
if (radeon_crtc->encoder) {
|
||||
struct radeon_encoder *radeon_encoder =
|
||||
to_radeon_encoder(radeon_crtc->encoder);
|
||||
|
||||
radeon_crtc->output_csc = radeon_encoder->output_csc;
|
||||
}
|
||||
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
|
||||
return false;
|
||||
if (!atombios_crtc_prepare_pll(crtc, adjusted_mode))
|
||||
|
@ -158,7 +158,7 @@ done:
|
||||
#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1)
|
||||
|
||||
static ssize_t
|
||||
radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
||||
radeon_dp_aux_transfer_atom(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
struct radeon_i2c_chan *chan =
|
||||
container_of(aux, struct radeon_i2c_chan, aux);
|
||||
@ -226,11 +226,20 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
||||
|
||||
void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct drm_device *dev = radeon_connector->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd;
|
||||
radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev;
|
||||
radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer;
|
||||
if (ASIC_IS_DCE5(rdev)) {
|
||||
if (radeon_auxch)
|
||||
radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_native;
|
||||
else
|
||||
radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom;
|
||||
} else {
|
||||
radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom;
|
||||
}
|
||||
|
||||
ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux);
|
||||
if (!ret)
|
||||
@ -301,8 +310,8 @@ static int dp_get_max_dp_pix_clock(int link_rate,
|
||||
|
||||
/***** radeon specific DP functions *****/
|
||||
|
||||
static int radeon_dp_get_max_link_rate(struct drm_connector *connector,
|
||||
u8 dpcd[DP_DPCD_SIZE])
|
||||
int radeon_dp_get_max_link_rate(struct drm_connector *connector,
|
||||
u8 dpcd[DP_DPCD_SIZE])
|
||||
{
|
||||
int max_link_rate;
|
||||
|
||||
|
@ -671,7 +671,15 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
struct radeon_encoder_atom_dig *dig_enc;
|
||||
|
||||
if (radeon_encoder_is_digital(encoder)) {
|
||||
dig_enc = radeon_encoder->enc_priv;
|
||||
if (dig_enc->active_mst_links)
|
||||
return ATOM_ENCODER_MODE_DP_MST;
|
||||
}
|
||||
if (radeon_encoder->is_mst_encoder || radeon_encoder->offset)
|
||||
return ATOM_ENCODER_MODE_DP_MST;
|
||||
/* dp bridges are always DP */
|
||||
if (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)
|
||||
return ATOM_ENCODER_MODE_DP;
|
||||
@ -823,7 +831,7 @@ union dig_encoder_control {
|
||||
};
|
||||
|
||||
void
|
||||
atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
|
||||
atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
@ -920,7 +928,10 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
|
||||
|
||||
if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
|
||||
args.v3.acConfig.ucDigSel = dig->dig_encoder;
|
||||
if (enc_override != -1)
|
||||
args.v3.acConfig.ucDigSel = enc_override;
|
||||
else
|
||||
args.v3.acConfig.ucDigSel = dig->dig_encoder;
|
||||
args.v3.ucBitPerColor = radeon_atom_get_bpc(encoder);
|
||||
break;
|
||||
case 4:
|
||||
@ -948,7 +959,11 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
|
||||
else
|
||||
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
|
||||
}
|
||||
args.v4.acConfig.ucDigSel = dig->dig_encoder;
|
||||
|
||||
if (enc_override != -1)
|
||||
args.v4.acConfig.ucDigSel = enc_override;
|
||||
else
|
||||
args.v4.acConfig.ucDigSel = dig->dig_encoder;
|
||||
args.v4.ucBitPerColor = radeon_atom_get_bpc(encoder);
|
||||
if (hpd_id == RADEON_HPD_NONE)
|
||||
args.v4.ucHPD_ID = 0;
|
||||
@ -969,6 +984,12 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode)
|
||||
{
|
||||
atombios_dig_encoder_setup2(encoder, action, panel_mode, -1);
|
||||
}
|
||||
|
||||
union dig_transmitter_control {
|
||||
DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
|
||||
DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
|
||||
@ -978,7 +999,7 @@ union dig_transmitter_control {
|
||||
};
|
||||
|
||||
void
|
||||
atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
|
||||
atombios_dig_transmitter_setup2(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set, int fe)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
@ -1328,7 +1349,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
|
||||
args.v5.asConfig.ucHPDSel = 0;
|
||||
else
|
||||
args.v5.asConfig.ucHPDSel = hpd_id + 1;
|
||||
args.v5.ucDigEncoderSel = 1 << dig_encoder;
|
||||
args.v5.ucDigEncoderSel = (fe != -1) ? (1 << fe) : (1 << dig_encoder);
|
||||
args.v5.ucDPLaneSet = lane_set;
|
||||
break;
|
||||
default:
|
||||
@ -1344,6 +1365,12 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
void
|
||||
atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
|
||||
{
|
||||
atombios_dig_transmitter_setup2(encoder, action, lane_num, lane_set, -1);
|
||||
}
|
||||
|
||||
bool
|
||||
atombios_set_edp_panel_power(struct drm_connector *connector, int action)
|
||||
{
|
||||
@ -1687,6 +1714,11 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
|
||||
/* don't power off encoders with active MST links */
|
||||
if (dig->active_mst_links)
|
||||
return;
|
||||
|
||||
if (ASIC_IS_DCE4(rdev)) {
|
||||
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
|
||||
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
|
||||
@ -1955,6 +1987,53 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
|
||||
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
|
||||
}
|
||||
|
||||
void
|
||||
atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder, int fe)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
|
||||
int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
|
||||
uint8_t frev, crev;
|
||||
union crtc_source_param args;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
|
||||
return;
|
||||
|
||||
if (frev != 1 && crev != 2)
|
||||
DRM_ERROR("Unknown table for MST %d, %d\n", frev, crev);
|
||||
|
||||
args.v2.ucCRTC = radeon_crtc->crtc_id;
|
||||
args.v2.ucEncodeMode = ATOM_ENCODER_MODE_DP_MST;
|
||||
|
||||
switch (fe) {
|
||||
case 0:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
|
||||
break;
|
||||
case 1:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
|
||||
break;
|
||||
case 2:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
|
||||
break;
|
||||
case 3:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
|
||||
break;
|
||||
case 4:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
|
||||
break;
|
||||
case 5:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
|
||||
break;
|
||||
case 6:
|
||||
args.v2.ucEncoderID = ASIC_INT_DIG7_ENCODER_ID;
|
||||
break;
|
||||
}
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
}
|
||||
|
||||
static void
|
||||
atombios_apply_encoder_quirks(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode)
|
||||
@ -2003,7 +2082,14 @@ atombios_apply_encoder_quirks(struct drm_encoder *encoder,
|
||||
}
|
||||
}
|
||||
|
||||
static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
|
||||
void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx)
|
||||
{
|
||||
if (enc_idx < 0)
|
||||
return;
|
||||
rdev->mode_info.active_encoders &= ~(1 << enc_idx);
|
||||
}
|
||||
|
||||
int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
@ -2012,71 +2098,79 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
|
||||
struct drm_encoder *test_encoder;
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
uint32_t dig_enc_in_use = 0;
|
||||
int enc_idx = -1;
|
||||
|
||||
if (fe_idx >= 0) {
|
||||
enc_idx = fe_idx;
|
||||
goto assigned;
|
||||
}
|
||||
if (ASIC_IS_DCE6(rdev)) {
|
||||
/* DCE6 */
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
if (dig->linkb)
|
||||
return 1;
|
||||
enc_idx = 1;
|
||||
else
|
||||
return 0;
|
||||
enc_idx = 0;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
if (dig->linkb)
|
||||
return 3;
|
||||
enc_idx = 3;
|
||||
else
|
||||
return 2;
|
||||
enc_idx = 2;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
if (dig->linkb)
|
||||
return 5;
|
||||
enc_idx = 5;
|
||||
else
|
||||
return 4;
|
||||
enc_idx = 4;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
|
||||
return 6;
|
||||
enc_idx = 6;
|
||||
break;
|
||||
}
|
||||
goto assigned;
|
||||
} else if (ASIC_IS_DCE4(rdev)) {
|
||||
/* DCE4/5 */
|
||||
if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
|
||||
/* ontario follows DCE4 */
|
||||
if (rdev->family == CHIP_PALM) {
|
||||
if (dig->linkb)
|
||||
return 1;
|
||||
enc_idx = 1;
|
||||
else
|
||||
return 0;
|
||||
enc_idx = 0;
|
||||
} else
|
||||
/* llano follows DCE3.2 */
|
||||
return radeon_crtc->crtc_id;
|
||||
enc_idx = radeon_crtc->crtc_id;
|
||||
} else {
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
if (dig->linkb)
|
||||
return 1;
|
||||
enc_idx = 1;
|
||||
else
|
||||
return 0;
|
||||
enc_idx = 0;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
if (dig->linkb)
|
||||
return 3;
|
||||
enc_idx = 3;
|
||||
else
|
||||
return 2;
|
||||
enc_idx = 2;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
if (dig->linkb)
|
||||
return 5;
|
||||
enc_idx = 5;
|
||||
else
|
||||
return 4;
|
||||
enc_idx = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto assigned;
|
||||
}
|
||||
|
||||
/* on DCE32 and encoder can driver any block so just crtc id */
|
||||
if (ASIC_IS_DCE32(rdev)) {
|
||||
return radeon_crtc->crtc_id;
|
||||
enc_idx = radeon_crtc->crtc_id;
|
||||
goto assigned;
|
||||
}
|
||||
|
||||
/* on DCE3 - LVTMA can only be driven by DIGB */
|
||||
@ -2104,6 +2198,17 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
|
||||
if (!(dig_enc_in_use & 1))
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
assigned:
|
||||
if (enc_idx == -1) {
|
||||
DRM_ERROR("Got encoder index incorrect - returning 0\n");
|
||||
return 0;
|
||||
}
|
||||
if (rdev->mode_info.active_encoders & (1 << enc_idx)) {
|
||||
DRM_ERROR("chosen encoder in use %d\n", enc_idx);
|
||||
}
|
||||
rdev->mode_info.active_encoders |= (1 << enc_idx);
|
||||
return enc_idx;
|
||||
}
|
||||
|
||||
/* This only needs to be called once at startup */
|
||||
@ -2362,7 +2467,9 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
|
||||
ENCODER_OBJECT_ID_NONE)) {
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
if (dig) {
|
||||
dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder);
|
||||
if (dig->dig_encoder >= 0)
|
||||
radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
|
||||
dig->dig_encoder = radeon_atom_pick_dig_encoder(encoder, -1);
|
||||
if (radeon_encoder->active_device & ATOM_DEVICE_DFP_SUPPORT) {
|
||||
if (rdev->family >= CHIP_R600)
|
||||
dig->afmt = rdev->mode_info.afmt[dig->dig_encoder];
|
||||
@ -2464,10 +2571,18 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
|
||||
|
||||
disable_done:
|
||||
if (radeon_encoder_is_digital(encoder)) {
|
||||
dig = radeon_encoder->enc_priv;
|
||||
dig->dig_encoder = -1;
|
||||
}
|
||||
radeon_encoder->active_device = 0;
|
||||
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
|
||||
if (rdev->asic->display.hdmi_enable)
|
||||
radeon_hdmi_enable(rdev, encoder, false);
|
||||
}
|
||||
if (atombios_get_encoder_mode(encoder) != ATOM_ENCODER_MODE_DP_MST) {
|
||||
dig = radeon_encoder->enc_priv;
|
||||
radeon_atom_release_dig_encoder(rdev, dig->dig_encoder);
|
||||
dig->dig_encoder = -1;
|
||||
radeon_encoder->active_device = 0;
|
||||
}
|
||||
} else
|
||||
radeon_encoder->active_device = 0;
|
||||
}
|
||||
|
||||
/* these are handled by the primary encoders */
|
||||
|
@ -2751,13 +2751,54 @@ void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
|
||||
else /* current_index == 2 */
|
||||
pl = &ps->high;
|
||||
seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
|
||||
if (rdev->family >= CHIP_CEDAR) {
|
||||
seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u\n",
|
||||
current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
|
||||
} else {
|
||||
seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u\n",
|
||||
current_index, pl->sclk, pl->mclk, pl->vddc);
|
||||
}
|
||||
seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u\n",
|
||||
current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
|
||||
}
|
||||
}
|
||||
|
||||
u32 btc_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
|
||||
struct radeon_ps *rps = &eg_pi->current_rps;
|
||||
struct rv7xx_ps *ps = rv770_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
|
||||
CURRENT_PROFILE_INDEX_SHIFT;
|
||||
|
||||
if (current_index > 2) {
|
||||
return 0;
|
||||
} else {
|
||||
if (current_index == 0)
|
||||
pl = &ps->low;
|
||||
else if (current_index == 1)
|
||||
pl = &ps->medium;
|
||||
else /* current_index == 2 */
|
||||
pl = &ps->high;
|
||||
return pl->sclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 btc_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
|
||||
struct radeon_ps *rps = &eg_pi->current_rps;
|
||||
struct rv7xx_ps *ps = rv770_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
|
||||
CURRENT_PROFILE_INDEX_SHIFT;
|
||||
|
||||
if (current_index > 2) {
|
||||
return 0;
|
||||
} else {
|
||||
if (current_index == 0)
|
||||
pl = &ps->low;
|
||||
else if (current_index == 1)
|
||||
pl = &ps->medium;
|
||||
else /* current_index == 2 */
|
||||
pl = &ps->high;
|
||||
return pl->mclk;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5922,6 +5922,20 @@ void ci_dpm_print_power_state(struct radeon_device *rdev,
|
||||
r600_dpm_print_ps_status(rdev, rps);
|
||||
}
|
||||
|
||||
u32 ci_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
u32 sclk = ci_get_average_sclk_freq(rdev);
|
||||
|
||||
return sclk;
|
||||
}
|
||||
|
||||
u32 ci_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
u32 mclk = ci_get_average_mclk_freq(rdev);
|
||||
|
||||
return mclk;
|
||||
}
|
||||
|
||||
u32 ci_dpm_get_sclk(struct radeon_device *rdev, bool low)
|
||||
{
|
||||
struct ci_power_info *pi = ci_get_pi(rdev);
|
||||
|
@ -141,6 +141,39 @@ static void cik_fini_cg(struct radeon_device *rdev);
|
||||
static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev,
|
||||
bool enable);
|
||||
|
||||
/**
|
||||
* cik_get_allowed_info_register - fetch the register for the info ioctl
|
||||
*
|
||||
* @rdev: radeon_device pointer
|
||||
* @reg: register offset in bytes
|
||||
* @val: register value
|
||||
*
|
||||
* Returns 0 for success or -EINVAL for an invalid register
|
||||
*
|
||||
*/
|
||||
int cik_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val)
|
||||
{
|
||||
switch (reg) {
|
||||
case GRBM_STATUS:
|
||||
case GRBM_STATUS2:
|
||||
case GRBM_STATUS_SE0:
|
||||
case GRBM_STATUS_SE1:
|
||||
case GRBM_STATUS_SE2:
|
||||
case GRBM_STATUS_SE3:
|
||||
case SRBM_STATUS:
|
||||
case SRBM_STATUS2:
|
||||
case (SDMA0_STATUS_REG + SDMA0_REGISTER_OFFSET):
|
||||
case (SDMA0_STATUS_REG + SDMA1_REGISTER_OFFSET):
|
||||
case UVD_STATUS:
|
||||
/* TODO VCE */
|
||||
*val = RREG32(reg);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* get temperature in millidegrees */
|
||||
int ci_get_temp(struct radeon_device *rdev)
|
||||
{
|
||||
@ -7394,12 +7427,12 @@ int cik_irq_set(struct radeon_device *rdev)
|
||||
(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
|
||||
cp_int_cntl |= PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE;
|
||||
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
|
||||
dma_cntl = RREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
|
||||
dma_cntl1 = RREG32(SDMA0_CNTL + SDMA1_REGISTER_OFFSET) & ~TRAP_ENABLE;
|
||||
@ -7486,27 +7519,27 @@ int cik_irq_set(struct radeon_device *rdev)
|
||||
}
|
||||
if (rdev->irq.hpd[0]) {
|
||||
DRM_DEBUG("cik_irq_set: hpd 1\n");
|
||||
hpd1 |= DC_HPDx_INT_EN;
|
||||
hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[1]) {
|
||||
DRM_DEBUG("cik_irq_set: hpd 2\n");
|
||||
hpd2 |= DC_HPDx_INT_EN;
|
||||
hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[2]) {
|
||||
DRM_DEBUG("cik_irq_set: hpd 3\n");
|
||||
hpd3 |= DC_HPDx_INT_EN;
|
||||
hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[3]) {
|
||||
DRM_DEBUG("cik_irq_set: hpd 4\n");
|
||||
hpd4 |= DC_HPDx_INT_EN;
|
||||
hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[4]) {
|
||||
DRM_DEBUG("cik_irq_set: hpd 5\n");
|
||||
hpd5 |= DC_HPDx_INT_EN;
|
||||
hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[5]) {
|
||||
DRM_DEBUG("cik_irq_set: hpd 6\n");
|
||||
hpd6 |= DC_HPDx_INT_EN;
|
||||
hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
|
||||
WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
|
||||
@ -7678,6 +7711,36 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD1_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD1_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD2_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD2_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD3_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD3_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD4_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD4_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -7803,6 +7866,7 @@ int cik_irq_process(struct radeon_device *rdev)
|
||||
u8 me_id, pipe_id, queue_id;
|
||||
u32 ring_index;
|
||||
bool queue_hotplug = false;
|
||||
bool queue_dp = false;
|
||||
bool queue_reset = false;
|
||||
u32 addr, status, mc_client;
|
||||
bool queue_thermal = false;
|
||||
@ -8048,6 +8112,48 @@ restart_ih:
|
||||
DRM_DEBUG("IH: HPD6\n");
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 1\n");
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 2\n");
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 3\n");
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 4\n");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 5\n");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 6\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
|
||||
break;
|
||||
@ -8256,6 +8362,8 @@ restart_ih:
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
WREG32(IH_RB_RPTR, rptr);
|
||||
}
|
||||
if (queue_dp)
|
||||
schedule_work(&rdev->dp_work);
|
||||
if (queue_hotplug)
|
||||
schedule_work(&rdev->hotplug_work);
|
||||
if (queue_reset) {
|
||||
|
@ -2088,6 +2088,8 @@
|
||||
# define CLK_OD(x) ((x) << 6)
|
||||
# define CLK_OD_MASK (0x1f << 6)
|
||||
|
||||
#define UVD_STATUS 0xf6bc
|
||||
|
||||
/* UVD clocks */
|
||||
|
||||
#define CG_DCLK_CNTL 0xC050009C
|
||||
|
@ -1006,6 +1006,34 @@ static void evergreen_init_golden_registers(struct radeon_device *rdev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* evergreen_get_allowed_info_register - fetch the register for the info ioctl
|
||||
*
|
||||
* @rdev: radeon_device pointer
|
||||
* @reg: register offset in bytes
|
||||
* @val: register value
|
||||
*
|
||||
* Returns 0 for success or -EINVAL for an invalid register
|
||||
*
|
||||
*/
|
||||
int evergreen_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val)
|
||||
{
|
||||
switch (reg) {
|
||||
case GRBM_STATUS:
|
||||
case GRBM_STATUS_SE0:
|
||||
case GRBM_STATUS_SE1:
|
||||
case SRBM_STATUS:
|
||||
case SRBM_STATUS2:
|
||||
case DMA_STATUS_REG:
|
||||
case UVD_STATUS:
|
||||
*val = RREG32(reg);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
|
||||
unsigned *bankh, unsigned *mtaspect,
|
||||
unsigned *tile_split)
|
||||
@ -4392,12 +4420,12 @@ int evergreen_irq_set(struct radeon_device *rdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
if (rdev->family == CHIP_ARUBA)
|
||||
thermal_int = RREG32(TN_CG_THERMAL_INT_CTRL) &
|
||||
~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
|
||||
@ -4486,27 +4514,27 @@ int evergreen_irq_set(struct radeon_device *rdev)
|
||||
}
|
||||
if (rdev->irq.hpd[0]) {
|
||||
DRM_DEBUG("evergreen_irq_set: hpd 1\n");
|
||||
hpd1 |= DC_HPDx_INT_EN;
|
||||
hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[1]) {
|
||||
DRM_DEBUG("evergreen_irq_set: hpd 2\n");
|
||||
hpd2 |= DC_HPDx_INT_EN;
|
||||
hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[2]) {
|
||||
DRM_DEBUG("evergreen_irq_set: hpd 3\n");
|
||||
hpd3 |= DC_HPDx_INT_EN;
|
||||
hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[3]) {
|
||||
DRM_DEBUG("evergreen_irq_set: hpd 4\n");
|
||||
hpd4 |= DC_HPDx_INT_EN;
|
||||
hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[4]) {
|
||||
DRM_DEBUG("evergreen_irq_set: hpd 5\n");
|
||||
hpd5 |= DC_HPDx_INT_EN;
|
||||
hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[5]) {
|
||||
DRM_DEBUG("evergreen_irq_set: hpd 6\n");
|
||||
hpd6 |= DC_HPDx_INT_EN;
|
||||
hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.afmt[0]) {
|
||||
DRM_DEBUG("evergreen_irq_set: hdmi 0\n");
|
||||
@ -4700,6 +4728,38 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD1_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD1_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD2_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD2_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD3_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD3_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD4_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD4_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
|
||||
if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) {
|
||||
tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
|
||||
tmp |= AFMT_AZ_FORMAT_WTRIG_ACK;
|
||||
@ -4780,6 +4840,7 @@ int evergreen_irq_process(struct radeon_device *rdev)
|
||||
u32 ring_index;
|
||||
bool queue_hotplug = false;
|
||||
bool queue_hdmi = false;
|
||||
bool queue_dp = false;
|
||||
bool queue_thermal = false;
|
||||
u32 status, addr;
|
||||
|
||||
@ -5019,6 +5080,48 @@ restart_ih:
|
||||
DRM_DEBUG("IH: HPD6\n");
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 1\n");
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 2\n");
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 3\n");
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 4\n");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 5\n");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 6\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
|
||||
break;
|
||||
@ -5151,6 +5254,8 @@ restart_ih:
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
WREG32(IH_RB_RPTR, rptr);
|
||||
}
|
||||
if (queue_dp)
|
||||
schedule_work(&rdev->dp_work);
|
||||
if (queue_hotplug)
|
||||
schedule_work(&rdev->hotplug_work);
|
||||
if (queue_hdmi)
|
||||
|
@ -1520,6 +1520,7 @@
|
||||
#define UVD_UDEC_DBW_ADDR_CONFIG 0xef54
|
||||
#define UVD_RBC_RB_RPTR 0xf690
|
||||
#define UVD_RBC_RB_WPTR 0xf694
|
||||
#define UVD_STATUS 0xf6bc
|
||||
|
||||
/*
|
||||
* PM4
|
||||
|
@ -2820,6 +2820,29 @@ void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
u32 kv_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct kv_power_info *pi = kv_get_pi(rdev);
|
||||
u32 current_index =
|
||||
(RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) >>
|
||||
CURR_SCLK_INDEX_SHIFT;
|
||||
u32 sclk;
|
||||
|
||||
if (current_index >= SMU__NUM_SCLK_DPM_STATE) {
|
||||
return 0;
|
||||
} else {
|
||||
sclk = be32_to_cpu(pi->graphics_level[current_index].SclkFrequency);
|
||||
return sclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 kv_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct kv_power_info *pi = kv_get_pi(rdev);
|
||||
|
||||
return pi->sys_info.bootup_uma_clk;
|
||||
}
|
||||
|
||||
void kv_dpm_print_power_state(struct radeon_device *rdev,
|
||||
struct radeon_ps *rps)
|
||||
{
|
||||
|
@ -828,6 +828,35 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* cayman_get_allowed_info_register - fetch the register for the info ioctl
|
||||
*
|
||||
* @rdev: radeon_device pointer
|
||||
* @reg: register offset in bytes
|
||||
* @val: register value
|
||||
*
|
||||
* Returns 0 for success or -EINVAL for an invalid register
|
||||
*
|
||||
*/
|
||||
int cayman_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val)
|
||||
{
|
||||
switch (reg) {
|
||||
case GRBM_STATUS:
|
||||
case GRBM_STATUS_SE0:
|
||||
case GRBM_STATUS_SE1:
|
||||
case SRBM_STATUS:
|
||||
case SRBM_STATUS2:
|
||||
case (DMA_STATUS_REG + DMA0_REGISTER_OFFSET):
|
||||
case (DMA_STATUS_REG + DMA1_REGISTER_OFFSET):
|
||||
case UVD_STATUS:
|
||||
*val = RREG32(reg);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int tn_get_temp(struct radeon_device *rdev)
|
||||
{
|
||||
u32 temp = RREG32_SMC(TN_CURRENT_GNB_TEMP) & 0x7ff;
|
||||
|
@ -4319,6 +4319,42 @@ void ni_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
u32 ni_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
|
||||
struct radeon_ps *rps = &eg_pi->current_rps;
|
||||
struct ni_ps *ps = ni_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
|
||||
CURRENT_STATE_INDEX_SHIFT;
|
||||
|
||||
if (current_index >= ps->performance_level_count) {
|
||||
return 0;
|
||||
} else {
|
||||
pl = &ps->performance_levels[current_index];
|
||||
return pl->sclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 ni_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
|
||||
struct radeon_ps *rps = &eg_pi->current_rps;
|
||||
struct ni_ps *ps = ni_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
|
||||
CURRENT_STATE_INDEX_SHIFT;
|
||||
|
||||
if (current_index >= ps->performance_level_count) {
|
||||
return 0;
|
||||
} else {
|
||||
pl = &ps->performance_levels[current_index];
|
||||
return pl->mclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low)
|
||||
{
|
||||
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
|
||||
|
@ -83,4 +83,48 @@
|
||||
# define NI_REGAMMA_PROG_B 4
|
||||
# define NI_OVL_REGAMMA_MODE(x) (((x) & 0x7) << 4)
|
||||
|
||||
#define NI_DP_MSE_LINK_TIMING 0x73a0
|
||||
# define NI_DP_MSE_LINK_FRAME (((x) & 0x3ff) << 0)
|
||||
# define NI_DP_MSE_LINK_LINE (((x) & 0x3) << 16)
|
||||
|
||||
#define NI_DP_MSE_MISC_CNTL 0x736c
|
||||
# define NI_DP_MSE_BLANK_CODE (((x) & 0x1) << 0)
|
||||
# define NI_DP_MSE_TIMESTAMP_MODE (((x) & 0x1) << 4)
|
||||
# define NI_DP_MSE_ZERO_ENCODER (((x) & 0x1) << 8)
|
||||
|
||||
#define NI_DP_MSE_RATE_CNTL 0x7384
|
||||
# define NI_DP_MSE_RATE_Y(x) (((x) & 0x3ffffff) << 0)
|
||||
# define NI_DP_MSE_RATE_X(x) (((x) & 0x3f) << 26)
|
||||
|
||||
#define NI_DP_MSE_RATE_UPDATE 0x738c
|
||||
|
||||
#define NI_DP_MSE_SAT0 0x7390
|
||||
# define NI_DP_MSE_SAT_SRC0(x) (((x) & 0x7) << 0)
|
||||
# define NI_DP_MSE_SAT_SLOT_COUNT0(x) (((x) & 0x3f) << 8)
|
||||
# define NI_DP_MSE_SAT_SRC1(x) (((x) & 0x7) << 16)
|
||||
# define NI_DP_MSE_SAT_SLOT_COUNT1(x) (((x) & 0x3f) << 24)
|
||||
|
||||
#define NI_DP_MSE_SAT1 0x7394
|
||||
|
||||
#define NI_DP_MSE_SAT2 0x7398
|
||||
|
||||
#define NI_DP_MSE_SAT_UPDATE 0x739c
|
||||
|
||||
#define NI_DIG_BE_CNTL 0x7140
|
||||
# define NI_DIG_FE_SOURCE_SELECT(x) (((x) & 0x7f) << 8)
|
||||
# define NI_DIG_FE_DIG_MODE(x) (((x) & 0x7) << 16)
|
||||
# define NI_DIG_MODE_DP_SST 0
|
||||
# define NI_DIG_MODE_LVDS 1
|
||||
# define NI_DIG_MODE_TMDS_DVI 2
|
||||
# define NI_DIG_MODE_TMDS_HDMI 3
|
||||
# define NI_DIG_MODE_DP_MST 5
|
||||
# define NI_DIG_HPD_SELECT(x) (((x) & 0x7) << 28)
|
||||
|
||||
#define NI_DIG_FE_CNTL 0x7000
|
||||
# define NI_DIG_SOURCE_SELECT(x) (((x) & 0x3) << 0)
|
||||
# define NI_DIG_STEREOSYNC_SELECT(x) (((x) & 0x3) << 4)
|
||||
# define NI_DIG_STEREOSYNC_GATE_EN(x) (((x) & 0x1) << 8)
|
||||
# define NI_DIG_DUAL_LINK_ENABLE(x) (((x) & 0x1) << 16)
|
||||
# define NI_DIG_SWAP(x) (((x) & 0x1) << 18)
|
||||
# define NI_DIG_SYMCLK_FE_ON (0x1 << 24)
|
||||
#endif
|
||||
|
@ -816,6 +816,52 @@
|
||||
#define MC_PMG_CMD_MRS2 0x2b5c
|
||||
#define MC_SEQ_PMG_CMD_MRS2_LP 0x2b60
|
||||
|
||||
#define AUX_CONTROL 0x6200
|
||||
#define AUX_EN (1 << 0)
|
||||
#define AUX_LS_READ_EN (1 << 8)
|
||||
#define AUX_LS_UPDATE_DISABLE(x) (((x) & 0x1) << 12)
|
||||
#define AUX_HPD_DISCON(x) (((x) & 0x1) << 16)
|
||||
#define AUX_DET_EN (1 << 18)
|
||||
#define AUX_HPD_SEL(x) (((x) & 0x7) << 20)
|
||||
#define AUX_IMPCAL_REQ_EN (1 << 24)
|
||||
#define AUX_TEST_MODE (1 << 28)
|
||||
#define AUX_DEGLITCH_EN (1 << 29)
|
||||
#define AUX_SW_CONTROL 0x6204
|
||||
#define AUX_SW_GO (1 << 0)
|
||||
#define AUX_LS_READ_TRIG (1 << 2)
|
||||
#define AUX_SW_START_DELAY(x) (((x) & 0xf) << 4)
|
||||
#define AUX_SW_WR_BYTES(x) (((x) & 0x1f) << 16)
|
||||
|
||||
#define AUX_SW_INTERRUPT_CONTROL 0x620c
|
||||
#define AUX_SW_DONE_INT (1 << 0)
|
||||
#define AUX_SW_DONE_ACK (1 << 1)
|
||||
#define AUX_SW_DONE_MASK (1 << 2)
|
||||
#define AUX_SW_LS_DONE_INT (1 << 4)
|
||||
#define AUX_SW_LS_DONE_MASK (1 << 6)
|
||||
#define AUX_SW_STATUS 0x6210
|
||||
#define AUX_SW_DONE (1 << 0)
|
||||
#define AUX_SW_REQ (1 << 1)
|
||||
#define AUX_SW_RX_TIMEOUT_STATE(x) (((x) & 0x7) << 4)
|
||||
#define AUX_SW_RX_TIMEOUT (1 << 7)
|
||||
#define AUX_SW_RX_OVERFLOW (1 << 8)
|
||||
#define AUX_SW_RX_HPD_DISCON (1 << 9)
|
||||
#define AUX_SW_RX_PARTIAL_BYTE (1 << 10)
|
||||
#define AUX_SW_NON_AUX_MODE (1 << 11)
|
||||
#define AUX_SW_RX_MIN_COUNT_VIOL (1 << 12)
|
||||
#define AUX_SW_RX_INVALID_STOP (1 << 14)
|
||||
#define AUX_SW_RX_SYNC_INVALID_L (1 << 17)
|
||||
#define AUX_SW_RX_SYNC_INVALID_H (1 << 18)
|
||||
#define AUX_SW_RX_INVALID_START (1 << 19)
|
||||
#define AUX_SW_RX_RECV_NO_DET (1 << 20)
|
||||
#define AUX_SW_RX_RECV_INVALID_H (1 << 22)
|
||||
#define AUX_SW_RX_RECV_INVALID_V (1 << 23)
|
||||
|
||||
#define AUX_SW_DATA 0x6218
|
||||
#define AUX_SW_DATA_RW (1 << 0)
|
||||
#define AUX_SW_DATA_MASK(x) (((x) & 0xff) << 8)
|
||||
#define AUX_SW_DATA_INDEX(x) (((x) & 0x1f) << 16)
|
||||
#define AUX_SW_AUTOINCREMENT_DISABLE (1 << 31)
|
||||
|
||||
#define LB_SYNC_RESET_SEL 0x6b28
|
||||
#define LB_SYNC_RESET_SEL_MASK (3 << 0)
|
||||
#define LB_SYNC_RESET_SEL_SHIFT 0
|
||||
@ -1086,6 +1132,7 @@
|
||||
#define UVD_UDEC_DBW_ADDR_CONFIG 0xEF54
|
||||
#define UVD_RBC_RB_RPTR 0xF690
|
||||
#define UVD_RBC_RB_WPTR 0xF694
|
||||
#define UVD_STATUS 0xf6bc
|
||||
|
||||
/*
|
||||
* PM4
|
||||
|
@ -108,6 +108,32 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev);
|
||||
extern int evergreen_rlc_resume(struct radeon_device *rdev);
|
||||
extern void rv770_set_clk_bypass_mode(struct radeon_device *rdev);
|
||||
|
||||
/**
|
||||
* r600_get_allowed_info_register - fetch the register for the info ioctl
|
||||
*
|
||||
* @rdev: radeon_device pointer
|
||||
* @reg: register offset in bytes
|
||||
* @val: register value
|
||||
*
|
||||
* Returns 0 for success or -EINVAL for an invalid register
|
||||
*
|
||||
*/
|
||||
int r600_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val)
|
||||
{
|
||||
switch (reg) {
|
||||
case GRBM_STATUS:
|
||||
case GRBM_STATUS2:
|
||||
case R_000E50_SRBM_STATUS:
|
||||
case DMA_STATUS_REG:
|
||||
case UVD_STATUS:
|
||||
*val = RREG32(reg);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_get_xclk - get the xclk
|
||||
*
|
||||
|
@ -111,6 +111,8 @@ extern int radeon_deep_color;
|
||||
extern int radeon_use_pflipirq;
|
||||
extern int radeon_bapm;
|
||||
extern int radeon_backlight;
|
||||
extern int radeon_auxch;
|
||||
extern int radeon_mst;
|
||||
|
||||
/*
|
||||
* Copy from radeon_drv.h so we don't have to include both and have conflicting
|
||||
@ -1856,6 +1858,8 @@ struct radeon_asic {
|
||||
u32 (*get_xclk)(struct radeon_device *rdev);
|
||||
/* get the gpu clock counter */
|
||||
uint64_t (*get_gpu_clock_counter)(struct radeon_device *rdev);
|
||||
/* get register for info ioctl */
|
||||
int (*get_allowed_info_register)(struct radeon_device *rdev, u32 reg, u32 *val);
|
||||
/* gart */
|
||||
struct {
|
||||
void (*tlb_flush)(struct radeon_device *rdev);
|
||||
@ -1984,6 +1988,8 @@ struct radeon_asic {
|
||||
u32 (*fan_ctrl_get_mode)(struct radeon_device *rdev);
|
||||
int (*set_fan_speed_percent)(struct radeon_device *rdev, u32 speed);
|
||||
int (*get_fan_speed_percent)(struct radeon_device *rdev, u32 *speed);
|
||||
u32 (*get_current_sclk)(struct radeon_device *rdev);
|
||||
u32 (*get_current_mclk)(struct radeon_device *rdev);
|
||||
} dpm;
|
||||
/* pageflipping */
|
||||
struct {
|
||||
@ -2407,6 +2413,7 @@ struct radeon_device {
|
||||
struct radeon_rlc rlc;
|
||||
struct radeon_mec mec;
|
||||
struct work_struct hotplug_work;
|
||||
struct work_struct dp_work;
|
||||
struct work_struct audio_work;
|
||||
int num_crtc; /* number of crtcs */
|
||||
struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
|
||||
@ -2931,6 +2938,7 @@ static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
|
||||
#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
|
||||
#define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev))
|
||||
#define radeon_get_gpu_clock_counter(rdev) (rdev)->asic->get_gpu_clock_counter((rdev))
|
||||
#define radeon_get_allowed_info_register(rdev, r, v) (rdev)->asic->get_allowed_info_register((rdev), (r), (v))
|
||||
#define radeon_dpm_init(rdev) rdev->asic->dpm.init((rdev))
|
||||
#define radeon_dpm_setup_asic(rdev) rdev->asic->dpm.setup_asic((rdev))
|
||||
#define radeon_dpm_enable(rdev) rdev->asic->dpm.enable((rdev))
|
||||
@ -2949,6 +2957,8 @@ static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
|
||||
#define radeon_dpm_vblank_too_short(rdev) rdev->asic->dpm.vblank_too_short((rdev))
|
||||
#define radeon_dpm_powergate_uvd(rdev, g) rdev->asic->dpm.powergate_uvd((rdev), (g))
|
||||
#define radeon_dpm_enable_bapm(rdev, e) rdev->asic->dpm.enable_bapm((rdev), (e))
|
||||
#define radeon_dpm_get_current_sclk(rdev) rdev->asic->dpm.get_current_sclk((rdev))
|
||||
#define radeon_dpm_get_current_mclk(rdev) rdev->asic->dpm.get_current_mclk((rdev))
|
||||
|
||||
/* Common functions */
|
||||
/* AGP */
|
||||
|
@ -136,6 +136,11 @@ static void radeon_register_accessor_init(struct radeon_device *rdev)
|
||||
}
|
||||
}
|
||||
|
||||
static int radeon_invalid_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* helper to disable agp */
|
||||
/**
|
||||
@ -199,6 +204,7 @@ static struct radeon_asic r100_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &r100_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &r100_pci_gart_tlb_flush,
|
||||
.get_page_entry = &r100_pci_gart_get_page_entry,
|
||||
@ -266,6 +272,7 @@ static struct radeon_asic r200_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &r100_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &r100_pci_gart_tlb_flush,
|
||||
.get_page_entry = &r100_pci_gart_get_page_entry,
|
||||
@ -361,6 +368,7 @@ static struct radeon_asic r300_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &r300_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &r100_pci_gart_tlb_flush,
|
||||
.get_page_entry = &r100_pci_gart_get_page_entry,
|
||||
@ -428,6 +436,7 @@ static struct radeon_asic r300_asic_pcie = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &r300_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rv370_pcie_gart_get_page_entry,
|
||||
@ -495,6 +504,7 @@ static struct radeon_asic r420_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &r300_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rv370_pcie_gart_get_page_entry,
|
||||
@ -562,6 +572,7 @@ static struct radeon_asic rs400_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &rs400_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &rs400_gart_tlb_flush,
|
||||
.get_page_entry = &rs400_gart_get_page_entry,
|
||||
@ -629,6 +640,7 @@ static struct radeon_asic rs600_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &rs600_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &rs600_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -696,6 +708,7 @@ static struct radeon_asic rs690_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &rs690_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &rs400_gart_tlb_flush,
|
||||
.get_page_entry = &rs400_gart_get_page_entry,
|
||||
@ -763,6 +776,7 @@ static struct radeon_asic rv515_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &rv515_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rv370_pcie_gart_get_page_entry,
|
||||
@ -830,6 +844,7 @@ static struct radeon_asic r520_asic = {
|
||||
.mmio_hdp_flush = NULL,
|
||||
.gui_idle = &r100_gui_idle,
|
||||
.mc_wait_for_idle = &r520_mc_wait_for_idle,
|
||||
.get_allowed_info_register = radeon_invalid_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rv370_pcie_gart_get_page_entry,
|
||||
@ -925,6 +940,7 @@ static struct radeon_asic r600_asic = {
|
||||
.mc_wait_for_idle = &r600_mc_wait_for_idle,
|
||||
.get_xclk = &r600_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = r600_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &r600_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1009,6 +1025,7 @@ static struct radeon_asic rv6xx_asic = {
|
||||
.mc_wait_for_idle = &r600_mc_wait_for_idle,
|
||||
.get_xclk = &r600_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = r600_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &r600_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1080,6 +1097,8 @@ static struct radeon_asic rv6xx_asic = {
|
||||
.print_power_state = &rv6xx_dpm_print_power_state,
|
||||
.debugfs_print_current_performance_level = &rv6xx_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &rv6xx_dpm_force_performance_level,
|
||||
.get_current_sclk = &rv6xx_dpm_get_current_sclk,
|
||||
.get_current_mclk = &rv6xx_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &rs600_page_flip,
|
||||
@ -1099,6 +1118,7 @@ static struct radeon_asic rs780_asic = {
|
||||
.mc_wait_for_idle = &r600_mc_wait_for_idle,
|
||||
.get_xclk = &r600_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = r600_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &r600_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1170,6 +1190,8 @@ static struct radeon_asic rs780_asic = {
|
||||
.print_power_state = &rs780_dpm_print_power_state,
|
||||
.debugfs_print_current_performance_level = &rs780_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &rs780_dpm_force_performance_level,
|
||||
.get_current_sclk = &rs780_dpm_get_current_sclk,
|
||||
.get_current_mclk = &rs780_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &rs600_page_flip,
|
||||
@ -1202,6 +1224,7 @@ static struct radeon_asic rv770_asic = {
|
||||
.mc_wait_for_idle = &r600_mc_wait_for_idle,
|
||||
.get_xclk = &rv770_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = r600_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &r600_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1274,6 +1297,8 @@ static struct radeon_asic rv770_asic = {
|
||||
.debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &rv770_dpm_force_performance_level,
|
||||
.vblank_too_short = &rv770_dpm_vblank_too_short,
|
||||
.get_current_sclk = &rv770_dpm_get_current_sclk,
|
||||
.get_current_mclk = &rv770_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &rv770_page_flip,
|
||||
@ -1319,6 +1344,7 @@ static struct radeon_asic evergreen_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &rv770_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = evergreen_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &evergreen_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1391,6 +1417,8 @@ static struct radeon_asic evergreen_asic = {
|
||||
.debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &rv770_dpm_force_performance_level,
|
||||
.vblank_too_short = &cypress_dpm_vblank_too_short,
|
||||
.get_current_sclk = &rv770_dpm_get_current_sclk,
|
||||
.get_current_mclk = &rv770_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
@ -1410,6 +1438,7 @@ static struct radeon_asic sumo_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &r600_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = evergreen_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &evergreen_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1481,6 +1510,8 @@ static struct radeon_asic sumo_asic = {
|
||||
.print_power_state = &sumo_dpm_print_power_state,
|
||||
.debugfs_print_current_performance_level = &sumo_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &sumo_dpm_force_performance_level,
|
||||
.get_current_sclk = &sumo_dpm_get_current_sclk,
|
||||
.get_current_mclk = &sumo_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
@ -1500,6 +1531,7 @@ static struct radeon_asic btc_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &rv770_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = evergreen_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &evergreen_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1572,6 +1604,8 @@ static struct radeon_asic btc_asic = {
|
||||
.debugfs_print_current_performance_level = &btc_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &rv770_dpm_force_performance_level,
|
||||
.vblank_too_short = &btc_dpm_vblank_too_short,
|
||||
.get_current_sclk = &btc_dpm_get_current_sclk,
|
||||
.get_current_mclk = &btc_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
@ -1634,6 +1668,7 @@ static struct radeon_asic cayman_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &rv770_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = cayman_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &cayman_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1717,6 +1752,8 @@ static struct radeon_asic cayman_asic = {
|
||||
.debugfs_print_current_performance_level = &ni_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &ni_dpm_force_performance_level,
|
||||
.vblank_too_short = &ni_dpm_vblank_too_short,
|
||||
.get_current_sclk = &ni_dpm_get_current_sclk,
|
||||
.get_current_mclk = &ni_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
@ -1736,6 +1773,7 @@ static struct radeon_asic trinity_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &r600_get_xclk,
|
||||
.get_gpu_clock_counter = &r600_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = cayman_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &cayman_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1819,6 +1857,8 @@ static struct radeon_asic trinity_asic = {
|
||||
.debugfs_print_current_performance_level = &trinity_dpm_debugfs_print_current_performance_level,
|
||||
.force_performance_level = &trinity_dpm_force_performance_level,
|
||||
.enable_bapm = &trinity_dpm_enable_bapm,
|
||||
.get_current_sclk = &trinity_dpm_get_current_sclk,
|
||||
.get_current_mclk = &trinity_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
@ -1868,6 +1908,7 @@ static struct radeon_asic si_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &si_get_xclk,
|
||||
.get_gpu_clock_counter = &si_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = si_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &si_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -1955,6 +1996,8 @@ static struct radeon_asic si_asic = {
|
||||
.fan_ctrl_get_mode = &si_fan_ctrl_get_mode,
|
||||
.get_fan_speed_percent = &si_fan_ctrl_get_fan_speed_percent,
|
||||
.set_fan_speed_percent = &si_fan_ctrl_set_fan_speed_percent,
|
||||
.get_current_sclk = &si_dpm_get_current_sclk,
|
||||
.get_current_mclk = &si_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
@ -2032,6 +2075,7 @@ static struct radeon_asic ci_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &cik_get_xclk,
|
||||
.get_gpu_clock_counter = &cik_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = cik_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &cik_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -2123,6 +2167,8 @@ static struct radeon_asic ci_asic = {
|
||||
.fan_ctrl_get_mode = &ci_fan_ctrl_get_mode,
|
||||
.get_fan_speed_percent = &ci_fan_ctrl_get_fan_speed_percent,
|
||||
.set_fan_speed_percent = &ci_fan_ctrl_set_fan_speed_percent,
|
||||
.get_current_sclk = &ci_dpm_get_current_sclk,
|
||||
.get_current_mclk = &ci_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
@ -2142,6 +2188,7 @@ static struct radeon_asic kv_asic = {
|
||||
.mc_wait_for_idle = &evergreen_mc_wait_for_idle,
|
||||
.get_xclk = &cik_get_xclk,
|
||||
.get_gpu_clock_counter = &cik_get_gpu_clock_counter,
|
||||
.get_allowed_info_register = cik_get_allowed_info_register,
|
||||
.gart = {
|
||||
.tlb_flush = &cik_pcie_gart_tlb_flush,
|
||||
.get_page_entry = &rs600_gart_get_page_entry,
|
||||
@ -2229,6 +2276,8 @@ static struct radeon_asic kv_asic = {
|
||||
.force_performance_level = &kv_dpm_force_performance_level,
|
||||
.powergate_uvd = &kv_dpm_powergate_uvd,
|
||||
.enable_bapm = &kv_dpm_enable_bapm,
|
||||
.get_current_sclk = &kv_dpm_get_current_sclk,
|
||||
.get_current_mclk = &kv_dpm_get_current_mclk,
|
||||
},
|
||||
.pflip = {
|
||||
.page_flip = &evergreen_page_flip,
|
||||
|
@ -384,6 +384,8 @@ u32 r600_gfx_get_wptr(struct radeon_device *rdev,
|
||||
struct radeon_ring *ring);
|
||||
void r600_gfx_set_wptr(struct radeon_device *rdev,
|
||||
struct radeon_ring *ring);
|
||||
int r600_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val);
|
||||
/* r600 irq */
|
||||
int r600_irq_process(struct radeon_device *rdev);
|
||||
int r600_irq_init(struct radeon_device *rdev);
|
||||
@ -433,6 +435,8 @@ void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||
struct seq_file *m);
|
||||
int rv6xx_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
u32 rv6xx_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 rv6xx_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
/* rs780 dpm */
|
||||
int rs780_dpm_init(struct radeon_device *rdev);
|
||||
int rs780_dpm_enable(struct radeon_device *rdev);
|
||||
@ -449,6 +453,8 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||
struct seq_file *m);
|
||||
int rs780_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
u32 rs780_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 rs780_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
|
||||
/*
|
||||
* rv770,rv730,rv710,rv740
|
||||
@ -488,6 +494,8 @@ void rv770_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||
int rv770_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
bool rv770_dpm_vblank_too_short(struct radeon_device *rdev);
|
||||
u32 rv770_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 rv770_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
|
||||
/*
|
||||
* evergreen
|
||||
@ -540,6 +548,8 @@ struct radeon_fence *evergreen_copy_dma(struct radeon_device *rdev,
|
||||
unsigned num_gpu_pages,
|
||||
struct reservation_object *resv);
|
||||
int evergreen_get_temp(struct radeon_device *rdev);
|
||||
int evergreen_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val);
|
||||
int sumo_get_temp(struct radeon_device *rdev);
|
||||
int tn_get_temp(struct radeon_device *rdev);
|
||||
int cypress_dpm_init(struct radeon_device *rdev);
|
||||
@ -563,6 +573,8 @@ u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low);
|
||||
bool btc_dpm_vblank_too_short(struct radeon_device *rdev);
|
||||
void btc_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
|
||||
struct seq_file *m);
|
||||
u32 btc_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 btc_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
int sumo_dpm_init(struct radeon_device *rdev);
|
||||
int sumo_dpm_enable(struct radeon_device *rdev);
|
||||
int sumo_dpm_late_enable(struct radeon_device *rdev);
|
||||
@ -581,6 +593,8 @@ void sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev
|
||||
struct seq_file *m);
|
||||
int sumo_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
u32 sumo_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 sumo_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
|
||||
/*
|
||||
* cayman
|
||||
@ -637,6 +651,8 @@ uint32_t cayman_dma_get_wptr(struct radeon_device *rdev,
|
||||
struct radeon_ring *ring);
|
||||
void cayman_dma_set_wptr(struct radeon_device *rdev,
|
||||
struct radeon_ring *ring);
|
||||
int cayman_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val);
|
||||
|
||||
int ni_dpm_init(struct radeon_device *rdev);
|
||||
void ni_dpm_setup_asic(struct radeon_device *rdev);
|
||||
@ -655,6 +671,8 @@ void ni_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
|
||||
int ni_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
bool ni_dpm_vblank_too_short(struct radeon_device *rdev);
|
||||
u32 ni_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 ni_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
int trinity_dpm_init(struct radeon_device *rdev);
|
||||
int trinity_dpm_enable(struct radeon_device *rdev);
|
||||
int trinity_dpm_late_enable(struct radeon_device *rdev);
|
||||
@ -674,6 +692,8 @@ void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *r
|
||||
int trinity_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
|
||||
u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
|
||||
/* DCE6 - SI */
|
||||
void dce6_bandwidth_update(struct radeon_device *rdev);
|
||||
@ -726,6 +746,8 @@ u32 si_get_xclk(struct radeon_device *rdev);
|
||||
uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev);
|
||||
int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
|
||||
int si_get_temp(struct radeon_device *rdev);
|
||||
int si_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val);
|
||||
int si_dpm_init(struct radeon_device *rdev);
|
||||
void si_dpm_setup_asic(struct radeon_device *rdev);
|
||||
int si_dpm_enable(struct radeon_device *rdev);
|
||||
@ -746,6 +768,8 @@ int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
|
||||
u32 speed);
|
||||
u32 si_fan_ctrl_get_mode(struct radeon_device *rdev);
|
||||
void si_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode);
|
||||
u32 si_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 si_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
|
||||
/* DCE8 - CIK */
|
||||
void dce8_bandwidth_update(struct radeon_device *rdev);
|
||||
@ -841,6 +865,8 @@ void cik_sdma_set_wptr(struct radeon_device *rdev,
|
||||
struct radeon_ring *ring);
|
||||
int ci_get_temp(struct radeon_device *rdev);
|
||||
int kv_get_temp(struct radeon_device *rdev);
|
||||
int cik_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val);
|
||||
|
||||
int ci_dpm_init(struct radeon_device *rdev);
|
||||
int ci_dpm_enable(struct radeon_device *rdev);
|
||||
@ -862,6 +888,8 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
bool ci_dpm_vblank_too_short(struct radeon_device *rdev);
|
||||
void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
|
||||
u32 ci_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 ci_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
|
||||
int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
|
||||
u32 *speed);
|
||||
@ -890,6 +918,8 @@ int kv_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level);
|
||||
void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
|
||||
void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
|
||||
u32 kv_dpm_get_current_sclk(struct radeon_device *rdev);
|
||||
u32 kv_dpm_get_current_mclk(struct radeon_device *rdev);
|
||||
|
||||
/* uvd v1.0 */
|
||||
uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
|
||||
|
@ -845,6 +845,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
||||
|
||||
radeon_link_encoder_connector(dev);
|
||||
|
||||
radeon_setup_mst_connector(dev);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -520,16 +520,40 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
|
||||
struct radeon_device *rdev = encoder->dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector = NULL;
|
||||
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
|
||||
struct hdmi_avi_infoframe frame;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(connector,
|
||||
&encoder->dev->mode_config.connector_list, head) {
|
||||
if (connector->encoder == encoder) {
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!radeon_connector) {
|
||||
DRM_ERROR("Couldn't find encoder's connector\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
|
||||
if (err < 0) {
|
||||
DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (drm_rgb_quant_range_selectable(radeon_connector_edid(connector))) {
|
||||
if (radeon_encoder->output_csc == RADEON_OUTPUT_CSC_TVRGB)
|
||||
frame.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED;
|
||||
else
|
||||
frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
|
||||
} else {
|
||||
frame.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
|
||||
}
|
||||
|
||||
err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
|
||||
if (err < 0) {
|
||||
DRM_ERROR("failed to pack AVI infoframe: %d\n", err);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
#include "radeon.h"
|
||||
#include "radeon_audio.h"
|
||||
@ -34,12 +35,33 @@
|
||||
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
static int radeon_dp_handle_hpd(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
int ret;
|
||||
|
||||
ret = radeon_dp_mst_check_status(radeon_connector);
|
||||
if (ret == -EINVAL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
void radeon_connector_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
|
||||
struct radeon_connector_atom_dig *dig_connector =
|
||||
radeon_connector->con_priv;
|
||||
|
||||
if (radeon_connector->is_mst_connector)
|
||||
return;
|
||||
if (dig_connector->is_mst) {
|
||||
radeon_dp_handle_hpd(connector);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* bail if the connector does not have hpd pin, e.g.,
|
||||
* VGA, TV, etc.
|
||||
*/
|
||||
@ -725,6 +747,30 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
|
||||
radeon_property_change_mode(&radeon_encoder->base);
|
||||
}
|
||||
|
||||
if (property == rdev->mode_info.output_csc_property) {
|
||||
if (connector->encoder)
|
||||
radeon_encoder = to_radeon_encoder(connector->encoder);
|
||||
else {
|
||||
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
|
||||
radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
|
||||
}
|
||||
|
||||
if (radeon_encoder->output_csc == val)
|
||||
return 0;
|
||||
|
||||
radeon_encoder->output_csc = val;
|
||||
|
||||
if (connector->encoder->crtc) {
|
||||
struct drm_crtc *crtc = connector->encoder->crtc;
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
|
||||
radeon_crtc->output_csc = radeon_encoder->output_csc;
|
||||
|
||||
(*crtc_funcs->load_lut)(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1585,6 +1631,9 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
||||
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
|
||||
int r;
|
||||
|
||||
if (radeon_dig_connector->is_mst)
|
||||
return connector_status_disconnected;
|
||||
|
||||
r = pm_runtime_get_sync(connector->dev->dev);
|
||||
if (r < 0)
|
||||
return connector_status_disconnected;
|
||||
@ -1643,12 +1692,21 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
||||
radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
|
||||
if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
|
||||
ret = connector_status_connected;
|
||||
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
|
||||
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
|
||||
radeon_dp_getdpcd(radeon_connector);
|
||||
r = radeon_dp_mst_probe(radeon_connector);
|
||||
if (r == 1)
|
||||
ret = connector_status_disconnected;
|
||||
}
|
||||
} else {
|
||||
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
|
||||
if (radeon_dp_getdpcd(radeon_connector))
|
||||
ret = connector_status_connected;
|
||||
if (radeon_dp_getdpcd(radeon_connector)) {
|
||||
r = radeon_dp_mst_probe(radeon_connector);
|
||||
if (r == 1)
|
||||
ret = connector_status_disconnected;
|
||||
else
|
||||
ret = connector_status_connected;
|
||||
}
|
||||
} else {
|
||||
/* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */
|
||||
if (radeon_ddc_probe(radeon_connector, false))
|
||||
@ -1872,6 +1930,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
DRM_MODE_SCALE_NONE);
|
||||
if (ASIC_IS_DCE5(rdev))
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.output_csc_property,
|
||||
RADEON_OUTPUT_CSC_BYPASS);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
@ -1904,6 +1966,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.audio_property,
|
||||
RADEON_AUDIO_AUTO);
|
||||
if (ASIC_IS_DCE5(rdev))
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.output_csc_property,
|
||||
RADEON_OUTPUT_CSC_BYPASS);
|
||||
|
||||
subpixel_order = SubPixelHorizontalRGB;
|
||||
connector->interlace_allowed = true;
|
||||
@ -1950,6 +2016,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
DRM_MODE_SCALE_NONE);
|
||||
if (ASIC_IS_DCE5(rdev))
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.output_csc_property,
|
||||
RADEON_OUTPUT_CSC_BYPASS);
|
||||
/* no HPD on analog connectors */
|
||||
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
@ -1972,6 +2042,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
DRM_MODE_SCALE_NONE);
|
||||
if (ASIC_IS_DCE5(rdev))
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.output_csc_property,
|
||||
RADEON_OUTPUT_CSC_BYPASS);
|
||||
/* no HPD on analog connectors */
|
||||
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
||||
connector->interlace_allowed = true;
|
||||
@ -2023,6 +2097,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
}
|
||||
if (ASIC_IS_DCE5(rdev))
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.output_csc_property,
|
||||
RADEON_OUTPUT_CSC_BYPASS);
|
||||
connector->interlace_allowed = true;
|
||||
if (connector_type == DRM_MODE_CONNECTOR_DVII)
|
||||
connector->doublescan_allowed = true;
|
||||
@ -2068,6 +2146,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
rdev->mode_info.audio_property,
|
||||
RADEON_AUDIO_AUTO);
|
||||
}
|
||||
if (ASIC_IS_DCE5(rdev))
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.output_csc_property,
|
||||
RADEON_OUTPUT_CSC_BYPASS);
|
||||
subpixel_order = SubPixelHorizontalRGB;
|
||||
connector->interlace_allowed = true;
|
||||
if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
|
||||
@ -2116,6 +2198,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
rdev->mode_info.audio_property,
|
||||
RADEON_AUDIO_AUTO);
|
||||
}
|
||||
if (ASIC_IS_DCE5(rdev))
|
||||
drm_object_attach_property(&radeon_connector->base.base,
|
||||
rdev->mode_info.output_csc_property,
|
||||
RADEON_OUTPUT_CSC_BYPASS);
|
||||
connector->interlace_allowed = true;
|
||||
/* in theory with a DP to VGA converter... */
|
||||
connector->doublescan_allowed = false;
|
||||
@ -2352,3 +2438,27 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
||||
connector->display_info.subpixel_order = subpixel_order;
|
||||
drm_connector_register(connector);
|
||||
}
|
||||
|
||||
void radeon_setup_mst_connector(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
|
||||
if (!ASIC_IS_DCE5(rdev))
|
||||
return;
|
||||
|
||||
if (radeon_mst == 0)
|
||||
return;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
int ret;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
|
||||
continue;
|
||||
|
||||
ret = radeon_dp_mst_init(radeon_connector);
|
||||
}
|
||||
}
|
||||
|
@ -1442,6 +1442,11 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||
DRM_ERROR("registering gem debugfs failed (%d).\n", r);
|
||||
}
|
||||
|
||||
r = radeon_mst_debugfs_init(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("registering mst debugfs failed (%d).\n", r);
|
||||
}
|
||||
|
||||
if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) {
|
||||
/* Acceleration not working on AGP card try again
|
||||
* with fallback to PCI or PCIE GART
|
||||
|
@ -154,7 +154,7 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc)
|
||||
(NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
|
||||
NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
|
||||
WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset,
|
||||
(NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) |
|
||||
(NI_OUTPUT_CSC_GRPH_MODE(radeon_crtc->output_csc) |
|
||||
NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
|
||||
/* XXX match this to the depth of the crtc fmt block, move to modeset? */
|
||||
WREG32(0x6940 + radeon_crtc->crtc_offset, 0);
|
||||
@ -1382,6 +1382,13 @@ static struct drm_prop_enum_list radeon_dither_enum_list[] =
|
||||
{ RADEON_FMT_DITHER_ENABLE, "on" },
|
||||
};
|
||||
|
||||
static struct drm_prop_enum_list radeon_output_csc_enum_list[] =
|
||||
{ { RADEON_OUTPUT_CSC_BYPASS, "bypass" },
|
||||
{ RADEON_OUTPUT_CSC_TVRGB, "tvrgb" },
|
||||
{ RADEON_OUTPUT_CSC_YCBCR601, "ycbcr601" },
|
||||
{ RADEON_OUTPUT_CSC_YCBCR709, "ycbcr709" },
|
||||
};
|
||||
|
||||
static int radeon_modeset_create_props(struct radeon_device *rdev)
|
||||
{
|
||||
int sz;
|
||||
@ -1444,6 +1451,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
|
||||
"dither",
|
||||
radeon_dither_enum_list, sz);
|
||||
|
||||
sz = ARRAY_SIZE(radeon_output_csc_enum_list);
|
||||
rdev->mode_info.output_csc_property =
|
||||
drm_property_create_enum(rdev->ddev, 0,
|
||||
"output_csc",
|
||||
radeon_output_csc_enum_list, sz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
206
drivers/gpu/drm/radeon/radeon_dp_auxch.c
Normal file
206
drivers/gpu/drm/radeon/radeon_dp_auxch.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2015 Red Hat 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: Dave Airlie
|
||||
*/
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
#include "radeon.h"
|
||||
#include "nid.h"
|
||||
|
||||
#define AUX_RX_ERROR_FLAGS (AUX_SW_RX_OVERFLOW | \
|
||||
AUX_SW_RX_HPD_DISCON | \
|
||||
AUX_SW_RX_PARTIAL_BYTE | \
|
||||
AUX_SW_NON_AUX_MODE | \
|
||||
AUX_SW_RX_MIN_COUNT_VIOL | \
|
||||
AUX_SW_RX_INVALID_STOP | \
|
||||
AUX_SW_RX_SYNC_INVALID_L | \
|
||||
AUX_SW_RX_SYNC_INVALID_H | \
|
||||
AUX_SW_RX_INVALID_START | \
|
||||
AUX_SW_RX_RECV_NO_DET | \
|
||||
AUX_SW_RX_RECV_INVALID_H | \
|
||||
AUX_SW_RX_RECV_INVALID_V)
|
||||
|
||||
#define AUX_SW_REPLY_GET_BYTE_COUNT(x) (((x) >> 24) & 0x1f)
|
||||
|
||||
#define BARE_ADDRESS_SIZE 3
|
||||
|
||||
static const u32 aux_offset[] =
|
||||
{
|
||||
0x6200 - 0x6200,
|
||||
0x6250 - 0x6200,
|
||||
0x62a0 - 0x6200,
|
||||
0x6300 - 0x6200,
|
||||
0x6350 - 0x6200,
|
||||
0x63a0 - 0x6200,
|
||||
};
|
||||
|
||||
ssize_t
|
||||
radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
struct radeon_i2c_chan *chan =
|
||||
container_of(aux, struct radeon_i2c_chan, aux);
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
int ret = 0, i;
|
||||
uint32_t tmp, ack = 0;
|
||||
int instance = chan->rec.i2c_id & 0xf;
|
||||
u8 byte;
|
||||
u8 *buf = msg->buffer;
|
||||
int retry_count = 0;
|
||||
int bytes;
|
||||
int msize;
|
||||
bool is_write = false;
|
||||
|
||||
if (WARN_ON(msg->size > 16))
|
||||
return -E2BIG;
|
||||
|
||||
switch (msg->request & ~DP_AUX_I2C_MOT) {
|
||||
case DP_AUX_NATIVE_WRITE:
|
||||
case DP_AUX_I2C_WRITE:
|
||||
is_write = true;
|
||||
break;
|
||||
case DP_AUX_NATIVE_READ:
|
||||
case DP_AUX_I2C_READ:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* work out two sizes required */
|
||||
msize = 0;
|
||||
bytes = BARE_ADDRESS_SIZE;
|
||||
if (msg->size) {
|
||||
msize = msg->size - 1;
|
||||
bytes++;
|
||||
if (is_write)
|
||||
bytes += msg->size;
|
||||
}
|
||||
|
||||
mutex_lock(&chan->mutex);
|
||||
|
||||
/* switch the pad to aux mode */
|
||||
tmp = RREG32(chan->rec.mask_clk_reg);
|
||||
tmp |= (1 << 16);
|
||||
WREG32(chan->rec.mask_clk_reg, tmp);
|
||||
|
||||
/* setup AUX control register with correct HPD pin */
|
||||
tmp = RREG32(AUX_CONTROL + aux_offset[instance]);
|
||||
|
||||
tmp &= AUX_HPD_SEL(0x7);
|
||||
tmp |= AUX_HPD_SEL(chan->rec.hpd);
|
||||
tmp |= AUX_EN | AUX_LS_READ_EN;
|
||||
|
||||
WREG32(AUX_CONTROL + aux_offset[instance], tmp);
|
||||
|
||||
/* atombios appears to write this twice lets copy it */
|
||||
WREG32(AUX_SW_CONTROL + aux_offset[instance],
|
||||
AUX_SW_WR_BYTES(bytes));
|
||||
WREG32(AUX_SW_CONTROL + aux_offset[instance],
|
||||
AUX_SW_WR_BYTES(bytes));
|
||||
|
||||
/* write the data header into the registers */
|
||||
/* request, addres, msg size */
|
||||
byte = (msg->request << 4);
|
||||
WREG32(AUX_SW_DATA + aux_offset[instance],
|
||||
AUX_SW_DATA_MASK(byte) | AUX_SW_AUTOINCREMENT_DISABLE);
|
||||
|
||||
byte = (msg->address >> 8) & 0xff;
|
||||
WREG32(AUX_SW_DATA + aux_offset[instance],
|
||||
AUX_SW_DATA_MASK(byte));
|
||||
|
||||
byte = msg->address & 0xff;
|
||||
WREG32(AUX_SW_DATA + aux_offset[instance],
|
||||
AUX_SW_DATA_MASK(byte));
|
||||
|
||||
byte = msize;
|
||||
WREG32(AUX_SW_DATA + aux_offset[instance],
|
||||
AUX_SW_DATA_MASK(byte));
|
||||
|
||||
/* if we are writing - write the msg buffer */
|
||||
if (is_write) {
|
||||
for (i = 0; i < msg->size; i++) {
|
||||
WREG32(AUX_SW_DATA + aux_offset[instance],
|
||||
AUX_SW_DATA_MASK(buf[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/* clear the ACK */
|
||||
WREG32(AUX_SW_INTERRUPT_CONTROL + aux_offset[instance], AUX_SW_DONE_ACK);
|
||||
|
||||
/* write the size and GO bits */
|
||||
WREG32(AUX_SW_CONTROL + aux_offset[instance],
|
||||
AUX_SW_WR_BYTES(bytes) | AUX_SW_GO);
|
||||
|
||||
/* poll the status registers - TODO irq support */
|
||||
do {
|
||||
tmp = RREG32(AUX_SW_STATUS + aux_offset[instance]);
|
||||
if (tmp & AUX_SW_DONE) {
|
||||
break;
|
||||
}
|
||||
usleep_range(100, 200);
|
||||
} while (retry_count++ < 1000);
|
||||
|
||||
if (retry_count >= 1000) {
|
||||
DRM_ERROR("auxch hw never signalled completion, error %08x\n", tmp);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (tmp & AUX_SW_RX_TIMEOUT) {
|
||||
DRM_DEBUG_KMS("dp_aux_ch timed out\n");
|
||||
ret = -ETIMEDOUT;
|
||||
goto done;
|
||||
}
|
||||
if (tmp & AUX_RX_ERROR_FLAGS) {
|
||||
DRM_DEBUG_KMS("dp_aux_ch flags not zero: %08x\n", tmp);
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytes = AUX_SW_REPLY_GET_BYTE_COUNT(tmp);
|
||||
if (bytes) {
|
||||
WREG32(AUX_SW_DATA + aux_offset[instance],
|
||||
AUX_SW_DATA_RW | AUX_SW_AUTOINCREMENT_DISABLE);
|
||||
|
||||
tmp = RREG32(AUX_SW_DATA + aux_offset[instance]);
|
||||
ack = (tmp >> 8) & 0xff;
|
||||
|
||||
for (i = 0; i < bytes - 1; i++) {
|
||||
tmp = RREG32(AUX_SW_DATA + aux_offset[instance]);
|
||||
if (buf)
|
||||
buf[i] = (tmp >> 8) & 0xff;
|
||||
}
|
||||
if (buf)
|
||||
ret = bytes - 1;
|
||||
}
|
||||
|
||||
WREG32(AUX_SW_INTERRUPT_CONTROL + aux_offset[instance], AUX_SW_DONE_ACK);
|
||||
|
||||
if (is_write)
|
||||
ret = msg->size;
|
||||
done:
|
||||
mutex_unlock(&chan->mutex);
|
||||
|
||||
if (ret >= 0)
|
||||
msg->reply = ack >> 4;
|
||||
return ret;
|
||||
}
|
782
drivers/gpu/drm/radeon/radeon_dp_mst.c
Normal file
782
drivers/gpu/drm/radeon/radeon_dp_mst.c
Normal file
@ -0,0 +1,782 @@
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
|
||||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
#include "ni_reg.h"
|
||||
|
||||
static struct radeon_encoder *radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector);
|
||||
|
||||
static int radeon_atom_set_enc_offset(int id)
|
||||
{
|
||||
static const int offsets[] = { EVERGREEN_CRTC0_REGISTER_OFFSET,
|
||||
EVERGREEN_CRTC1_REGISTER_OFFSET,
|
||||
EVERGREEN_CRTC2_REGISTER_OFFSET,
|
||||
EVERGREEN_CRTC3_REGISTER_OFFSET,
|
||||
EVERGREEN_CRTC4_REGISTER_OFFSET,
|
||||
EVERGREEN_CRTC5_REGISTER_OFFSET,
|
||||
0x13830 - 0x7030 };
|
||||
|
||||
return offsets[id];
|
||||
}
|
||||
|
||||
static int radeon_dp_mst_set_be_cntl(struct radeon_encoder *primary,
|
||||
struct radeon_encoder_mst *mst_enc,
|
||||
enum radeon_hpd_id hpd, bool enable)
|
||||
{
|
||||
struct drm_device *dev = primary->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t reg;
|
||||
int retries = 0;
|
||||
uint32_t temp;
|
||||
|
||||
reg = RREG32(NI_DIG_BE_CNTL + primary->offset);
|
||||
|
||||
/* set MST mode */
|
||||
reg &= ~NI_DIG_FE_DIG_MODE(7);
|
||||
reg |= NI_DIG_FE_DIG_MODE(NI_DIG_MODE_DP_MST);
|
||||
|
||||
if (enable)
|
||||
reg |= NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe);
|
||||
else
|
||||
reg &= ~NI_DIG_FE_SOURCE_SELECT(1 << mst_enc->fe);
|
||||
|
||||
reg |= NI_DIG_HPD_SELECT(hpd);
|
||||
DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DIG_BE_CNTL + primary->offset, reg);
|
||||
WREG32(NI_DIG_BE_CNTL + primary->offset, reg);
|
||||
|
||||
if (enable) {
|
||||
uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe);
|
||||
|
||||
do {
|
||||
temp = RREG32(NI_DIG_FE_CNTL + offset);
|
||||
} while ((temp & NI_DIG_SYMCLK_FE_ON) && retries++ < 10000);
|
||||
if (retries == 10000)
|
||||
DRM_ERROR("timed out waiting for FE %d %d\n", primary->offset, mst_enc->fe);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_dp_mst_set_stream_attrib(struct radeon_encoder *primary,
|
||||
int stream_number,
|
||||
int fe,
|
||||
int slots)
|
||||
{
|
||||
struct drm_device *dev = primary->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
u32 temp, val;
|
||||
int retries = 0;
|
||||
int satreg, satidx;
|
||||
|
||||
satreg = stream_number >> 1;
|
||||
satidx = stream_number & 1;
|
||||
|
||||
temp = RREG32(NI_DP_MSE_SAT0 + satreg + primary->offset);
|
||||
|
||||
val = NI_DP_MSE_SAT_SLOT_COUNT0(slots) | NI_DP_MSE_SAT_SRC0(fe);
|
||||
|
||||
val <<= (16 * satidx);
|
||||
|
||||
temp &= ~(0xffff << (16 * satidx));
|
||||
|
||||
temp |= val;
|
||||
|
||||
DRM_DEBUG_KMS("writing 0x%08x 0x%08x\n", NI_DP_MSE_SAT0 + satreg + primary->offset, temp);
|
||||
WREG32(NI_DP_MSE_SAT0 + satreg + primary->offset, temp);
|
||||
|
||||
WREG32(NI_DP_MSE_SAT_UPDATE + primary->offset, 1);
|
||||
|
||||
do {
|
||||
temp = RREG32(NI_DP_MSE_SAT_UPDATE + primary->offset);
|
||||
} while ((temp & 0x1) && retries++ < 10000);
|
||||
|
||||
if (retries == 10000)
|
||||
DRM_ERROR("timed out waitin for SAT update %d\n", primary->offset);
|
||||
|
||||
/* MTP 16 ? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_dp_mst_update_stream_attribs(struct radeon_connector *mst_conn,
|
||||
struct radeon_encoder *primary)
|
||||
{
|
||||
struct drm_device *dev = mst_conn->base.dev;
|
||||
struct stream_attribs new_attribs[6];
|
||||
int i;
|
||||
int idx = 0;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct drm_connector *connector;
|
||||
|
||||
memset(new_attribs, 0, sizeof(new_attribs));
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_encoder *subenc;
|
||||
struct radeon_encoder_mst *mst_enc;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
if (!radeon_connector->is_mst_connector)
|
||||
continue;
|
||||
|
||||
if (radeon_connector->mst_port != mst_conn)
|
||||
continue;
|
||||
|
||||
subenc = radeon_connector->mst_encoder;
|
||||
mst_enc = subenc->enc_priv;
|
||||
|
||||
if (!mst_enc->enc_active)
|
||||
continue;
|
||||
|
||||
new_attribs[idx].fe = mst_enc->fe;
|
||||
new_attribs[idx].slots = drm_dp_mst_get_vcpi_slots(&mst_conn->mst_mgr, mst_enc->port);
|
||||
idx++;
|
||||
}
|
||||
|
||||
for (i = 0; i < idx; i++) {
|
||||
if (new_attribs[i].fe != mst_conn->cur_stream_attribs[i].fe ||
|
||||
new_attribs[i].slots != mst_conn->cur_stream_attribs[i].slots) {
|
||||
radeon_dp_mst_set_stream_attrib(primary, i, new_attribs[i].fe, new_attribs[i].slots);
|
||||
mst_conn->cur_stream_attribs[i].fe = new_attribs[i].fe;
|
||||
mst_conn->cur_stream_attribs[i].slots = new_attribs[i].slots;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = idx; i < mst_conn->enabled_attribs; i++) {
|
||||
radeon_dp_mst_set_stream_attrib(primary, i, 0, 0);
|
||||
mst_conn->cur_stream_attribs[i].fe = 0;
|
||||
mst_conn->cur_stream_attribs[i].slots = 0;
|
||||
}
|
||||
mst_conn->enabled_attribs = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_dp_mst_set_vcp_size(struct radeon_encoder *mst, uint32_t x, uint32_t y)
|
||||
{
|
||||
struct drm_device *dev = mst->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder_mst *mst_enc = mst->enc_priv;
|
||||
uint32_t val, temp;
|
||||
uint32_t offset = radeon_atom_set_enc_offset(mst_enc->fe);
|
||||
int retries = 0;
|
||||
|
||||
val = NI_DP_MSE_RATE_X(x) | NI_DP_MSE_RATE_Y(y);
|
||||
|
||||
WREG32(NI_DP_MSE_RATE_CNTL + offset, val);
|
||||
|
||||
do {
|
||||
temp = RREG32(NI_DP_MSE_RATE_UPDATE + offset);
|
||||
} while ((temp & 0x1) && (retries++ < 10000));
|
||||
|
||||
if (retries >= 10000)
|
||||
DRM_ERROR("timed out wait for rate cntl %d\n", mst_enc->fe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct radeon_connector *master = radeon_connector->mst_port;
|
||||
struct edid *edid;
|
||||
int ret = 0;
|
||||
|
||||
edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, radeon_connector->port);
|
||||
radeon_connector->edid = edid;
|
||||
DRM_DEBUG_KMS("edid retrieved %p\n", edid);
|
||||
if (radeon_connector->edid) {
|
||||
drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
|
||||
ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
|
||||
drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
|
||||
return ret;
|
||||
}
|
||||
drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int radeon_dp_mst_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
return radeon_dp_mst_get_ddc_modes(connector);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
radeon_dp_mst_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
/* TODO - validate mode against available PBN for link */
|
||||
if (mode->clock < 10000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||
return MODE_H_ILLEGAL;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
struct drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
return &radeon_connector->mst_encoder->base;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs radeon_dp_mst_connector_helper_funcs = {
|
||||
.get_modes = radeon_dp_mst_get_modes,
|
||||
.mode_valid = radeon_dp_mst_mode_valid,
|
||||
.best_encoder = radeon_mst_best_encoder,
|
||||
};
|
||||
|
||||
static enum drm_connector_status
|
||||
radeon_dp_mst_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct radeon_connector *master = radeon_connector->mst_port;
|
||||
|
||||
return drm_dp_mst_detect_port(connector, &master->mst_mgr, radeon_connector->port);
|
||||
}
|
||||
|
||||
static void
|
||||
radeon_dp_mst_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct radeon_encoder *radeon_encoder = radeon_connector->mst_encoder;
|
||||
|
||||
drm_encoder_cleanup(&radeon_encoder->base);
|
||||
kfree(radeon_encoder);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(radeon_connector);
|
||||
}
|
||||
|
||||
static void radeon_connector_dpms(struct drm_connector *connector, int mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("\n");
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = {
|
||||
.dpms = radeon_connector_dpms,
|
||||
.detect = radeon_dp_mst_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = radeon_dp_mst_connector_destroy,
|
||||
};
|
||||
|
||||
static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_port *port,
|
||||
const char *pathprop)
|
||||
{
|
||||
struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
|
||||
struct drm_device *dev = master->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct drm_connector *connector;
|
||||
|
||||
radeon_connector = kzalloc(sizeof(*radeon_connector), GFP_KERNEL);
|
||||
if (!radeon_connector)
|
||||
return NULL;
|
||||
|
||||
radeon_connector->is_mst_connector = true;
|
||||
connector = &radeon_connector->base;
|
||||
radeon_connector->port = port;
|
||||
radeon_connector->mst_port = master;
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
drm_connector_init(dev, connector, &radeon_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort);
|
||||
drm_connector_helper_add(connector, &radeon_dp_mst_connector_helper_funcs);
|
||||
radeon_connector->mst_encoder = radeon_dp_create_fake_mst_encoder(master);
|
||||
|
||||
drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
|
||||
drm_mode_connector_set_path_property(connector, pathprop);
|
||||
drm_reinit_primary_mode_group(dev);
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
radeon_fb_add_connector(rdev, connector);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
drm_connector_register(connector);
|
||||
return connector;
|
||||
}
|
||||
|
||||
static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
|
||||
struct drm_device *dev = master->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
drm_connector_unregister(connector);
|
||||
/* need to nuke the connector */
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
/* dpms off */
|
||||
radeon_fb_remove_connector(rdev, connector);
|
||||
|
||||
drm_connector_cleanup(connector);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
drm_reinit_primary_mode_group(dev);
|
||||
|
||||
|
||||
kfree(connector);
|
||||
DRM_DEBUG_KMS("\n");
|
||||
}
|
||||
|
||||
static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
|
||||
{
|
||||
struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
|
||||
struct drm_device *dev = master->base.dev;
|
||||
|
||||
drm_kms_helper_hotplug_event(dev);
|
||||
}
|
||||
|
||||
struct drm_dp_mst_topology_cbs mst_cbs = {
|
||||
.add_connector = radeon_dp_add_mst_connector,
|
||||
.destroy_connector = radeon_dp_destroy_mst_connector,
|
||||
.hotplug = radeon_dp_mst_hotplug,
|
||||
};
|
||||
|
||||
struct radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
if (!connector->encoder)
|
||||
continue;
|
||||
if (!radeon_connector->is_mst_connector)
|
||||
continue;
|
||||
|
||||
DRM_DEBUG_KMS("checking %p vs %p\n", connector->encoder, encoder);
|
||||
if (connector->encoder == encoder)
|
||||
return radeon_connector;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(radeon_crtc->encoder);
|
||||
struct radeon_encoder_mst *mst_enc = radeon_encoder->enc_priv;
|
||||
struct radeon_connector *radeon_connector = radeon_mst_find_connector(&radeon_encoder->base);
|
||||
int dp_clock;
|
||||
struct radeon_connector_atom_dig *dig_connector = mst_enc->connector->con_priv;
|
||||
|
||||
if (radeon_connector) {
|
||||
radeon_connector->pixelclock_for_modeset = mode->clock;
|
||||
if (radeon_connector->base.display_info.bpc)
|
||||
radeon_crtc->bpc = radeon_connector->base.display_info.bpc;
|
||||
else
|
||||
radeon_crtc->bpc = 8;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("dp_clock %p %d\n", dig_connector, dig_connector->dp_clock);
|
||||
dp_clock = dig_connector->dp_clock;
|
||||
radeon_crtc->ss_enabled =
|
||||
radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss,
|
||||
ASIC_INTERNAL_SS_ON_DP,
|
||||
dp_clock);
|
||||
}
|
||||
|
||||
static void
|
||||
radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder, *primary;
|
||||
struct radeon_encoder_mst *mst_enc;
|
||||
struct radeon_encoder_atom_dig *dig_enc;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct drm_crtc *crtc;
|
||||
struct radeon_crtc *radeon_crtc;
|
||||
int ret, slots;
|
||||
|
||||
if (!ASIC_IS_DCE5(rdev)) {
|
||||
DRM_ERROR("got mst dpms on non-DCE5\n");
|
||||
return;
|
||||
}
|
||||
|
||||
radeon_connector = radeon_mst_find_connector(encoder);
|
||||
if (!radeon_connector)
|
||||
return;
|
||||
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
||||
mst_enc = radeon_encoder->enc_priv;
|
||||
|
||||
primary = mst_enc->primary;
|
||||
|
||||
dig_enc = primary->enc_priv;
|
||||
|
||||
crtc = encoder->crtc;
|
||||
DRM_DEBUG_KMS("got connector %d\n", dig_enc->active_mst_links);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
dig_enc->active_mst_links++;
|
||||
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
|
||||
if (dig_enc->active_mst_links == 1) {
|
||||
mst_enc->fe = dig_enc->dig_encoder;
|
||||
mst_enc->fe_from_be = true;
|
||||
atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe);
|
||||
|
||||
atombios_dig_encoder_setup(&primary->base, ATOM_ENCODER_CMD_SETUP, 0);
|
||||
atombios_dig_transmitter_setup2(&primary->base, ATOM_TRANSMITTER_ACTION_ENABLE,
|
||||
0, 0, dig_enc->dig_encoder);
|
||||
|
||||
if (radeon_dp_needs_link_train(mst_enc->connector) ||
|
||||
dig_enc->active_mst_links == 1) {
|
||||
radeon_dp_link_train(&primary->base, &mst_enc->connector->base);
|
||||
}
|
||||
|
||||
} else {
|
||||
mst_enc->fe = radeon_atom_pick_dig_encoder(encoder, radeon_crtc->crtc_id);
|
||||
if (mst_enc->fe == -1)
|
||||
DRM_ERROR("failed to get frontend for dig encoder\n");
|
||||
mst_enc->fe_from_be = false;
|
||||
atombios_set_mst_encoder_crtc_source(encoder, mst_enc->fe);
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder,
|
||||
dig_enc->linkb, radeon_crtc->crtc_id);
|
||||
|
||||
ret = drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr,
|
||||
radeon_connector->port,
|
||||
mst_enc->pbn, &slots);
|
||||
ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr);
|
||||
|
||||
radeon_dp_mst_set_be_cntl(primary, mst_enc,
|
||||
radeon_connector->mst_port->hpd.hpd, true);
|
||||
|
||||
mst_enc->enc_active = true;
|
||||
radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary);
|
||||
radeon_dp_mst_set_vcp_size(radeon_encoder, slots, 0);
|
||||
|
||||
atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0,
|
||||
mst_enc->fe);
|
||||
ret = drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr);
|
||||
|
||||
ret = drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr);
|
||||
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
DRM_ERROR("DPMS OFF %d\n", dig_enc->active_mst_links);
|
||||
|
||||
if (!mst_enc->enc_active)
|
||||
return;
|
||||
|
||||
drm_dp_mst_reset_vcpi_slots(&radeon_connector->mst_port->mst_mgr, mst_enc->port);
|
||||
ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr);
|
||||
|
||||
drm_dp_check_act_status(&radeon_connector->mst_port->mst_mgr);
|
||||
/* and this can also fail */
|
||||
drm_dp_update_payload_part2(&radeon_connector->mst_port->mst_mgr);
|
||||
|
||||
drm_dp_mst_deallocate_vcpi(&radeon_connector->mst_port->mst_mgr, mst_enc->port);
|
||||
|
||||
mst_enc->enc_active = false;
|
||||
radeon_dp_mst_update_stream_attribs(radeon_connector->mst_port, primary);
|
||||
|
||||
radeon_dp_mst_set_be_cntl(primary, mst_enc,
|
||||
radeon_connector->mst_port->hpd.hpd, false);
|
||||
atombios_dig_encoder_setup2(&primary->base, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0,
|
||||
mst_enc->fe);
|
||||
|
||||
if (!mst_enc->fe_from_be)
|
||||
radeon_atom_release_dig_encoder(rdev, mst_enc->fe);
|
||||
|
||||
mst_enc->fe_from_be = false;
|
||||
dig_enc->active_mst_links--;
|
||||
if (dig_enc->active_mst_links == 0) {
|
||||
/* drop link */
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool radeon_mst_mode_fixup(struct drm_encoder *encoder,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct radeon_encoder_mst *mst_enc;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
int bpp = 24;
|
||||
|
||||
mst_enc = radeon_encoder->enc_priv;
|
||||
|
||||
mst_enc->pbn = drm_dp_calc_pbn_mode(adjusted_mode->clock, bpp);
|
||||
|
||||
mst_enc->primary->active_device = mst_enc->primary->devices & mst_enc->connector->devices;
|
||||
DRM_DEBUG_KMS("setting active device to %08x from %08x %08x for encoder %d\n",
|
||||
mst_enc->primary->active_device, mst_enc->primary->devices,
|
||||
mst_enc->connector->devices, mst_enc->primary->base.encoder_type);
|
||||
|
||||
|
||||
drm_mode_set_crtcinfo(adjusted_mode, 0);
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
|
||||
dig_connector = mst_enc->connector->con_priv;
|
||||
dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd);
|
||||
dig_connector->dp_clock = radeon_dp_get_max_link_rate(&mst_enc->connector->base,
|
||||
dig_connector->dpcd);
|
||||
DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector,
|
||||
dig_connector->dp_lane_count, dig_connector->dp_clock);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void radeon_mst_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_encoder *radeon_encoder, *primary;
|
||||
struct radeon_encoder_mst *mst_enc;
|
||||
struct radeon_encoder_atom_dig *dig_enc;
|
||||
|
||||
radeon_connector = radeon_mst_find_connector(encoder);
|
||||
if (!radeon_connector) {
|
||||
DRM_DEBUG_KMS("failed to find connector %p\n", encoder);
|
||||
return;
|
||||
}
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
||||
radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
|
||||
mst_enc = radeon_encoder->enc_priv;
|
||||
|
||||
primary = mst_enc->primary;
|
||||
|
||||
dig_enc = primary->enc_priv;
|
||||
|
||||
mst_enc->port = radeon_connector->port;
|
||||
|
||||
if (dig_enc->dig_encoder == -1) {
|
||||
dig_enc->dig_encoder = radeon_atom_pick_dig_encoder(&primary->base, -1);
|
||||
primary->offset = radeon_atom_set_enc_offset(dig_enc->dig_encoder);
|
||||
atombios_set_mst_encoder_crtc_source(encoder, dig_enc->dig_encoder);
|
||||
|
||||
|
||||
}
|
||||
DRM_DEBUG_KMS("%d %d\n", dig_enc->dig_encoder, primary->offset);
|
||||
}
|
||||
|
||||
static void
|
||||
radeon_mst_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("\n");
|
||||
}
|
||||
|
||||
static void radeon_mst_encoder_commit(struct drm_encoder *encoder)
|
||||
{
|
||||
radeon_mst_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
DRM_DEBUG_KMS("\n");
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs radeon_mst_helper_funcs = {
|
||||
.dpms = radeon_mst_encoder_dpms,
|
||||
.mode_fixup = radeon_mst_mode_fixup,
|
||||
.prepare = radeon_mst_encoder_prepare,
|
||||
.mode_set = radeon_mst_encoder_mode_set,
|
||||
.commit = radeon_mst_encoder_commit,
|
||||
};
|
||||
|
||||
void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
drm_encoder_cleanup(encoder);
|
||||
kfree(encoder);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs radeon_dp_mst_enc_funcs = {
|
||||
.destroy = radeon_dp_mst_encoder_destroy,
|
||||
};
|
||||
|
||||
static struct radeon_encoder *
|
||||
radeon_dp_create_fake_mst_encoder(struct radeon_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder;
|
||||
struct radeon_encoder_mst *mst_enc;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_connector_helper_funcs *connector_funcs = connector->base.helper_private;
|
||||
struct drm_encoder *enc_master = connector_funcs->best_encoder(&connector->base);
|
||||
|
||||
DRM_DEBUG_KMS("enc master is %p\n", enc_master);
|
||||
radeon_encoder = kzalloc(sizeof(*radeon_encoder), GFP_KERNEL);
|
||||
if (!radeon_encoder)
|
||||
return NULL;
|
||||
|
||||
radeon_encoder->enc_priv = kzalloc(sizeof(*mst_enc), GFP_KERNEL);
|
||||
if (!radeon_encoder->enc_priv) {
|
||||
kfree(radeon_encoder);
|
||||
return NULL;
|
||||
}
|
||||
encoder = &radeon_encoder->base;
|
||||
switch (rdev->num_crtc) {
|
||||
case 1:
|
||||
encoder->possible_crtcs = 0x1;
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
encoder->possible_crtcs = 0x3;
|
||||
break;
|
||||
case 4:
|
||||
encoder->possible_crtcs = 0xf;
|
||||
break;
|
||||
case 6:
|
||||
encoder->possible_crtcs = 0x3f;
|
||||
break;
|
||||
}
|
||||
|
||||
drm_encoder_init(dev, &radeon_encoder->base, &radeon_dp_mst_enc_funcs,
|
||||
DRM_MODE_ENCODER_DPMST);
|
||||
drm_encoder_helper_add(encoder, &radeon_mst_helper_funcs);
|
||||
|
||||
mst_enc = radeon_encoder->enc_priv;
|
||||
mst_enc->connector = connector;
|
||||
mst_enc->primary = to_radeon_encoder(enc_master);
|
||||
radeon_encoder->is_mst_encoder = true;
|
||||
return radeon_encoder;
|
||||
}
|
||||
|
||||
int
|
||||
radeon_dp_mst_init(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct drm_device *dev = radeon_connector->base.dev;
|
||||
|
||||
if (!radeon_connector->ddc_bus->has_aux)
|
||||
return 0;
|
||||
|
||||
radeon_connector->mst_mgr.cbs = &mst_cbs;
|
||||
return drm_dp_mst_topology_mgr_init(&radeon_connector->mst_mgr, dev->dev,
|
||||
&radeon_connector->ddc_bus->aux, 16, 6,
|
||||
radeon_connector->base.base.id);
|
||||
}
|
||||
|
||||
int
|
||||
radeon_dp_mst_probe(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
int ret;
|
||||
u8 msg[1];
|
||||
|
||||
if (dig_connector->dpcd[DP_DPCD_REV] < 0x12)
|
||||
return 0;
|
||||
|
||||
ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_MSTM_CAP, msg,
|
||||
1);
|
||||
if (ret) {
|
||||
if (msg[0] & DP_MST_CAP) {
|
||||
DRM_DEBUG_KMS("Sink is MST capable\n");
|
||||
dig_connector->is_mst = true;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("Sink is not MST capable\n");
|
||||
dig_connector->is_mst = false;
|
||||
}
|
||||
|
||||
}
|
||||
drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr,
|
||||
dig_connector->is_mst);
|
||||
return dig_connector->is_mst;
|
||||
}
|
||||
|
||||
int
|
||||
radeon_dp_mst_check_status(struct radeon_connector *radeon_connector)
|
||||
{
|
||||
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
|
||||
int retry;
|
||||
|
||||
if (dig_connector->is_mst) {
|
||||
u8 esi[16] = { 0 };
|
||||
int dret;
|
||||
int ret = 0;
|
||||
bool handled;
|
||||
|
||||
dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux,
|
||||
DP_SINK_COUNT_ESI, esi, 8);
|
||||
go_again:
|
||||
if (dret == 8) {
|
||||
DRM_DEBUG_KMS("got esi %02x %02x %02x\n", esi[0], esi[1], esi[2]);
|
||||
ret = drm_dp_mst_hpd_irq(&radeon_connector->mst_mgr, esi, &handled);
|
||||
|
||||
if (handled) {
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
int wret;
|
||||
wret = drm_dp_dpcd_write(&radeon_connector->ddc_bus->aux,
|
||||
DP_SINK_COUNT_ESI + 1, &esi[1], 3);
|
||||
if (wret == 3)
|
||||
break;
|
||||
}
|
||||
|
||||
dret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux,
|
||||
DP_SINK_COUNT_ESI, esi, 8);
|
||||
if (dret == 8) {
|
||||
DRM_DEBUG_KMS("got esi2 %02x %02x %02x\n", esi[0], esi[1], esi[2]);
|
||||
goto go_again;
|
||||
}
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("failed to get ESI - device may have failed %d\n", ret);
|
||||
dig_connector->is_mst = false;
|
||||
drm_dp_mst_topology_mgr_set_mst(&radeon_connector->mst_mgr,
|
||||
dig_connector->is_mst);
|
||||
/* send a hotplug event */
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
static int radeon_debugfs_mst_info(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *dig_connector;
|
||||
int i;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
|
||||
continue;
|
||||
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
if (radeon_connector->is_mst_connector)
|
||||
continue;
|
||||
if (!dig_connector->is_mst)
|
||||
continue;
|
||||
drm_dp_mst_dump_topology(m, &radeon_connector->mst_mgr);
|
||||
|
||||
for (i = 0; i < radeon_connector->enabled_attribs; i++)
|
||||
seq_printf(m, "attrib %d: %d %d\n", i,
|
||||
radeon_connector->cur_stream_attribs[i].fe,
|
||||
radeon_connector->cur_stream_attribs[i].slots);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_info_list radeon_debugfs_mst_list[] = {
|
||||
{"radeon_mst_info", &radeon_debugfs_mst_info, 0, NULL},
|
||||
};
|
||||
#endif
|
||||
|
||||
int radeon_mst_debugfs_init(struct radeon_device *rdev)
|
||||
{
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
return radeon_debugfs_add_files(rdev, radeon_debugfs_mst_list, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
@ -190,6 +190,8 @@ int radeon_deep_color = 0;
|
||||
int radeon_use_pflipirq = 2;
|
||||
int radeon_bapm = -1;
|
||||
int radeon_backlight = -1;
|
||||
int radeon_auxch = -1;
|
||||
int radeon_mst = 0;
|
||||
|
||||
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
|
||||
module_param_named(no_wb, radeon_no_wb, int, 0444);
|
||||
@ -239,7 +241,7 @@ module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
|
||||
MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
|
||||
module_param_named(msi, radeon_msi, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (defaul 10000 = 10 seconds, 0 = disable)");
|
||||
MODULE_PARM_DESC(lockup_timeout, "GPU lockup timeout in ms (default 10000 = 10 seconds, 0 = disable)");
|
||||
module_param_named(lockup_timeout, radeon_lockup_timeout, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(fastfb, "Direct FB access for IGP chips (0 = disable, 1 = enable)");
|
||||
@ -275,6 +277,12 @@ module_param_named(bapm, radeon_bapm, int, 0444);
|
||||
MODULE_PARM_DESC(backlight, "backlight support (1 = enable, 0 = disable, -1 = auto)");
|
||||
module_param_named(backlight, radeon_backlight, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(auxch, "Use native auxch experimental support (1 = enable, 0 = disable, -1 = auto)");
|
||||
module_param_named(auxch, radeon_auxch, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)");
|
||||
module_param_named(mst, radeon_mst, int, 0444);
|
||||
|
||||
static struct pci_device_id pciidlist[] = {
|
||||
radeon_PCI_IDS
|
||||
};
|
||||
|
@ -247,7 +247,16 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
if (radeon_encoder->active_device & radeon_connector->devices)
|
||||
if (radeon_encoder->is_mst_encoder) {
|
||||
struct radeon_encoder_mst *mst_enc;
|
||||
|
||||
if (!radeon_connector->is_mst_connector)
|
||||
continue;
|
||||
|
||||
mst_enc = radeon_encoder->enc_priv;
|
||||
if (mst_enc->connector == radeon_connector->mst_port)
|
||||
return connector;
|
||||
} else if (radeon_encoder->active_device & radeon_connector->devices)
|
||||
return connector;
|
||||
}
|
||||
return NULL;
|
||||
@ -393,6 +402,9 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
case DRM_MODE_CONNECTOR_DisplayPort:
|
||||
if (radeon_connector->is_mst_connector)
|
||||
return false;
|
||||
|
||||
dig_connector = radeon_connector->con_priv;
|
||||
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
|
||||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
|
||||
|
@ -257,6 +257,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
|
||||
}
|
||||
|
||||
info->par = rfbdev;
|
||||
info->skip_vt_switch = true;
|
||||
|
||||
ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
|
||||
if (ret) {
|
||||
@ -434,3 +435,13 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector)
|
||||
{
|
||||
drm_fb_helper_add_one_connector(&rdev->mode_info.rfbdev->helper, connector);
|
||||
}
|
||||
|
||||
void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector)
|
||||
{
|
||||
drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector);
|
||||
}
|
||||
|
@ -87,6 +87,20 @@ static void radeon_hotplug_work_func(struct work_struct *work)
|
||||
drm_helper_hpd_irq_event(dev);
|
||||
}
|
||||
|
||||
static void radeon_dp_work_func(struct work_struct *work)
|
||||
{
|
||||
struct radeon_device *rdev = container_of(work, struct radeon_device,
|
||||
dp_work);
|
||||
struct drm_device *dev = rdev->ddev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
|
||||
/* this should take a mutex */
|
||||
if (mode_config->num_connector) {
|
||||
list_for_each_entry(connector, &mode_config->connector_list, head)
|
||||
radeon_connector_hotplug(connector);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* radeon_driver_irq_preinstall_kms - drm irq preinstall callback
|
||||
*
|
||||
@ -276,6 +290,7 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
|
||||
}
|
||||
|
||||
INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func);
|
||||
INIT_WORK(&rdev->dp_work, radeon_dp_work_func);
|
||||
INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi);
|
||||
|
||||
rdev->irq.installed = true;
|
||||
|
@ -547,6 +547,35 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
|
||||
else
|
||||
*value = 1;
|
||||
break;
|
||||
case RADEON_INFO_CURRENT_GPU_TEMP:
|
||||
/* get temperature in millidegrees C */
|
||||
if (rdev->asic->pm.get_temperature)
|
||||
*value = radeon_get_temperature(rdev);
|
||||
else
|
||||
*value = 0;
|
||||
break;
|
||||
case RADEON_INFO_CURRENT_GPU_SCLK:
|
||||
/* get sclk in Mhz */
|
||||
if (rdev->pm.dpm_enabled)
|
||||
*value = radeon_dpm_get_current_sclk(rdev) / 100;
|
||||
else
|
||||
*value = rdev->pm.current_sclk / 100;
|
||||
break;
|
||||
case RADEON_INFO_CURRENT_GPU_MCLK:
|
||||
/* get mclk in Mhz */
|
||||
if (rdev->pm.dpm_enabled)
|
||||
*value = radeon_dpm_get_current_mclk(rdev) / 100;
|
||||
else
|
||||
*value = rdev->pm.current_mclk / 100;
|
||||
break;
|
||||
case RADEON_INFO_READ_REG:
|
||||
if (copy_from_user(value, value_ptr, sizeof(uint32_t))) {
|
||||
DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (radeon_get_allowed_info_register(rdev, *value, value))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("Invalid request %d\n", info->request);
|
||||
return -EINVAL;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -85,6 +86,13 @@ enum radeon_hpd_id {
|
||||
RADEON_HPD_NONE = 0xff,
|
||||
};
|
||||
|
||||
enum radeon_output_csc {
|
||||
RADEON_OUTPUT_CSC_BYPASS = 0,
|
||||
RADEON_OUTPUT_CSC_TVRGB = 1,
|
||||
RADEON_OUTPUT_CSC_YCBCR601 = 2,
|
||||
RADEON_OUTPUT_CSC_YCBCR709 = 3,
|
||||
};
|
||||
|
||||
#define RADEON_MAX_I2C_BUS 16
|
||||
|
||||
/* radeon gpio-based i2c
|
||||
@ -255,6 +263,8 @@ struct radeon_mode_info {
|
||||
struct drm_property *audio_property;
|
||||
/* FMT dithering */
|
||||
struct drm_property *dither_property;
|
||||
/* Output CSC */
|
||||
struct drm_property *output_csc_property;
|
||||
/* hardcoded DFP edid from BIOS */
|
||||
struct edid *bios_hardcoded_edid;
|
||||
int bios_hardcoded_edid_size;
|
||||
@ -265,6 +275,9 @@ struct radeon_mode_info {
|
||||
u16 firmware_flags;
|
||||
/* pointer to backlight encoder */
|
||||
struct radeon_encoder *bl_encoder;
|
||||
|
||||
/* bitmask for active encoder frontends */
|
||||
uint32_t active_encoders;
|
||||
};
|
||||
|
||||
#define RADEON_MAX_BL_LEVEL 0xFF
|
||||
@ -357,6 +370,7 @@ struct radeon_crtc {
|
||||
u32 wm_low;
|
||||
u32 wm_high;
|
||||
struct drm_display_mode hw_mode;
|
||||
enum radeon_output_csc output_csc;
|
||||
};
|
||||
|
||||
struct radeon_encoder_primary_dac {
|
||||
@ -426,12 +440,24 @@ struct radeon_encoder_atom_dig {
|
||||
uint8_t backlight_level;
|
||||
int panel_mode;
|
||||
struct radeon_afmt *afmt;
|
||||
int active_mst_links;
|
||||
};
|
||||
|
||||
struct radeon_encoder_atom_dac {
|
||||
enum radeon_tv_std tv_std;
|
||||
};
|
||||
|
||||
struct radeon_encoder_mst {
|
||||
int crtc;
|
||||
struct radeon_encoder *primary;
|
||||
struct radeon_connector *connector;
|
||||
struct drm_dp_mst_port *port;
|
||||
int pbn;
|
||||
int fe;
|
||||
bool fe_from_be;
|
||||
bool enc_active;
|
||||
};
|
||||
|
||||
struct radeon_encoder {
|
||||
struct drm_encoder base;
|
||||
uint32_t encoder_enum;
|
||||
@ -450,6 +476,11 @@ struct radeon_encoder {
|
||||
bool is_ext_encoder;
|
||||
u16 caps;
|
||||
struct radeon_audio_funcs *audio;
|
||||
enum radeon_output_csc output_csc;
|
||||
bool can_mst;
|
||||
uint32_t offset;
|
||||
bool is_mst_encoder;
|
||||
/* front end for this mst encoder */
|
||||
};
|
||||
|
||||
struct radeon_connector_atom_dig {
|
||||
@ -460,6 +491,7 @@ struct radeon_connector_atom_dig {
|
||||
int dp_clock;
|
||||
int dp_lane_count;
|
||||
bool edp_on;
|
||||
bool is_mst;
|
||||
};
|
||||
|
||||
struct radeon_gpio_rec {
|
||||
@ -503,6 +535,11 @@ enum radeon_connector_dither {
|
||||
RADEON_FMT_DITHER_ENABLE = 1,
|
||||
};
|
||||
|
||||
struct stream_attribs {
|
||||
uint16_t fe;
|
||||
uint16_t slots;
|
||||
};
|
||||
|
||||
struct radeon_connector {
|
||||
struct drm_connector base;
|
||||
uint32_t connector_id;
|
||||
@ -524,6 +561,14 @@ struct radeon_connector {
|
||||
enum radeon_connector_audio audio;
|
||||
enum radeon_connector_dither dither;
|
||||
int pixelclock_for_modeset;
|
||||
bool is_mst_connector;
|
||||
struct radeon_connector *mst_port;
|
||||
struct drm_dp_mst_port *port;
|
||||
struct drm_dp_mst_topology_mgr mst_mgr;
|
||||
|
||||
struct radeon_encoder *mst_encoder;
|
||||
struct stream_attribs cur_stream_attribs[6];
|
||||
int enabled_attribs;
|
||||
};
|
||||
|
||||
struct radeon_framebuffer {
|
||||
@ -708,15 +753,26 @@ extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
|
||||
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
|
||||
extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector);
|
||||
int radeon_dp_get_max_link_rate(struct drm_connector *connector,
|
||||
u8 *dpcd);
|
||||
extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
|
||||
u8 power_state);
|
||||
extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
|
||||
extern ssize_t
|
||||
radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg);
|
||||
|
||||
extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
|
||||
extern void atombios_dig_encoder_setup2(struct drm_encoder *encoder, int action, int panel_mode, int enc_override);
|
||||
extern void radeon_atom_encoder_init(struct radeon_device *rdev);
|
||||
extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev);
|
||||
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
|
||||
int action, uint8_t lane_num,
|
||||
uint8_t lane_set);
|
||||
extern void atombios_dig_transmitter_setup2(struct drm_encoder *encoder,
|
||||
int action, uint8_t lane_num,
|
||||
uint8_t lane_set, int fe);
|
||||
extern void atombios_set_mst_encoder_crtc_source(struct drm_encoder *encoder,
|
||||
int fe);
|
||||
extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
|
||||
extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
|
||||
void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
|
||||
@ -929,7 +985,23 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
|
||||
void radeon_fb_output_poll_changed(struct radeon_device *rdev);
|
||||
|
||||
void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id);
|
||||
|
||||
void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector);
|
||||
void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector);
|
||||
|
||||
void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
|
||||
|
||||
int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
|
||||
|
||||
/* mst */
|
||||
int radeon_dp_mst_init(struct radeon_connector *radeon_connector);
|
||||
int radeon_dp_mst_probe(struct radeon_connector *radeon_connector);
|
||||
int radeon_dp_mst_check_status(struct radeon_connector *radeon_connector);
|
||||
int radeon_mst_debugfs_init(struct radeon_device *rdev);
|
||||
void radeon_dp_mst_prepare_pll(struct drm_crtc *crtc, struct drm_display_mode *mode);
|
||||
|
||||
void radeon_setup_mst_connector(struct drm_device *dev);
|
||||
|
||||
int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx);
|
||||
void radeon_atom_release_dig_encoder(struct radeon_device *rdev, int enc_idx);
|
||||
#endif
|
||||
|
@ -1001,6 +1001,28 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||
ps->sclk_high, ps->max_voltage);
|
||||
}
|
||||
|
||||
/* get the current sclk in 10 khz units */
|
||||
u32 rs780_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
u32 current_fb_div = RREG32(FVTHROT_STATUS_REG0) & CURRENT_FEEDBACK_DIV_MASK;
|
||||
u32 func_cntl = RREG32(CG_SPLL_FUNC_CNTL);
|
||||
u32 ref_div = ((func_cntl & SPLL_REF_DIV_MASK) >> SPLL_REF_DIV_SHIFT) + 1;
|
||||
u32 post_div = ((func_cntl & SPLL_SW_HILEN_MASK) >> SPLL_SW_HILEN_SHIFT) + 1 +
|
||||
((func_cntl & SPLL_SW_LOLEN_MASK) >> SPLL_SW_LOLEN_SHIFT) + 1;
|
||||
u32 sclk = (rdev->clock.spll.reference_freq * current_fb_div) /
|
||||
(post_div * ref_div);
|
||||
|
||||
return sclk;
|
||||
}
|
||||
|
||||
/* get the current mclk in 10 khz units */
|
||||
u32 rs780_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct igp_power_info *pi = rs780_get_pi(rdev);
|
||||
|
||||
return pi->bootup_uma_clk;
|
||||
}
|
||||
|
||||
int rs780_dpm_force_performance_level(struct radeon_device *rdev,
|
||||
enum radeon_dpm_forced_level level)
|
||||
{
|
||||
|
@ -2050,6 +2050,52 @@ void rv6xx_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||
}
|
||||
}
|
||||
|
||||
/* get the current sclk in 10 khz units */
|
||||
u32 rv6xx_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ps *rps = rdev->pm.dpm.current_ps;
|
||||
struct rv6xx_ps *ps = rv6xx_get_ps(rps);
|
||||
struct rv6xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
|
||||
CURRENT_PROFILE_INDEX_SHIFT;
|
||||
|
||||
if (current_index > 2) {
|
||||
return 0;
|
||||
} else {
|
||||
if (current_index == 0)
|
||||
pl = &ps->low;
|
||||
else if (current_index == 1)
|
||||
pl = &ps->medium;
|
||||
else /* current_index == 2 */
|
||||
pl = &ps->high;
|
||||
return pl->sclk;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the current mclk in 10 khz units */
|
||||
u32 rv6xx_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ps *rps = rdev->pm.dpm.current_ps;
|
||||
struct rv6xx_ps *ps = rv6xx_get_ps(rps);
|
||||
struct rv6xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
|
||||
CURRENT_PROFILE_INDEX_SHIFT;
|
||||
|
||||
if (current_index > 2) {
|
||||
return 0;
|
||||
} else {
|
||||
if (current_index == 0)
|
||||
pl = &ps->low;
|
||||
else if (current_index == 1)
|
||||
pl = &ps->medium;
|
||||
else /* current_index == 2 */
|
||||
pl = &ps->high;
|
||||
return pl->mclk;
|
||||
}
|
||||
}
|
||||
|
||||
void rv6xx_dpm_fini(struct radeon_device *rdev)
|
||||
{
|
||||
int i;
|
||||
|
@ -2492,6 +2492,50 @@ void rv770_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
|
||||
}
|
||||
}
|
||||
|
||||
u32 rv770_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ps *rps = rdev->pm.dpm.current_ps;
|
||||
struct rv7xx_ps *ps = rv770_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
|
||||
CURRENT_PROFILE_INDEX_SHIFT;
|
||||
|
||||
if (current_index > 2) {
|
||||
return 0;
|
||||
} else {
|
||||
if (current_index == 0)
|
||||
pl = &ps->low;
|
||||
else if (current_index == 1)
|
||||
pl = &ps->medium;
|
||||
else /* current_index == 2 */
|
||||
pl = &ps->high;
|
||||
return pl->sclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 rv770_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ps *rps = rdev->pm.dpm.current_ps;
|
||||
struct rv7xx_ps *ps = rv770_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
|
||||
CURRENT_PROFILE_INDEX_SHIFT;
|
||||
|
||||
if (current_index > 2) {
|
||||
return 0;
|
||||
} else {
|
||||
if (current_index == 0)
|
||||
pl = &ps->low;
|
||||
else if (current_index == 1)
|
||||
pl = &ps->medium;
|
||||
else /* current_index == 2 */
|
||||
pl = &ps->high;
|
||||
return pl->mclk;
|
||||
}
|
||||
}
|
||||
|
||||
void rv770_dpm_fini(struct radeon_device *rdev)
|
||||
{
|
||||
int i;
|
||||
|
@ -1264,6 +1264,36 @@ static void si_init_golden_registers(struct radeon_device *rdev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* si_get_allowed_info_register - fetch the register for the info ioctl
|
||||
*
|
||||
* @rdev: radeon_device pointer
|
||||
* @reg: register offset in bytes
|
||||
* @val: register value
|
||||
*
|
||||
* Returns 0 for success or -EINVAL for an invalid register
|
||||
*
|
||||
*/
|
||||
int si_get_allowed_info_register(struct radeon_device *rdev,
|
||||
u32 reg, u32 *val)
|
||||
{
|
||||
switch (reg) {
|
||||
case GRBM_STATUS:
|
||||
case GRBM_STATUS2:
|
||||
case GRBM_STATUS_SE0:
|
||||
case GRBM_STATUS_SE1:
|
||||
case SRBM_STATUS:
|
||||
case SRBM_STATUS2:
|
||||
case (DMA_STATUS_REG + DMA0_REGISTER_OFFSET):
|
||||
case (DMA_STATUS_REG + DMA1_REGISTER_OFFSET):
|
||||
case UVD_STATUS:
|
||||
*val = RREG32(reg);
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#define PCIE_BUS_CLK 10000
|
||||
#define TCLK (PCIE_BUS_CLK / 10)
|
||||
|
||||
@ -6055,12 +6085,12 @@ int si_irq_set(struct radeon_device *rdev)
|
||||
(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
|
||||
|
||||
if (!ASIC_IS_NODCE(rdev)) {
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN;
|
||||
hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
|
||||
}
|
||||
|
||||
dma_cntl = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
|
||||
@ -6123,27 +6153,27 @@ int si_irq_set(struct radeon_device *rdev)
|
||||
}
|
||||
if (rdev->irq.hpd[0]) {
|
||||
DRM_DEBUG("si_irq_set: hpd 1\n");
|
||||
hpd1 |= DC_HPDx_INT_EN;
|
||||
hpd1 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[1]) {
|
||||
DRM_DEBUG("si_irq_set: hpd 2\n");
|
||||
hpd2 |= DC_HPDx_INT_EN;
|
||||
hpd2 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[2]) {
|
||||
DRM_DEBUG("si_irq_set: hpd 3\n");
|
||||
hpd3 |= DC_HPDx_INT_EN;
|
||||
hpd3 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[3]) {
|
||||
DRM_DEBUG("si_irq_set: hpd 4\n");
|
||||
hpd4 |= DC_HPDx_INT_EN;
|
||||
hpd4 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[4]) {
|
||||
DRM_DEBUG("si_irq_set: hpd 5\n");
|
||||
hpd5 |= DC_HPDx_INT_EN;
|
||||
hpd5 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
if (rdev->irq.hpd[5]) {
|
||||
DRM_DEBUG("si_irq_set: hpd 6\n");
|
||||
hpd6 |= DC_HPDx_INT_EN;
|
||||
hpd6 |= DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN;
|
||||
}
|
||||
|
||||
WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
|
||||
@ -6306,6 +6336,37 @@ static inline void si_irq_ack(struct radeon_device *rdev)
|
||||
tmp |= DC_HPDx_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD1_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD1_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD2_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD2_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD3_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD3_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD4_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD4_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD5_INT_CONTROL, tmp);
|
||||
}
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
tmp = RREG32(DC_HPD5_INT_CONTROL);
|
||||
tmp |= DC_HPDx_RX_INT_ACK;
|
||||
WREG32(DC_HPD6_INT_CONTROL, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void si_irq_disable(struct radeon_device *rdev)
|
||||
@ -6371,6 +6432,7 @@ int si_irq_process(struct radeon_device *rdev)
|
||||
u32 src_id, src_data, ring_id;
|
||||
u32 ring_index;
|
||||
bool queue_hotplug = false;
|
||||
bool queue_dp = false;
|
||||
bool queue_thermal = false;
|
||||
u32 status, addr;
|
||||
|
||||
@ -6611,6 +6673,48 @@ restart_ih:
|
||||
DRM_DEBUG("IH: HPD6\n");
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 1\n");
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 2\n");
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 3\n");
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 4\n");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 5\n");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
|
||||
rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT;
|
||||
queue_dp = true;
|
||||
DRM_DEBUG("IH: HPD_RX 6\n");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data);
|
||||
break;
|
||||
@ -6693,6 +6797,8 @@ restart_ih:
|
||||
rptr &= rdev->ih.ptr_mask;
|
||||
WREG32(IH_RB_RPTR, rptr);
|
||||
}
|
||||
if (queue_dp)
|
||||
schedule_work(&rdev->dp_work);
|
||||
if (queue_hotplug)
|
||||
schedule_work(&rdev->hotplug_work);
|
||||
if (queue_thermal && rdev->pm.dpm_enabled)
|
||||
|
@ -6993,3 +6993,39 @@ void si_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
|
||||
current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
|
||||
}
|
||||
}
|
||||
|
||||
u32 si_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
|
||||
struct radeon_ps *rps = &eg_pi->current_rps;
|
||||
struct ni_ps *ps = ni_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
|
||||
CURRENT_STATE_INDEX_SHIFT;
|
||||
|
||||
if (current_index >= ps->performance_level_count) {
|
||||
return 0;
|
||||
} else {
|
||||
pl = &ps->performance_levels[current_index];
|
||||
return pl->sclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 si_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
|
||||
struct radeon_ps *rps = &eg_pi->current_rps;
|
||||
struct ni_ps *ps = ni_get_ps(rps);
|
||||
struct rv7xx_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
|
||||
CURRENT_STATE_INDEX_SHIFT;
|
||||
|
||||
if (current_index >= ps->performance_level_count) {
|
||||
return 0;
|
||||
} else {
|
||||
pl = &ps->performance_levels[current_index];
|
||||
return pl->mclk;
|
||||
}
|
||||
}
|
||||
|
@ -1556,6 +1556,7 @@
|
||||
#define UVD_UDEC_DBW_ADDR_CONFIG 0xEF54
|
||||
#define UVD_RBC_RB_RPTR 0xF690
|
||||
#define UVD_RBC_RB_WPTR 0xF694
|
||||
#define UVD_STATUS 0xf6bc
|
||||
|
||||
#define UVD_CGC_CTRL 0xF4B0
|
||||
# define DCM (1 << 0)
|
||||
|
@ -1837,6 +1837,34 @@ void sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev
|
||||
}
|
||||
}
|
||||
|
||||
u32 sumo_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct sumo_power_info *pi = sumo_get_pi(rdev);
|
||||
struct radeon_ps *rps = &pi->current_rps;
|
||||
struct sumo_ps *ps = sumo_get_ps(rps);
|
||||
struct sumo_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) >>
|
||||
CURR_INDEX_SHIFT;
|
||||
|
||||
if (current_index == BOOST_DPM_LEVEL) {
|
||||
pl = &pi->boost_pl;
|
||||
return pl->sclk;
|
||||
} else if (current_index >= ps->num_levels) {
|
||||
return 0;
|
||||
} else {
|
||||
pl = &ps->levels[current_index];
|
||||
return pl->sclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 sumo_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct sumo_power_info *pi = sumo_get_pi(rdev);
|
||||
|
||||
return pi->sys_info.bootup_uma_clk;
|
||||
}
|
||||
|
||||
void sumo_dpm_fini(struct radeon_device *rdev)
|
||||
{
|
||||
int i;
|
||||
|
@ -1964,6 +1964,31 @@ void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *r
|
||||
}
|
||||
}
|
||||
|
||||
u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct trinity_power_info *pi = trinity_get_pi(rdev);
|
||||
struct radeon_ps *rps = &pi->current_rps;
|
||||
struct trinity_ps *ps = trinity_get_ps(rps);
|
||||
struct trinity_pl *pl;
|
||||
u32 current_index =
|
||||
(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
|
||||
CURRENT_STATE_SHIFT;
|
||||
|
||||
if (current_index >= ps->num_levels) {
|
||||
return 0;
|
||||
} else {
|
||||
pl = &ps->levels[current_index];
|
||||
return pl->sclk;
|
||||
}
|
||||
}
|
||||
|
||||
u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev)
|
||||
{
|
||||
struct trinity_power_info *pi = trinity_get_pi(rdev);
|
||||
|
||||
return pi->sys_info.bootup_uma_clk;
|
||||
}
|
||||
|
||||
void trinity_dpm_fini(struct radeon_device *rdev)
|
||||
{
|
||||
int i;
|
||||
|
@ -486,6 +486,8 @@ int drm_dp_calc_pbn_mode(int clock, int bpp);
|
||||
|
||||
bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots);
|
||||
|
||||
int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
|
||||
|
||||
|
||||
void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
|
||||
|
||||
|
@ -1034,6 +1034,10 @@ struct drm_radeon_cs {
|
||||
#define RADEON_INFO_VRAM_USAGE 0x1e
|
||||
#define RADEON_INFO_GTT_USAGE 0x1f
|
||||
#define RADEON_INFO_ACTIVE_CU_COUNT 0x20
|
||||
#define RADEON_INFO_CURRENT_GPU_TEMP 0x21
|
||||
#define RADEON_INFO_CURRENT_GPU_SCLK 0x22
|
||||
#define RADEON_INFO_CURRENT_GPU_MCLK 0x23
|
||||
#define RADEON_INFO_READ_REG 0x24
|
||||
|
||||
struct drm_radeon_info {
|
||||
uint32_t request;
|
||||
|
Loading…
x
Reference in New Issue
Block a user