summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-04-13 16:57:25 +1000
committerDave Airlie <airlied@redhat.com>2016-04-13 16:57:25 +1000
commit691edd918f9c1c07ebe2598fbe920a296a7d21fc (patch)
treef5af08fa707400291f7a64ce40c14f7c3e33e588
parent741e73f5c7d4eefc3d0f7e2e858f504930a188d6 (diff)
WIP: start using the bios parser instead of amdgpu codedrm-amdgpu-dal-wip-bios-parser-separate
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_crtc.c111
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_encoders.c44
4 files changed, 153 insertions, 24 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index d3e3e8e4bd62..4634842f150d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -57,7 +57,7 @@
#include "amd_powerplay.h"
#include "gpu_scheduler.h"
-
+#include "dc_bios_types.h"
/*
* Modules parameters.
*/
@@ -1949,6 +1949,8 @@ struct amdgpu_device {
bool is_atom_bios;
struct amdgpu_bo *stollen_vga_memory;
uint32_t bios_scratch[AMDGPU_BIOS_NUM_SCRATCH];
+ struct dc_bios *dcb;
+ struct cgs_device *bios_cgs;
/* Register/doorbell mmio */
resource_size_t rmmio_base;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 5c7c67e9aae3..78cab9b1ebb0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -39,6 +39,8 @@
#include "atom.h"
#include "amdgpu_atombios.h"
#include "amd_pcie.h"
+
+#include "bios_parser_interface.h"
#ifdef CONFIG_DRM_AMDGPU_CIK
#include "cik.h"
#endif
@@ -841,6 +843,9 @@ static void amdgpu_atombios_fini(struct amdgpu_device *adev)
adev->mode_info.atom_context = NULL;
kfree(adev->mode_info.atom_card_info);
adev->mode_info.atom_card_info = NULL;
+
+ dal_bios_parser_destroy(&adev->dcb);
+ amdgpu_cgs_destroy_device(adev->bios_cgs);
}
/**
@@ -888,6 +893,19 @@ static int amdgpu_atombios_init(struct amdgpu_device *adev)
mutex_init(&adev->mode_info.atom_context->mutex);
amdgpu_atombios_scratch_regs_init(adev);
amdgpu_atom_allocate_fb_scratch(adev->mode_info.atom_context);
+
+ adev->bios_cgs = amdgpu_cgs_create_device(adev);
+ if (!adev->bios_cgs) {
+ amdgpu_atombios_fini(adev);
+ return -ENOMEM;
+ }
+
+ {
+ struct bp_init_data bp_init;
+ bp_init.cgs = adev->bios_cgs;
+ bp_init.bios = adev->bios;
+ adev->dcb = dal_bios_parser_create(&bp_init, DCE_VERSION_8_0);
+ }
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
index 3d06743a1ab6..3f58c8f12695 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
@@ -302,6 +302,115 @@ union adjust_pixel_clock {
ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
};
+static enum signal_type encoder_mode_to_signal_type(int encoder_mode, bool is_duallink)
+{
+ switch (encoder_mode) {
+ case ATOM_ENCODER_MODE_DVI:
+ return (is_duallink ? SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK);
+ case ATOM_ENCODER_MODE_HDMI:
+ return SIGNAL_TYPE_HDMI_TYPE_A;
+ case ATOM_ENCODER_MODE_LVDS:
+ return SIGNAL_TYPE_LVDS;
+ case ATOM_ENCODER_MODE_DP:
+ return SIGNAL_TYPE_DISPLAY_PORT;
+ case ATOM_ENCODER_MODE_CRT:
+ default:
+ return SIGNAL_TYPE_RGB;
+ }
+}
+
+#if 1
+static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc,
+ struct drm_display_mode *mode)
+{
+ struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ struct amdgpu_device *adev = dev->dev_private;
+ struct drm_encoder *encoder = amdgpu_crtc->encoder;
+ struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
+ struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder);
+ int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(encoder);
+ struct bp_adjust_pixel_clock_parameters args = {0};
+ u32 clock = mode->clock;
+ u32 dp_clock = mode->clock;
+ int bpc = amdgpu_crtc->bpc;
+ bool is_duallink = amdgpu_dig_monitor_is_duallink(encoder, mode->clock);
+ u32 adjusted_clock = mode->clock;
+
+ args.signal_type = encoder_mode_to_signal_type(encoder_mode, is_duallink);
+
+ amdgpu_crtc->pll_flags = AMDGPU_PLL_USE_FRAC_FB_DIV;
+
+ if ((amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
+ (amdgpu_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_ID_UNKNOWN)) {
+ if (connector) {
+ struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+ struct amdgpu_connector_atom_dig *dig_connector =
+ amdgpu_connector->con_priv;
+
+ dp_clock = dig_connector->dp_clock;
+ }
+ }
+
+ /* use recommended ref_div for ss */
+ if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+ if (amdgpu_crtc->ss_enabled) {
+ if (amdgpu_crtc->ss.refdiv) {
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_REF_DIV;
+ amdgpu_crtc->pll_reference_div = amdgpu_crtc->ss.refdiv;
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_FRAC_FB_DIV;
+ }
+ }
+
+ }
+ if (amdgpu_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_PREFER_CLOSEST_LOWER;
+ if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_IS_LCD;
+ /* adjust pll for deep color modes */
+ if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
+ switch (bpc) {
+ case 8:
+ default:
+ break;
+ case 10:
+ clock = (clock * 5) / 4;
+ break;
+ case 12:
+ clock = (clock * 3) / 2;
+ break;
+ case 16:
+ clock = clock * 2;
+ break;
+ }
+ }
+ if (amdgpu_crtc->ss_enabled && amdgpu_crtc->ss.percentage)
+ args.ss_enable = true;
+
+ if (ENCODER_MODE_IS_DP(encoder_mode))
+ args.pixel_clock = dp_clock;
+ else
+ args.pixel_clock = clock;
+
+ args.encoder_object_id = amdgpu_encoder->encoder_object_id;
+
+ dc_bios_adjust_pixel_clock(adev->dcb, &args);
+
+ adjusted_clock = args.adjusted_pixel_clock;
+
+ if (args.reference_divider) {
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_FRAC_FB_DIV;
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_REF_DIV;
+ amdgpu_crtc->pll_reference_div = args.reference_divider;
+ }
+ if (args.pixel_clock_post_divider) {
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_FRAC_FB_DIV;
+ amdgpu_crtc->pll_flags |= AMDGPU_PLL_USE_POST_DIV;
+ amdgpu_crtc->pll_post_div = args.pixel_clock_post_divider;
+ }
+ return adjusted_clock;
+}
+#else
static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc,
struct drm_display_mode *mode)
{
@@ -451,7 +560,7 @@ static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc,
return adjusted_clock;
}
-
+#endif
union set_pixel_clock {
SET_PIXEL_CLOCK_PS_ALLOCATION base;
PIXEL_CLOCK_PARAMETERS v1;
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
index 4b367c4ce6b8..e03279cdf56e 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -101,12 +101,12 @@ amdgpu_atombios_encoder_set_backlight_level(struct amdgpu_encoder *amdgpu_encode
case ENCODER_ID_INTERNAL_UNIPHY2:
if (dig->backlight_level == 0)
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
- ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+ TRANSMITTER_CONTROL_BACKLIGHT_OFF, 0, 0);
else {
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
- ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL, 0, 0);
+ TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS, 0, 0);
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
- ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+ TRANSMITTER_CONTROL_BACKLIGHT_ON, 0, 0);
}
break;
default:
@@ -700,7 +700,7 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a
int dig_encoder = dig->dig_encoder;
int hpd_id = AMDGPU_HPD_NONE;
- if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+ if (action == TRANSMITTER_CONTROL_INIT) {
connector = amdgpu_get_connector_for_encoder_init(encoder);
/* just needed to avoid bailing in the encoder check. the encoder
* isn't used for init
@@ -754,9 +754,9 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a
switch (crev) {
case 1:
args.v1.ucAction = action;
- if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+ if (action == TRANSMITTER_CONTROL_INIT) {
args.v1.usInitInfo = cpu_to_le16(connector_object_id);
- } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+ } else if (action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) {
args.v1.asMode.ucLaneSel = lane_num;
args.v1.asMode.ucLaneSet = lane_set;
} else {
@@ -811,9 +811,9 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a
break;
case 2:
args.v2.ucAction = action;
- if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+ if (action == TRANSMITTER_CONTROL_INIT) {
args.v2.usInitInfo = cpu_to_le16(connector_object_id);
- } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+ } else if (action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) {
args.v2.asMode.ucLaneSel = lane_num;
args.v2.asMode.ucLaneSet = lane_set;
} else {
@@ -853,9 +853,9 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a
break;
case 3:
args.v3.ucAction = action;
- if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+ if (action == TRANSMITTER_CONTROL_INIT) {
args.v3.usInitInfo = cpu_to_le16(connector_object_id);
- } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+ } else if (action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) {
args.v3.asMode.ucLaneSel = lane_num;
args.v3.asMode.ucLaneSet = lane_set;
} else {
@@ -912,9 +912,9 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a
break;
case 4:
args.v4.ucAction = action;
- if (action == ATOM_TRANSMITTER_ACTION_INIT) {
+ if (action == TRANSMITTER_CONTROL_INIT) {
args.v4.usInitInfo = cpu_to_le16(connector_object_id);
- } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) {
+ } else if (action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS) {
args.v4.asMode.ucLaneSel = lane_num;
args.v4.asMode.ucLaneSet = lane_set;
} else {
@@ -1066,7 +1066,7 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a
else
args.v6.ucLaneNum = 4;
args.v6.ucConnObjId = connector_object_id;
- if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH)
+ if (action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
args.v6.ucDPLaneSet = lane_set;
else
args.v6.ucDigMode = amdgpu_atombios_encoder_get_encoder_mode(encoder);
@@ -1104,8 +1104,8 @@ amdgpu_atombios_encoder_set_edp_panel_power(struct drm_connector *connector,
if (connector->connector_type != DRM_MODE_CONNECTOR_eDP)
goto done;
- if ((action != ATOM_TRANSMITTER_ACTION_POWER_ON) &&
- (action != ATOM_TRANSMITTER_ACTION_POWER_OFF))
+ if ((action != TRANSMITTER_CONTROL_POWER_ON) &&
+ (action != TRANSMITTER_CONTROL_POWER_OFF))
goto done;
if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev))
@@ -1118,7 +1118,7 @@ amdgpu_atombios_encoder_set_edp_panel_power(struct drm_connector *connector,
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
/* wait for the panel to power up */
- if (action == ATOM_TRANSMITTER_ACTION_POWER_ON) {
+ if (action == TRANSMITTER_CONTROL_POWER_ON) {
int i;
for (i = 0; i < 300; i++) {
@@ -1276,13 +1276,13 @@ amdgpu_atombios_encoder_setup_dig(struct drm_encoder *encoder, int action)
connector) {
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
amdgpu_atombios_encoder_set_edp_panel_power(connector,
- ATOM_TRANSMITTER_ACTION_POWER_ON);
+ TRANSMITTER_CONTROL_POWER_ON);
amdgpu_dig_connector->edp_on = true;
}
}
/* enable the transmitter */
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
- ATOM_TRANSMITTER_ACTION_ENABLE,
+ TRANSMITTER_CONTROL_ENABLE,
0, 0);
if (ENCODER_MODE_IS_DP(amdgpu_atombios_encoder_get_encoder_mode(encoder)) &&
connector) {
@@ -1303,19 +1303,19 @@ amdgpu_atombios_encoder_setup_dig(struct drm_encoder *encoder, int action)
amdgpu_atombios_encoder_setup_external_encoder(encoder, ext_encoder, ATOM_DISABLE);
if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
- ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+ TRANSMITTER_CONTROL_BACKLIGHT_OFF, 0, 0);
if (ENCODER_MODE_IS_DP(amdgpu_atombios_encoder_get_encoder_mode(encoder)) &&
connector)
amdgpu_atombios_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
/* disable the transmitter */
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
- ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+ TRANSMITTER_CONTROL_DISABLE, 0, 0);
if (ENCODER_MODE_IS_DP(amdgpu_atombios_encoder_get_encoder_mode(encoder)) &&
connector) {
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
amdgpu_atombios_encoder_set_edp_panel_power(connector,
- ATOM_TRANSMITTER_ACTION_POWER_OFF);
+ TRANSMITTER_CONTROL_POWER_OFF);
amdgpu_dig_connector->edp_on = false;
}
}
@@ -1584,7 +1584,7 @@ amdgpu_atombios_encoder_init_dig(struct amdgpu_device *adev)
case ENCODER_ID_INTERNAL_UNIPHY1:
case ENCODER_ID_INTERNAL_UNIPHY2:
case ENCODER_ID_INTERNAL_UNIPHY3:
- amdgpu_atombios_encoder_setup_dig_transmitter(encoder, ATOM_TRANSMITTER_ACTION_INIT,
+ amdgpu_atombios_encoder_setup_dig_transmitter(encoder, TRANSMITTER_CONTROL_INIT,
0, 0);
break;
}