diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 61 | 
1 files changed, 37 insertions, 24 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index c6fcb5b86a4..2817101fb16 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,7 +258,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)  		radeon_crtc->enabled = true;  		/* adjust pm to dpms changes BEFORE enabling crtcs */  		radeon_pm_compute_clocks(rdev); -		/* disable crtc pair power gating before programming */  		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)  			atombios_powergate_crtc(crtc, ATOM_DISABLE);  		atombios_enable_crtc(crtc, ATOM_ENABLE); @@ -278,25 +277,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)  			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);  		atombios_enable_crtc(crtc, ATOM_DISABLE);  		radeon_crtc->enabled = false; -		/* power gating is per-pair */ -		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) { -			struct drm_crtc *other_crtc; -			struct radeon_crtc *other_radeon_crtc; -			list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { -				other_radeon_crtc = to_radeon_crtc(other_crtc); -				if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || -				    ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || -				    ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || -				    ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || -				    ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || -				    ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { -					/* if both crtcs in the pair are off, enable power gating */ -					if (other_radeon_crtc->enabled == false) -						atombios_powergate_crtc(crtc, ATOM_ENABLE); -					break; -				} -			} -		} +		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) +			atombios_powergate_crtc(crtc, ATOM_ENABLE);  		/* adjust pm to dpms changes AFTER disabling crtcs */  		radeon_pm_compute_clocks(rdev);  		break; @@ -444,11 +426,28 @@ union atom_enable_ss {  static void atombios_crtc_program_ss(struct radeon_device *rdev,  				     int enable,  				     int pll_id, +				     int crtc_id,  				     struct radeon_atom_ss *ss)  { +	unsigned i;  	int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);  	union atom_enable_ss args; +	if (!enable) { +		for (i = 0; i < rdev->num_crtc; i++) { +			if (rdev->mode_info.crtcs[i] && +			    rdev->mode_info.crtcs[i]->enabled && +			    i != crtc_id && +			    pll_id == rdev->mode_info.crtcs[i]->pll_id) { +				/* one other crtc is using this pll don't turn +				 * off spread spectrum as it might turn off +				 * display on active crtc +				 */ +				return; +			} +		} +	} +  	memset(&args, 0, sizeof(args));  	if (ASIC_IS_DCE5(rdev)) { @@ -1028,7 +1027,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode  		radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,  					  &ref_div, &post_div); -	atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); +	atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);  	atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,  				  encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1051,7 +1050,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode  			ss.step = step_size;  		} -		atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); +		atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);  	}  } @@ -1572,11 +1571,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev)  								   ASIC_INTERNAL_SS_ON_DCPLL,  								   rdev->clock.default_dispclk);  		if (ss_enabled) -			atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); +			atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss);  		/* XXX: DCE5, make sure voltage, dispclk is high enough */  		atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk);  		if (ss_enabled) -			atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); +			atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss);  	}  } @@ -1665,9 +1664,22 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)  	struct drm_device *dev = crtc->dev;  	struct radeon_device *rdev = dev->dev_private;  	struct radeon_atom_ss ss; +	int i;  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); +	for (i = 0; i < rdev->num_crtc; i++) { +		if (rdev->mode_info.crtcs[i] && +		    rdev->mode_info.crtcs[i]->enabled && +		    i != radeon_crtc->crtc_id && +		    radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { +			/* one other crtc is using this pll don't turn +			 * off the pll +			 */ +			goto done; +		} +	} +  	switch (radeon_crtc->pll_id) {  	case ATOM_PPLL1:  	case ATOM_PPLL2: @@ -1684,6 +1696,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)  	default:  		break;  	} +done:  	radeon_crtc->pll_id = -1;  }  |