aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-10-03 10:32:58 +1000
committerDave Airlie <airlied@redhat.com>2012-10-03 10:32:58 +1000
commit8ff1f792dd68ad46f3cfe01e01a375b402cf08da (patch)
treeb73b4fa71c5a9357931360d7894beee247cd464e
parent2216c9e74fb3baac3cb73952158dbe38b703997e (diff)
parent82ffd92b162ece87c863c075d993c65333e8e78b (diff)
Merge branch 'drm-next-3.7' of git://people.freedesktop.org/~agd5f/linux into drm-next
Alex writes: "The big changes for 3.7 include: - Asynchronous VM page table updates for Cayman/SI - 2 level VM page table support. Saves memory compared to 1 level page tables. - Reworked PLL handing in the display code allows lots more combinations of monitors to work, including more than two DP displays assuming compatible clocks across shared PLLs. This also allows us to power down extra PLLs when we can share a single one across multiple displays which saves power. - Native backlight control on ATOMBIOS systems. - Improved ACPI support for interacting with the GPU. Fixes backlight control on some laptops. - Document AMD ACPI interfaces - Lots of code cleanup - Bug fixes" * 'drm-next-3.7' of git://people.freedesktop.org/~agd5f/linux: (79 commits) drm/radeon: add vm set_page() callback for SI drm/radeon: rework the vm_flush interface drm/radeon: use WRITE_DATA packets for vm flush on SI drm/radeon/pm: fix multi-head profile handling on BTC+ (v2) drm/radeon: fix radeon power state debug output drm/radeon: force MSIs on RS690 asics drm/radeon: Add MSI quirk for gateway RS690 drm/radeon: allow MIP_ADDRESS=0 for MSAA textures on Evergreen drm/radeon/kms: allow STRMOUT_BASE_UPDATE on RS780 and RS880 drm/radeon: add 2-level VM pagetables support v9 drm/radeon: refactor set_page chipset interface v5 drm/radeon: Fix scratch register leak in IB test. drm/radeon: restore backlight level on resume drm/radeon: add get_backlight_level callback drm/radeon: only adjust default clocks on NI GPUs drm/radeon: validate PPLL in crtc fixup drm/radeon: work around KMS modeset limitations in PLL allocation (v2) drm/radeon: make non-DP PPLL sharing more robust drm/radeon: store the encoder in the radeon_crtc drm/radeon: rework crtc pll setup to better support PPLL sharing ...
-rw-r--r--drivers/acpi/video.c8
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c663
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c367
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c282
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c61
-rw-r--r--drivers/gpu/drm/radeon/evergreen_reg.h2
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h7
-rw-r--r--drivers/gpu/drm/radeon/ni.c134
-rw-r--r--drivers/gpu/drm/radeon/nid.h1
-rw-r--r--drivers/gpu/drm/radeon/r100.c96
-rw-r--r--drivers/gpu/drm/radeon/r300.c4
-rw-r--r--drivers/gpu/drm/radeon/r520.c4
-rw-r--r--drivers/gpu/drm/radeon/r600.c37
-rw-r--r--drivers/gpu/drm/radeon/r600_blit.c115
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_kms.c52
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_shaders.h1
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c5
-rw-r--r--drivers/gpu/drm/radeon/r600_hdmi.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon.h192
-rw-r--r--drivers/gpu/drm/radeon/radeon_acpi.c607
-rw-r--r--drivers/gpu/drm/radeon/radeon_acpi.h445
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.c93
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h28
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c15
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c411
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c43
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c83
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c11
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c19
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_fence.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_gart.c602
-rw-r--r--drivers/gpu/drm/radeon/radeon_gem.c54
-rw-r--r--drivers/gpu/drm/radeon/radeon_ioc32.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c43
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c17
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_encoders.c65
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h49
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c22
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c104
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c30
-rw-r--r--drivers/gpu/drm/radeon/radeon_sa.c20
-rw-r--r--drivers/gpu/drm/radeon/radeon_test.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c2
-rw-r--r--drivers/gpu/drm/radeon/rs400.c6
-rw-r--r--drivers/gpu/drm/radeon/rs600.c49
-rw-r--r--drivers/gpu/drm/radeon/rs690.c6
-rw-r--r--drivers/gpu/drm/radeon/rv515.c18
-rw-r--r--drivers/gpu/drm/radeon/rv770.c10
-rw-r--r--drivers/gpu/drm/radeon/si.c113
-rw-r--r--drivers/gpu/drm/radeon/sid.h15
55 files changed, 3549 insertions, 1510 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 1e0a9e17c31..f94d4c818fc 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1448,8 +1448,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch,
* most likely via hotkey. */
acpi_bus_generate_proc_event(device, event, 0);
- if (!acpi_notifier_call_chain(device, event, 0))
- keycode = KEY_SWITCHVIDEOMODE;
+ keycode = KEY_SWITCHVIDEOMODE;
break;
case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
@@ -1479,8 +1478,9 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
break;
}
- if (event != ACPI_VIDEO_NOTIFY_SWITCH)
- acpi_notifier_call_chain(device, event, 0);
+ if (acpi_notifier_call_chain(device, event, 0))
+ /* Something vetoed the keypress. */
+ keycode = 0;
if (keycode) {
input_report_key(input, keycode, 1);
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 2817101fb16..96184d02c8d 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -83,25 +83,19 @@ static void atombios_scaler_setup(struct drm_crtc *crtc)
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
ENABLE_SCALER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
-
+ struct radeon_encoder *radeon_encoder =
+ to_radeon_encoder(radeon_crtc->encoder);
/* fixme - fill in enc_priv for atom dac */
enum radeon_tv_std tv_std = TV_STD_NTSC;
bool is_tv = false, is_cv = false;
- struct drm_encoder *encoder;
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
return;
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- /* find tv std */
- if (encoder->crtc == crtc) {
- struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
- struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
- tv_std = tv_dac->tv_std;
- is_tv = true;
- }
- }
+ if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
+ struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
+ tv_std = tv_dac->tv_std;
+ is_tv = true;
}
memset(&args, 0, sizeof(args));
@@ -533,99 +527,87 @@ union adjust_pixel_clock {
};
static u32 atombios_adjust_pll(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct radeon_pll *pll,
- bool ss_enabled,
- struct radeon_atom_ss *ss)
+ 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 drm_encoder *encoder = NULL;
- struct radeon_encoder *radeon_encoder = NULL;
- struct drm_connector *connector = NULL;
+ struct drm_encoder *encoder = radeon_crtc->encoder;
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
u32 adjusted_clock = mode->clock;
- int encoder_mode = 0;
+ int encoder_mode = atombios_get_encoder_mode(encoder);
u32 dp_clock = mode->clock;
- int bpc = 8;
- bool is_duallink = false;
+ int bpc = radeon_get_monitor_bpc(connector);
+ bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
/* reset the pll flags */
- pll->flags = 0;
+ radeon_crtc->pll_flags = 0;
if (ASIC_IS_AVIVO(rdev)) {
if ((rdev->family == CHIP_RS600) ||
(rdev->family == CHIP_RS690) ||
(rdev->family == CHIP_RS740))
- pll->flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/
- RADEON_PLL_PREFER_CLOSEST_LOWER);
+ radeon_crtc->pll_flags |= (/*RADEON_PLL_USE_FRAC_FB_DIV |*/
+ RADEON_PLL_PREFER_CLOSEST_LOWER);
if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */
- pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+ radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
else
- pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+ radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
if (rdev->family < CHIP_RV770)
- pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
+ radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
/* use frac fb div on APUs */
if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
- pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
} else {
- pll->flags |= RADEON_PLL_LEGACY;
+ radeon_crtc->pll_flags |= RADEON_PLL_LEGACY;
if (mode->clock > 200000) /* range limits??? */
- pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
+ radeon_crtc->pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
else
- pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+ radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
}
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- radeon_encoder = to_radeon_encoder(encoder);
- connector = radeon_get_connector_for_encoder(encoder);
- bpc = radeon_get_monitor_bpc(connector);
- encoder_mode = atombios_get_encoder_mode(encoder);
- is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
- if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
- (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
- if (connector) {
- struct radeon_connector *radeon_connector = to_radeon_connector(connector);
- struct radeon_connector_atom_dig *dig_connector =
- radeon_connector->con_priv;
-
- dp_clock = dig_connector->dp_clock;
- }
- }
+ if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
+ (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
+ if (connector) {
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+ struct radeon_connector_atom_dig *dig_connector =
+ radeon_connector->con_priv;
- /* use recommended ref_div for ss */
- if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
- if (ss_enabled) {
- if (ss->refdiv) {
- pll->flags |= RADEON_PLL_USE_REF_DIV;
- pll->reference_div = ss->refdiv;
- if (ASIC_IS_AVIVO(rdev))
- pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
- }
- }
- }
+ dp_clock = dig_connector->dp_clock;
+ }
+ }
- if (ASIC_IS_AVIVO(rdev)) {
- /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
- if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
- adjusted_clock = mode->clock * 2;
- if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
- pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
- if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
- pll->flags |= RADEON_PLL_IS_LCD;
- } else {
- if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
- pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
- if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
- pll->flags |= RADEON_PLL_USE_REF_DIV;
+ /* use recommended ref_div for ss */
+ if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+ if (radeon_crtc->ss_enabled) {
+ if (radeon_crtc->ss.refdiv) {
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
+ radeon_crtc->pll_reference_div = radeon_crtc->ss.refdiv;
+ if (ASIC_IS_AVIVO(rdev))
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
}
- break;
}
}
+ if (ASIC_IS_AVIVO(rdev)) {
+ /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
+ if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
+ adjusted_clock = mode->clock * 2;
+ if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+ radeon_crtc->pll_flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
+ if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+ radeon_crtc->pll_flags |= RADEON_PLL_IS_LCD;
+ } else {
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
+ radeon_crtc->pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
+ if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
+ }
+
/* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
* accordingly based on the encoder/transmitter to work around
* special hw requirements.
@@ -650,7 +632,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
args.v1.ucTransmitterID = radeon_encoder->encoder_id;
args.v1.ucEncodeMode = encoder_mode;
- if (ss_enabled && ss->percentage)
+ if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage)
args.v1.ucConfig |=
ADJUST_DISPLAY_CONFIG_SS_ENABLE;
@@ -663,7 +645,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
args.v3.sInput.ucEncodeMode = encoder_mode;
args.v3.sInput.ucDispPllConfig = 0;
- if (ss_enabled && ss->percentage)
+ if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage)
args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_SS_ENABLE;
if (ENCODER_MODE_IS_DP(encoder_mode)) {
@@ -695,14 +677,14 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
index, (uint32_t *)&args);
adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
if (args.v3.sOutput.ucRefDiv) {
- pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
- pll->flags |= RADEON_PLL_USE_REF_DIV;
- pll->reference_div = args.v3.sOutput.ucRefDiv;
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
+ radeon_crtc->pll_reference_div = args.v3.sOutput.ucRefDiv;
}
if (args.v3.sOutput.ucPostDiv) {
- pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
- pll->flags |= RADEON_PLL_USE_POST_DIV;
- pll->post_div = args.v3.sOutput.ucPostDiv;
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
+ radeon_crtc->pll_flags |= RADEON_PLL_USE_POST_DIV;
+ radeon_crtc->pll_post_div = args.v3.sOutput.ucPostDiv;
}
break;
default:
@@ -837,7 +819,10 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
args.v3.ucFracFbDiv = frac_fb_div;
args.v3.ucPostDiv = post_div;
args.v3.ucPpll = pll_id;
- args.v3.ucMiscInfo = (pll_id << 2);
+ if (crtc_id == ATOM_CRTC2)
+ args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
+ else
+ args.v3.ucMiscInfo = PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1;
if (ss_enabled && (ss->type & ATOM_EXTERNAL_SS_MASK))
args.v3.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
args.v3.ucTransmitterId = encoder_id;
@@ -907,58 +892,29 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
-static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+static bool atombios_crtc_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 drm_encoder *encoder = NULL;
- struct radeon_encoder *radeon_encoder = NULL;
- u32 pll_clock = mode->clock;
- u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
- struct radeon_pll *pll;
- u32 adjusted_clock;
- int encoder_mode = 0;
- struct radeon_atom_ss ss;
- bool ss_enabled = false;
- int bpc = 8;
+ struct radeon_encoder *radeon_encoder =
+ to_radeon_encoder(radeon_crtc->encoder);
+ int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);
- list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- if (encoder->crtc == crtc) {
- radeon_encoder = to_radeon_encoder(encoder);
- encoder_mode = atombios_get_encoder_mode(encoder);
- break;
- }
- }
-
- if (!radeon_encoder)
- return;
-
- switch (radeon_crtc->pll_id) {
- case ATOM_PPLL1:
- pll = &rdev->clock.p1pll;
- break;
- case ATOM_PPLL2:
- pll = &rdev->clock.p2pll;
- break;
- case ATOM_DCPLL:
- case ATOM_PPLL_INVALID:
- default:
- pll = &rdev->clock.dcpll;
- break;
- }
+ radeon_crtc->bpc = 8;
+ radeon_crtc->ss_enabled = false;
if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
- (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
+ (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 =
- radeon_get_connector_for_encoder(encoder);
+ radeon_get_connector_for_encoder(radeon_crtc->encoder);
struct radeon_connector *radeon_connector =
to_radeon_connector(connector);
struct radeon_connector_atom_dig *dig_connector =
radeon_connector->con_priv;
int dp_clock;
- bpc = radeon_get_monitor_bpc(connector);
+ radeon_crtc->bpc = radeon_get_monitor_bpc(connector);
switch (encoder_mode) {
case ATOM_ENCODER_MODE_DP_MST:
@@ -966,45 +922,54 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
/* DP/eDP */
dp_clock = dig_connector->dp_clock / 10;
if (ASIC_IS_DCE4(rdev))
- ss_enabled =
- radeon_atombios_get_asic_ss_info(rdev, &ss,
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_asic_ss_info(rdev, &radeon_crtc->ss,
ASIC_INTERNAL_SS_ON_DP,
dp_clock);
else {
if (dp_clock == 16200) {
- ss_enabled =
- radeon_atombios_get_ppll_ss_info(rdev, &ss,
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_ppll_ss_info(rdev,
+ &radeon_crtc->ss,
ATOM_DP_SS_ID2);
- if (!ss_enabled)
- ss_enabled =
- radeon_atombios_get_ppll_ss_info(rdev, &ss,
+ if (!radeon_crtc->ss_enabled)
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_ppll_ss_info(rdev,
+ &radeon_crtc->ss,
ATOM_DP_SS_ID1);
} else
- ss_enabled =
- radeon_atombios_get_ppll_ss_info(rdev, &ss,
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_ppll_ss_info(rdev,
+ &radeon_crtc->ss,
ATOM_DP_SS_ID1);
}
break;
case ATOM_ENCODER_MODE_LVDS:
if (ASIC_IS_DCE4(rdev))
- ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
- dig->lcd_ss_id,
- mode->clock / 10);
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_asic_ss_info(rdev,
+ &radeon_crtc->ss,
+ dig->lcd_ss_id,
+ mode->clock / 10);
else
- ss_enabled = radeon_atombios_get_ppll_ss_info(rdev, &ss,
- dig->lcd_ss_id);
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_ppll_ss_info(rdev,
+ &radeon_crtc->ss,
+ dig->lcd_ss_id);
break;
case ATOM_ENCODER_MODE_DVI:
if (ASIC_IS_DCE4(rdev))
- ss_enabled =
- radeon_atombios_get_asic_ss_info(rdev, &ss,
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_asic_ss_info(rdev,
+ &radeon_crtc->ss,
ASIC_INTERNAL_SS_ON_TMDS,
mode->clock / 10);
break;
case ATOM_ENCODER_MODE_HDMI:
if (ASIC_IS_DCE4(rdev))
- ss_enabled =
- radeon_atombios_get_asic_ss_info(rdev, &ss,
+ radeon_crtc->ss_enabled =
+ radeon_atombios_get_asic_ss_info(rdev,
+ &radeon_crtc->ss,
ASIC_INTERNAL_SS_ON_HDMI,
mode->clock / 10);
break;
@@ -1014,43 +979,80 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
}
/* adjust pixel clock as needed */
- adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss);
+ radeon_crtc->adjusted_clock = atombios_adjust_pll(crtc, mode);
+
+ return true;
+}
+
+static void atombios_crtc_set_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);
+ u32 pll_clock = mode->clock;
+ u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
+ struct radeon_pll *pll;
+ int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);
+
+ switch (radeon_crtc->pll_id) {
+ case ATOM_PPLL1:
+ pll = &rdev->clock.p1pll;
+ break;
+ case ATOM_PPLL2:
+ pll = &rdev->clock.p2pll;
+ break;
+ case ATOM_DCPLL:
+ case ATOM_PPLL_INVALID:
+ default:
+ pll = &rdev->clock.dcpll;
+ break;
+ }
+
+ /* update pll params */
+ pll->flags = radeon_crtc->pll_flags;
+ pll->reference_div = radeon_crtc->pll_reference_div;
+ pll->post_div = radeon_crtc->pll_post_div;
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
/* TV seems to prefer the legacy algo on some boards */
- radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
- &ref_div, &post_div);
+ radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock,
+ &fb_div, &frac_fb_div, &ref_div, &post_div);
else if (ASIC_IS_AVIVO(rdev))
- radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
- &ref_div, &post_div);
+ radeon_compute_pll_avivo(pll, radeon_crtc->adjusted_clock, &pll_clock,
+ &fb_div, &frac_fb_div, &ref_div, &post_div);
else
- radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
- &ref_div, &post_div);
+ radeon_compute_pll_legacy(pll, radeon_crtc->adjusted_clock, &pll_clock,
+ &fb_div, &frac_fb_div, &ref_div, &post_div);
- atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);
+ atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id,
+ radeon_crtc->crtc_id, &radeon_crtc->ss);
atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
encoder_mode, radeon_encoder->encoder_id, mode->clock,
- ref_div, fb_div, frac_fb_div, post_div, bpc, ss_enabled, &ss);
+ ref_div, fb_div, frac_fb_div, post_div,
+ radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss);
- if (ss_enabled) {
+ if (radeon_crtc->ss_enabled) {
/* calculate ss amount and step size */
if (ASIC_IS_DCE4(rdev)) {
u32 step_size;
- u32 amount = (((fb_div * 10) + frac_fb_div) * ss.percentage) / 10000;
- ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
- ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
+ u32 amount = (((fb_div * 10) + frac_fb_div) * radeon_crtc->ss.percentage) / 10000;
+ radeon_crtc->ss.amount = (amount / 10) & ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK;
+ radeon_crtc->ss.amount |= ((amount - (amount / 10)) << ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK;
- if (ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
- step_size = (4 * amount * ref_div * (ss.rate * 2048)) /
+ if (radeon_crtc->ss.type & ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD)
+ step_size = (4 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
(125 * 25 * pll->reference_freq / 100);
else
- step_size = (2 * amount * ref_div * (ss.rate * 2048)) /
+ step_size = (2 * amount * ref_div * (radeon_crtc->ss.rate * 2048)) /
(125 * 25 * pll->reference_freq / 100);
- ss.step = step_size;
+ radeon_crtc->ss.step = step_size;
}
- atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);
+ atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id,
+ radeon_crtc->crtc_id, &radeon_crtc->ss);
}
}
@@ -1479,85 +1481,251 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)
}
}
+/**
+ * radeon_get_pll_use_mask - look up a mask of which pplls are in use
+ *
+ * @crtc: drm crtc
+ *
+ * Returns the mask of which PPLLs (Pixel PLLs) are in use.
+ */
+static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc *test_crtc;
+ struct radeon_crtc *test_radeon_crtc;
+ u32 pll_in_use = 0;
+
+ list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc == test_crtc)
+ continue;
+
+ test_radeon_crtc = to_radeon_crtc(test_crtc);
+ if (test_radeon_crtc->pll_id != ATOM_PPLL_INVALID)
+ pll_in_use |= (1 << test_radeon_crtc->pll_id);
+ }
+ return pll_in_use;
+}
+
+/**
+ * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP
+ *
+ * @crtc: drm crtc
+ *
+ * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is
+ * also in DP mode. For DP, a single PPLL can be used for all DP
+ * crtcs/encoders.
+ */
+static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc *test_crtc;
+ struct radeon_crtc *test_radeon_crtc;
+
+ list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+ if (crtc == test_crtc)
+ continue;
+ test_radeon_crtc = to_radeon_crtc(test_crtc);
+ if (test_radeon_crtc->encoder &&
+ ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_radeon_crtc->encoder))) {
+ /* for DP use the same PLL for all */
+ if (t