Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 6103 → Rev 6104

/drivers/video/drm/radeon/atombios_encoders.c
27,6 → 27,7
#include <drm/drm_crtc_helper.h>
#include <drm/radeon_drm.h>
#include "radeon.h"
#include "radeon_audio.h"
#include "atom.h"
#include <linux/backlight.h>
 
236,6 → 237,7
backlight_update_status(bd);
 
DRM_INFO("radeon atom DIG backlight initialized\n");
rdev->mode_info.bl_encoder = radeon_encoder;
 
return;
 
309,7 → 311,7
adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
 
/* get the native mode for scaling */
if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT|ATOM_DEVICE_DFP_SUPPORT)) {
if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
radeon_panel_mode_fixup(encoder, adjusted_mode);
} else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
664,11 → 666,21
int
atombios_get_encoder_mode(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_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;
728,6 → 740,10
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)) {
if (radeon_audio != 0 &&
drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
return ATOM_ENCODER_MODE_DP_AUDIO;
return ATOM_ENCODER_MODE_DP;
} else if (radeon_audio != 0) {
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
742,6 → 758,10
}
break;
case DRM_MODE_CONNECTOR_eDP:
if (radeon_audio != 0 &&
drm_detect_monitor_audio(radeon_connector_edid(connector)) &&
ASIC_IS_DCE4(rdev) && !ASIC_IS_DCE5(rdev))
return ATOM_ENCODER_MODE_DP_AUDIO;
return ATOM_ENCODER_MODE_DP;
case DRM_MODE_CONNECTOR_DVIA:
case DRM_MODE_CONNECTOR_VGA:
812,7 → 832,7
};
 
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;
909,6 → 929,9
 
if (ENCODER_MODE_IS_DP(args.v3.ucEncoderMode) && (dp_clock == 270000))
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
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;
937,6 → 960,10
else
args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ;
}
 
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)
958,6 → 985,12
 
}
 
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;
967,7 → 1000,7
};
 
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;
1317,7 → 1350,7
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:
1333,6 → 1366,12
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)
{
1586,9 → 1625,15
} else
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
if (rdev->mode_info.bl_encoder) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
} else {
args.ucAction = ATOM_LCD_BLON;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
}
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
1667,9 → 1712,13
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
}
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
if (rdev->mode_info.bl_encoder)
atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
else
atombios_dig_transmitter_setup(encoder,
ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
}
if (ext_encoder)
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
break;
1676,6 → 1725,11
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);
1718,10 → 1772,17
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int encoder_mode = atombios_get_encoder_mode(encoder);
 
DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
radeon_encoder->encoder_id, mode, radeon_encoder->devices,
radeon_encoder->active_device);
 
if ((radeon_audio != 0) &&
((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
ENCODER_MODE_IS_DP(encoder_mode)))
radeon_audio_dpms(encoder, mode);
 
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1935,6 → 1996,53
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)
1983,8 → 2091,15
}
}
 
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;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
1992,32 → 2107,38
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)) {
2024,39 → 2145,41
/* 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 */
2084,7 → 2207,18
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 */
void
2123,6 → 2257,8
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
int encoder_mode;
 
radeon_encoder->pixel_clock = adjusted_mode->clock;
 
2171,13 → 2307,12
 
atombios_apply_encoder_quirks(encoder, adjusted_mode);
 
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
if (rdev->asic->display.hdmi_enable)
radeon_hdmi_enable(rdev, encoder, true);
if (rdev->asic->display.hdmi_setmode)
radeon_hdmi_setmode(rdev, encoder, adjusted_mode);
encoder_mode = atombios_get_encoder_mode(encoder);
if (connector && (radeon_audio != 0) &&
((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
ENCODER_MODE_IS_DP(encoder_mode)))
radeon_audio_mode_set(encoder, adjusted_mode);
}
}
 
static bool
atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
2340,7 → 2475,9
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];
2446,9 → 2583,13
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;
}