diff options
author | Dave Airlie <airlied@redhat.com> | 2016-04-13 16:57:25 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-04-13 16:57:25 +1000 |
commit | 691edd918f9c1c07ebe2598fbe920a296a7d21fc (patch) | |
tree | f5af08fa707400291f7a64ce40c14f7c3e33e588 | |
parent | 741e73f5c7d4eefc3d0f7e2e858f504930a188d6 (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.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/atombios_crtc.c | 111 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 44 |
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; } |