diff options
| -rw-r--r-- | linux-core/radeon_combios.c | 192 | ||||
| -rw-r--r-- | linux-core/radeon_legacy_crtc.c | 172 | ||||
| -rw-r--r-- | linux-core/radeon_legacy_encoders.c | 33 | ||||
| -rw-r--r-- | linux-core/radeon_mode.h | 36 | ||||
| -rw-r--r-- | linux-core/radeon_reg.h | 9 | 
5 files changed, 348 insertions, 94 deletions
| diff --git a/linux-core/radeon_combios.c b/linux-core/radeon_combios.c index 1080079f..bb8d0b27 100644 --- a/linux-core/radeon_combios.c +++ b/linux-core/radeon_combios.c @@ -428,7 +428,7 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)  	struct radeon_mode_info *mode_info = &dev_priv->mode_info;  	uint16_t pll_info;  	struct radeon_pll *pll = &mode_info->pll; -	int rev; +	int8_t rev;  	pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);  	if (pll_info) { @@ -450,17 +450,153 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)  		pll->xclk = radeon_bios16(dev_priv, pll_info + 0x08);  		// sclk/mclk use fixed point +		//sclk = radeon_bios16(pll_info + 8) / 100.0; +		//mclk = radeon_bios16(pll_info + 10) / 100.0; +		//if (sclk == 0) sclk = 200; +		//if (mclk == 0) mclk = 200;  		return true;  	}  	return false;  } +bool radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder) +{ +	struct drm_device *dev = encoder->base.dev; +	struct drm_radeon_private *dev_priv = dev->dev_private; +	uint16_t dac_info; +	uint8_t rev, bg, dac; + +	/* first check TV table */ +	dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); +	if (dac_info) { +		rev = radeon_bios8(dev_priv, dac_info + 0x3); +		if (rev > 4) { +			bg = radeon_bios8(dev_priv, dac_info + 0xc) & 0xf; +			dac = radeon_bios8(dev_priv, dac_info + 0xd) & 0xf; +			encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); + +			bg = radeon_bios8(dev_priv, dac_info + 0xe) & 0xf; +			dac = radeon_bios8(dev_priv, dac_info + 0xf) & 0xf; +			encoder->pal_tvdac_adj = (bg << 16) | (dac << 20); + +			bg = radeon_bios8(dev_priv, dac_info + 0x10) & 0xf; +			dac = radeon_bios8(dev_priv, dac_info + 0x11) & 0xf; +			encoder->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + +			return true; +		} else if (rev > 1) { +			bg = radeon_bios8(dev_priv, dac_info + 0xc) & 0xf; +			dac = (radeon_bios8(dev_priv, dac_info + 0xc) >> 4) & 0xf; +			encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); + +			bg = radeon_bios8(dev_priv, dac_info + 0xd) & 0xf; +			dac = (radeon_bios8(dev_priv, dac_info + 0xd) >> 4) & 0xf; +			encoder->pal_tvdac_adj = (bg << 16) | (dac << 20); + +			bg = radeon_bios8(dev_priv, dac_info + 0xe) & 0xf; +			dac = (radeon_bios8(dev_priv, dac_info + 0xe) >> 4) & 0xf; +			encoder->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + +			return true; +		} +	} + +	/* then check CRT table */ +	dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); +	if (dac_info) { +		rev = radeon_bios8(dev_priv, dac_info) & 0x3; +		if (rev < 2) { +			bg = radeon_bios8(dev_priv, dac_info + 0x3) & 0xf; +			dac = (radeon_bios8(dev_priv, dac_info + 0x3) >> 4) & 0xf; +			encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); +			encoder->pal_tvdac_adj = encoder->ps2_tvdac_adj; +			encoder->ntsc_tvdac_adj = encoder->ps2_tvdac_adj; + +			return true; +		} else { +			bg = radeon_bios8(dev_priv, dac_info + 0x4) & 0xf; +			dac = radeon_bios8(dev_priv, dac_info + 0x5) & 0xf; +			encoder->ps2_tvdac_adj = (bg << 16) | (dac << 20); +			encoder->pal_tvdac_adj = encoder->ps2_tvdac_adj; +			encoder->ntsc_tvdac_adj = encoder->ps2_tvdac_adj; + +			return true; +		} + +	} + +	return false; +} + +bool radeon_combios_get_tv_info(struct radeon_encoder *encoder) +{ +	struct drm_device *dev = encoder->base.dev; +	struct drm_radeon_private *dev_priv = dev->dev_private; +	uint16_t tv_info; + +	tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); +	if (tv_info) { +		if (radeon_bios8(dev_priv, tv_info + 6) == 'T') { +			switch (radeon_bios8(dev_priv, tv_info + 7) & 0xf) { +			case 1: +				encoder->tv_std = TV_STD_NTSC; +				DRM_INFO("Default TV standard: NTSC\n"); +				break; +			case 2: +				encoder->tv_std = TV_STD_PAL; +				DRM_INFO("Default TV standard: PAL\n"); +				break; +			case 3: +				encoder->tv_std = TV_STD_PAL_M; +				DRM_INFO("Default TV standard: PAL-M\n"); +				break; +			case 4: +				encoder->tv_std = TV_STD_PAL_60; +				DRM_INFO("Default TV standard: PAL-60\n"); +				break; +			case 5: +				encoder->tv_std = TV_STD_NTSC_J; +				DRM_INFO("Default TV standard: NTSC-J\n"); +				break; +			case 6: +				encoder->tv_std = TV_STD_SCART_PAL; +				DRM_INFO("Default TV standard: SCART-PAL\n"); +				break; +			default: +				encoder->tv_std = TV_STD_NTSC; +				DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); +				break; +			} + +			switch ((radeon_bios8(dev_priv, tv_info + 9) >> 2) & 0x3) { +			case 0: +				DRM_INFO("29.498928713 MHz TV ref clk\n"); +				break; +			case 1: +				DRM_INFO("28.636360000 MHz TV ref clk\n"); +				break; +			case 2: +				DRM_INFO("14.318180000 MHz TV ref clk\n"); +				break; +			case 3: +				DRM_INFO("27.000000000 MHz TV ref clk\n"); +				break; +			default: +				break; +			} +			return true; +		} +	} +	return false; +} +  bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder)  {  	struct drm_device *dev = encoder->base.dev;  	struct drm_radeon_private *dev_priv = dev->dev_private;  	uint16_t lcd_info; +	uint32_t panel_setup;  	char stmp[30];  	int tmp, i; @@ -478,9 +614,57 @@ bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder)  		DRM_INFO("Panel Size %dx%d\n", encoder->panel_xres, encoder->panel_yres); -		encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 44); -		if (encoder->panel_pwr_delay > 2000 || encoder->panel_pwr_delay < 0) -			encoder->panel_pwr_delay = 2000; +		encoder->panel_vcc_delay = radeon_bios16(dev_priv, lcd_info + 44); +		if (encoder->panel_vcc_delay > 2000 || encoder->panel_vcc_delay < 0) +			encoder->panel_vcc_delay = 2000; + +		encoder->panel_pwr_delay = radeon_bios16(dev_priv, lcd_info + 0x24); +		encoder->panel_digon_delay = radeon_bios16(dev_priv, lcd_info + 0x38) & 0xf; +		encoder->panel_blon_delay = (radeon_bios16(dev_priv, lcd_info + 0x38) >> 4) & 0xf; + +		encoder->panel_ref_divider = radeon_bios16(dev_priv, lcd_info + 46); +		encoder->panel_post_divider = radeon_bios8(dev_priv, lcd_info + 48); +		encoder->panel_fb_divider = radeon_bios16(dev_priv, lcd_info + 49); +		if ((encoder->panel_ref_divider != 0) && +		    (encoder->panel_fb_divider > 3)) +			encoder->use_bios_dividers = true; + +		panel_setup = radeon_bios32(dev_priv, lcd_info + 0x39); +		encoder->lvds_gen_cntl = 0; +		if (panel_setup & 0x1) +			encoder->lvds_gen_cntl |= RADEON_LVDS_PANEL_FORMAT; + +		if ((panel_setup >> 4) & 0x1) +			encoder->lvds_gen_cntl |= RADEON_LVDS_PANEL_TYPE; + +		switch ((panel_setup >> 8) & 0x8) { +		case 0: +			encoder->lvds_gen_cntl |= RADEON_LVDS_NO_FM; +			break; +		case 1: +			encoder->lvds_gen_cntl |= RADEON_LVDS_2_GREY; +			break; +		case 2: +			encoder->lvds_gen_cntl |= RADEON_LVDS_4_GREY; +			break; +		default: +			break; +		} + +		if ((panel_setup >> 16) & 0x1) +			encoder->lvds_gen_cntl |= RADEON_LVDS_FP_POL_LOW; + +		if ((panel_setup >> 17) & 0x1) +			encoder->lvds_gen_cntl |= RADEON_LVDS_LP_POL_LOW; + +		if ((panel_setup >> 18) & 0x1) +			encoder->lvds_gen_cntl |= RADEON_LVDS_DTM_POL_LOW; + +		if ((panel_setup >> 23) & 0x1) +			encoder->lvds_gen_cntl |= RADEON_LVDS_BL_CLK_SEL; + +		encoder->lvds_gen_cntl |= (panel_setup & 0xf0000000); +  		for (i = 0; i < 32; i++) {  			tmp = radeon_bios16(dev_priv, lcd_info + 64 + i * 2); diff --git a/linux-core/radeon_legacy_crtc.c b/linux-core/radeon_legacy_crtc.c index 08d4a477..6775ffc0 100644 --- a/linux-core/radeon_legacy_crtc.c +++ b/linux-core/radeon_legacy_crtc.c @@ -356,13 +356,9 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo  		uint32_t tv_dac_cntl = RADEON_READ(RADEON_TV_DAC_CNTL);  		uint32_t dac2_cntl = RADEON_READ(RADEON_DAC_CNTL2);  		uint32_t crtc2_gen_cntl = RADEON_READ(RADEON_CRTC2_GEN_CNTL); -//		state->dac2_cntl = info->StatedReg->dac2_cntl; -//		state->tv_dac_cntl = info->StatedReg->tv_dac_cntl; -//		state->crtc2_gen_cntl = info->StatedReg->crtc2_gen_cntl; -//		state->disp_hw_debug = info->StatedReg->disp_hw_debug; -//		state->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; -//		state->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; +		dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; +		dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;  		/* For CRT on DAC2, don't turn it on if BIOS didn't  		   enable it, even it's detected. @@ -395,19 +391,22 @@ static bool radeon_set_crtc1_timing(struct drm_crtc *crtc, struct drm_display_mo  	return true;  } -static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) +static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode)  {  	struct drm_device *dev = crtc->dev;  	struct drm_radeon_private *dev_priv = dev->dev_private; +	struct drm_encoder *encoder;  	uint32_t feedback_div = 0;  	uint32_t reference_div = 0;  	uint32_t post_divider = 0;  	uint32_t freq = 0;  	uint8_t pll_gain; +	int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; +	bool use_bios_divs = false;  	/* PLL registers */ -	uint32_t ppll_ref_div; -        uint32_t ppll_div_3; -        uint32_t htotal_cntl; +	uint32_t ppll_ref_div = 0; +        uint32_t ppll_div_3 = 0; +        uint32_t htotal_cntl = 0;          uint32_t vclk_ecp_cntl;  	struct radeon_pll *pll = &dev_priv->mode_info.pll; @@ -432,44 +431,56 @@ static void radeon_set_pll1(struct drm_crtc *crtc, struct drm_display_mode *mode  		{  0, 0 }  	}; -#if 0 // TODO -	if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { -		ppll_ref_div = info->RefDivider; -		ppll_div_3   = info->FeedbackDivider | (info->PostDivider << 16); -		htotal_cntl  = 0; -		return; +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { +		if (encoder->crtc == crtc) { +			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) +				pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; +			if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { +				struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + +				if (radeon_encoder->use_bios_dividers) { +					ppll_ref_div = radeon_encoder->panel_ref_divider; +					ppll_div_3   = (radeon_encoder->panel_fb_divider | +							(radeon_encoder->panel_post_divider << 16)); +					htotal_cntl  = 0; +					use_bios_divs = true; +				} else +					pll_flags |= RADEON_PLL_USE_REF_DIV; +			} +		}  	} -#endif  	DRM_DEBUG("\n"); -	radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags); -	for (post_div = &post_divs[0]; post_div->divider; ++post_div) { -		if (post_div->divider == post_divider) -			break; -	} +	if (!use_bios_divs) { +		radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags); -	if (!post_div->divider) { -		post_div = &post_divs[0]; -	} +		for (post_div = &post_divs[0]; post_div->divider; ++post_div) { +			if (post_div->divider == post_divider) +				break; +		} -	DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", -		  (unsigned)freq, -		  feedback_div, -		  reference_div, -		  post_divider); +		if (!post_div->divider) { +			post_div = &post_divs[0]; +		} -	ppll_ref_div   = reference_div; +		DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", +			  (unsigned)freq, +			  feedback_div, +			  reference_div, +			  post_divider); +		ppll_ref_div   = reference_div;  #if defined(__powerpc__) && (0) /* TODO */ -	/* apparently programming this otherwise causes a hang??? */ -	if (info->MacModel == RADEON_MAC_IBOOK) -		state->ppll_div_3 = 0x000600ad; -	else +		/* apparently programming this otherwise causes a hang??? */ +		if (info->MacModel == RADEON_MAC_IBOOK) +			state->ppll_div_3 = 0x000600ad; +		else  #endif -		ppll_div_3     = (feedback_div | (post_div->bitvalue << 16)); +			ppll_div_3     = (feedback_div | (post_div->bitvalue << 16)); +		htotal_cntl    = mode->htotal & 0x7; -	htotal_cntl    = mode->htotal & 0x7; +	}  	vclk_ecp_cntl = (RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL) &  			 ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; @@ -783,19 +794,22 @@ static bool radeon_set_crtc2_timing(struct drm_crtc *crtc, struct drm_display_mo  } -static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode, int flags) +static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode)  {  	struct drm_device *dev = crtc->dev;  	struct drm_radeon_private *dev_priv = dev->dev_private; +	struct drm_encoder *encoder;  	uint32_t feedback_div = 0;  	uint32_t reference_div = 0;  	uint32_t post_divider = 0;  	uint32_t freq = 0;  	uint8_t pll_gain; +	int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV; +	bool use_bios_divs = false;  	/* PLL2 registers */ -	uint32_t p2pll_ref_div; -	uint32_t p2pll_div_0; -	uint32_t htotal_cntl2; +	uint32_t p2pll_ref_div = 0; +	uint32_t p2pll_div_0 = 0; +	uint32_t htotal_cntl2 = 0;  	uint32_t pixclks_cntl;  	struct radeon_pll *pll = &dev_priv->mode_info.pll; @@ -819,37 +833,50 @@ static void radeon_set_pll2(struct drm_crtc *crtc, struct drm_display_mode *mode  		{  0, 0 }  	}; -#if 0 -	if ((flags & RADEON_PLL_USE_BIOS_DIVS) && info->UseBiosDividers) { -		p2pll_ref_div = info->RefDivider; -		p2pll_div_0   = info->FeedbackDivider | (info->PostDivider << 16); -		htotal_cntl2  = 0; -		return; +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { +		if (encoder->crtc == crtc) { +			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) +				pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; +			if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { +				struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + +				if (radeon_encoder->use_bios_dividers) { +					p2pll_ref_div = radeon_encoder->panel_ref_divider; +					p2pll_div_0   = (radeon_encoder->panel_fb_divider | +							(radeon_encoder->panel_post_divider << 16)); +					htotal_cntl2  = 0; +					use_bios_divs = true; +				} else +					pll_flags |= RADEON_PLL_USE_REF_DIV; +			} +		}  	} -#endif -	radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, flags); +	DRM_DEBUG("\n"); -	for (post_div = &post_divs[0]; post_div->divider; ++post_div) { -		if (post_div->divider == post_divider) -			break; -	} +	if (!use_bios_divs) { +		radeon_compute_pll(pll, mode->clock, &freq, &feedback_div, &reference_div, &post_divider, pll_flags); -	if (!post_div->divider) { -		post_div = &post_divs[0]; -	} +		for (post_div = &post_divs[0]; post_div->divider; ++post_div) { +			if (post_div->divider == post_divider) +				break; +		} -	DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", -		  (unsigned)freq, -		  feedback_div, -		  reference_div, -		  post_divider); +		if (!post_div->divider) { +			post_div = &post_divs[0]; +		} -	p2pll_ref_div    = reference_div; +		DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", +			  (unsigned)freq, +			  feedback_div, +			  reference_div, +			  post_divider); -	p2pll_div_0      = (feedback_div | (post_div->bitvalue << 16)); +		p2pll_ref_div    = reference_div; +		p2pll_div_0      = (feedback_div | (post_div->bitvalue << 16)); +		htotal_cntl2     = mode->htotal & 0x7; -	htotal_cntl2     = mode->htotal & 0x7; +	}  	pixclks_cntl     = ((RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL) &  			     ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | @@ -946,22 +973,9 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc,  				 int x, int y)  {  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); -	struct drm_device *dev = crtc->dev; -	struct drm_encoder *encoder; -	int pll_flags = RADEON_PLL_LEGACY | RADEON_PLL_PREFER_LOW_REF_DIV;  	DRM_DEBUG("\n"); -	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - -		if (encoder->crtc == crtc) { -			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_BIOS_DIVS | RADEON_PLL_USE_REF_DIV; -		} -	} -  	/* TODO TV */  	radeon_crtc_set_base(crtc, x, y); @@ -969,11 +983,11 @@ static void radeon_crtc_mode_set(struct drm_crtc *crtc,  	switch(radeon_crtc->crtc_id) {  	case 0:  		radeon_set_crtc1_timing(crtc, adjusted_mode); -		radeon_set_pll1(crtc, adjusted_mode, pll_flags); +		radeon_set_pll1(crtc, adjusted_mode);  		break;  	case 1:  		radeon_set_crtc2_timing(crtc, adjusted_mode); -		radeon_set_pll2(crtc, adjusted_mode, pll_flags); +		radeon_set_pll2(crtc, adjusted_mode);  		break;  	} diff --git a/linux-core/radeon_legacy_encoders.c b/linux-core/radeon_legacy_encoders.c index de9e8ac6..172f93de 100644 --- a/linux-core/radeon_legacy_encoders.c +++ b/linux-core/radeon_legacy_encoders.c @@ -213,10 +213,20 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)  		lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL);  		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;  		RADEON_WRITE(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); + +		/* enable lvds, turn on voltage */  		lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); -		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); +		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); +		RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); +		udelay(radeon_encoder->panel_digon_delay * 1000); + +		/* enable data */  		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); -		udelay(radeon_encoder->panel_pwr_delay * 1000); +		RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); +		udelay(radeon_encoder->panel_blon_delay * 1000); + +		/* enable backlight */ +		lvds_gen_cntl |= RADEON_LVDS_BLON;  		RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);  		break;  	case DRM_MODE_DPMS_STANDBY: @@ -226,7 +236,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)  		RADEON_WRITE_PLL_P(dev_priv, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);                  lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL);                  lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; -                lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN); +                lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);                  RADEON_WRITE(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);  		RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, pixclks_cntl);  		break; @@ -260,7 +270,10 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,  	lvds_pll_cntl = RADEON_READ(RADEON_LVDS_PLL_CNTL);  	lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; -	lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL); +	if (radeon_encoder->lvds_gen_cntl) +		lvds_gen_cntl = radeon_encoder->lvds_gen_cntl; +	else +		lvds_gen_cntl = RADEON_READ(RADEON_LVDS_GEN_CNTL);  	lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;  	lvds_gen_cntl &= ~(RADEON_LVDS_ON |  			   RADEON_LVDS_BLON | @@ -339,7 +352,6 @@ struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int b  	drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); -	/* TODO get the LVDS info from the BIOS for panel size etc. */  	/* get the lvds info from the bios */  	radeon_combios_get_lvds_info(radeon_encoder); @@ -659,6 +671,7 @@ struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, i  	drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);  	radeon_combios_get_tmds_info(radeon_encoder); +  	return encoder;  } @@ -893,6 +906,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,  	struct drm_device *dev = encoder->dev;  	struct drm_radeon_private *dev_priv = dev->dev_private;  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); +	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  	uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;  	uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0; @@ -924,8 +938,8 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,  		// FIXME TV  		tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |  				RADEON_TV_DAC_NHOLD | -				RADEON_TV_DAC_STD_PS2 /*| -				radeon_encoder->ps2_tvdac_adj*/); // fixme, get from bios +				RADEON_TV_DAC_STD_PS2 | +				radeon_encoder->ps2_tvdac_adj);  		RADEON_WRITE(RADEON_TV_DAC_CNTL, tv_dac_cntl);  	} @@ -1015,8 +1029,9 @@ struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int  	drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs); -	/* TODO get the tv dac vals from bios tables */ -	//radeon_combios_get_lvds_info(radeon_encoder); +	/* get the tv dac vals from bios tables */ +	radeon_combios_get_tv_info(radeon_encoder); +	radeon_combios_get_tv_dac_info(radeon_encoder);  	return encoder;  } diff --git a/linux-core/radeon_mode.h b/linux-core/radeon_mode.h index 6a2e275c..3271375d 100644 --- a/linux-core/radeon_mode.h +++ b/linux-core/radeon_mode.h @@ -87,6 +87,17 @@ enum radeon_rmx_type {  	RMX_CENTER,  }; +enum radeon_tv_std { +	TV_STD_NTSC, +	TV_STD_PAL, +	TV_STD_PAL_M, +	TV_STD_PAL_60, +	TV_STD_NTSC_J, +	TV_STD_SCART_PAL, +	TV_STD_SECAM, +	TV_STD_PAL_CN, +}; +  struct radeon_i2c_bus_rec {  	bool valid;  	uint32_t mask_clk_reg; @@ -337,13 +348,33 @@ struct radeon_encoder {  		enum radeon_tmds_type tmds;  	} type;  	int atom_device; /* atom devices */ + +	/* preferred mode */  	uint32_t panel_xres, panel_yres;  	uint32_t hoverplus, hsync_width;  	uint32_t hblank;  	uint32_t voverplus, vsync_width;  	uint32_t vblank; -	uint32_t panel_pwr_delay;  	uint32_t dotclock; + +	/* legacy lvds */ +	uint16_t panel_vcc_delay; +	uint16_t panel_pwr_delay; +	uint16_t panel_digon_delay; +	uint16_t panel_blon_delay; +	uint32_t panel_ref_divider; +	uint32_t panel_post_divider; +	uint32_t panel_fb_divider; +	bool use_bios_dividers; +	uint32_t lvds_gen_cntl; + +	/* legacy tv dac */ +	uint32_t ps2_tvdac_adj; +	uint32_t ntsc_tvdac_adj; +	uint32_t pal_tvdac_adj; +	enum radeon_tv_std tv_std; + +	/* legacy int tmds */  	struct radeon_tmds_pll tmds_pll[4];  }; @@ -351,7 +382,6 @@ struct radeon_connector {  	struct drm_connector base;  	struct radeon_i2c_chan *ddc_bus;  	int use_digital; -	  };  struct radeon_framebuffer { @@ -407,6 +437,8 @@ extern bool radeon_combios_get_clock_info(struct drm_device *dev);  extern void radeon_get_lvds_info(struct radeon_encoder *encoder);  extern bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder);  extern bool radeon_combios_get_tmds_info(struct radeon_encoder *encoder); +extern bool radeon_combios_get_tv_info(struct radeon_encoder *encoder); +extern bool radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);  extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,  				     u16 blue, int regno);  struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev, diff --git a/linux-core/radeon_reg.h b/linux-core/radeon_reg.h index ad91e04c..59108979 100644 --- a/linux-core/radeon_reg.h +++ b/linux-core/radeon_reg.h @@ -1027,14 +1027,23 @@  #       define RADEON_LVDS_DISPLAY_DIS      (1   <<  1)  #       define RADEON_LVDS_PANEL_TYPE       (1   <<  2)  #       define RADEON_LVDS_PANEL_FORMAT     (1   <<  3) +#       define RADEON_LVDS_NO_FM            (0   <<  4) +#       define RADEON_LVDS_2_GREY           (1   <<  4) +#       define RADEON_LVDS_4_GREY           (2   <<  4)  #       define RADEON_LVDS_RST_FM           (1   <<  6)  #       define RADEON_LVDS_EN               (1   <<  7)  #       define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8  #       define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8)  #       define RADEON_LVDS_BL_MOD_EN        (1   << 16) +#       define RADEON_LVDS_BL_CLK_SEL       (1   << 17)  #       define RADEON_LVDS_DIGON            (1   << 18)  #       define RADEON_LVDS_BLON             (1   << 19) +#       define RADEON_LVDS_FP_POL_LOW       (1   << 20) +#       define RADEON_LVDS_LP_POL_LOW       (1   << 21) +#       define RADEON_LVDS_DTM_POL_LOW      (1   << 22)  #       define RADEON_LVDS_SEL_CRTC2        (1   << 23) +#       define RADEON_LVDS_FPDI_EN          (1   << 27) +#       define RADEON_LVDS_HSYNC_DELAY_SHIFT        28  #define RADEON_LVDS_PLL_CNTL                0x02d4  #       define RADEON_HSYNC_DELAY_SHIFT     28  #       define RADEON_HSYNC_DELAY_MASK      (0xf << 28) | 
