forked from mirrors/linux
		
	drm/radeon/kms: add initial radeon tv-out support.
This ports the tv-out code from the DDX to KMS. adds a radeon.tv module option, radeon.tv=0 to disable tv Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
		
							parent
							
								
									551ebd837c
								
							
						
					
					
						commit
						4ce001abaf
					
				
					 15 changed files with 1943 additions and 390 deletions
				
			
		| 
						 | 
				
			
			@ -47,7 +47,7 @@ radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \
 | 
			
		|||
	radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \
 | 
			
		||||
	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
 | 
			
		||||
	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o \
 | 
			
		||||
	radeon_test.o r200.o
 | 
			
		||||
	radeon_test.o r200.o radeon_legacy_tv.o
 | 
			
		||||
 | 
			
		||||
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2374,6 +2374,17 @@ typedef struct _ATOM_ANALOG_TV_INFO {
 | 
			
		|||
	ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING];
 | 
			
		||||
} ATOM_ANALOG_TV_INFO;
 | 
			
		||||
 | 
			
		||||
#define MAX_SUPPORTED_TV_TIMING_V1_2    3
 | 
			
		||||
 | 
			
		||||
typedef struct _ATOM_ANALOG_TV_INFO_V1_2 {
 | 
			
		||||
	ATOM_COMMON_TABLE_HEADER sHeader;
 | 
			
		||||
	UCHAR                    ucTV_SupportedStandard;
 | 
			
		||||
	UCHAR                    ucTV_BootUpDefaultStandard;
 | 
			
		||||
	UCHAR                    ucExt_TV_ASIC_ID;
 | 
			
		||||
	UCHAR                    ucExt_TV_ASIC_SlaveAddr;
 | 
			
		||||
	ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING];
 | 
			
		||||
} ATOM_ANALOG_TV_INFO_V1_2;
 | 
			
		||||
 | 
			
		||||
/**************************************************************************/
 | 
			
		||||
/*  VRAM usage and their defintions */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,10 @@
 | 
			
		|||
#include "atom.h"
 | 
			
		||||
#include "atom-bits.h"
 | 
			
		||||
 | 
			
		||||
/* evil but including atombios.h is much worse */
 | 
			
		||||
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
 | 
			
		||||
				SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
 | 
			
		||||
				int32_t *pixel_clock);
 | 
			
		||||
static void atombios_overscan_setup(struct drm_crtc *crtc,
 | 
			
		||||
				    struct drm_display_mode *mode,
 | 
			
		||||
				    struct drm_display_mode *adjusted_mode)
 | 
			
		||||
| 
						 | 
				
			
			@ -89,17 +93,32 @@ 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);
 | 
			
		||||
 | 
			
		||||
	/* 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;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&args, 0, sizeof(args));
 | 
			
		||||
 | 
			
		||||
	args.ucScaler = radeon_crtc->crtc_id;
 | 
			
		||||
 | 
			
		||||
	if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) {
 | 
			
		||||
	if (is_tv) {
 | 
			
		||||
		switch (tv_std) {
 | 
			
		||||
		case TV_STD_NTSC:
 | 
			
		||||
		default:
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +147,7 @@ static void atombios_scaler_setup(struct drm_crtc *crtc)
 | 
			
		|||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
 | 
			
		||||
	} else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) {
 | 
			
		||||
	} else if (is_cv) {
 | 
			
		||||
		args.ucTVStandard = ATOM_TV_CV;
 | 
			
		||||
		args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -151,9 +170,9 @@ static void atombios_scaler_setup(struct drm_crtc *crtc)
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 | 
			
		||||
	if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
 | 
			
		||||
	    && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
 | 
			
		||||
		atom_rv515_force_tv_scaler(rdev);
 | 
			
		||||
	if ((is_tv || is_cv)
 | 
			
		||||
	    && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) {
 | 
			
		||||
		atom_rv515_force_tv_scaler(rdev, radeon_crtc);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -551,42 +570,68 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		|||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct drm_encoder *encoder;
 | 
			
		||||
	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
 | 
			
		||||
	int need_tv_timings = 0;
 | 
			
		||||
	bool ret;
 | 
			
		||||
 | 
			
		||||
	/* TODO color tiling */
 | 
			
		||||
	memset(&crtc_timing, 0, sizeof(crtc_timing));
 | 
			
		||||
 | 
			
		||||
	/* TODO tv */
 | 
			
		||||
	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;
 | 
			
		||||
				if (tv_dac) {
 | 
			
		||||
					if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
					    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
					    tv_dac->tv_std == TV_STD_PAL_M)
 | 
			
		||||
						need_tv_timings = 1;
 | 
			
		||||
					else
 | 
			
		||||
						need_tv_timings = 2;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	crtc_timing.ucCRTC = radeon_crtc->crtc_id;
 | 
			
		||||
	crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
 | 
			
		||||
	crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
 | 
			
		||||
	crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
 | 
			
		||||
	crtc_timing.usH_SyncWidth =
 | 
			
		||||
	    adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
 | 
			
		||||
	if (need_tv_timings) {
 | 
			
		||||
		ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1,
 | 
			
		||||
						 &crtc_timing, &adjusted_mode->clock);
 | 
			
		||||
		if (ret == false)
 | 
			
		||||
			need_tv_timings = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
 | 
			
		||||
	crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
 | 
			
		||||
	crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
 | 
			
		||||
	crtc_timing.usV_SyncWidth =
 | 
			
		||||
	    adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
 | 
			
		||||
	if (!need_tv_timings) {
 | 
			
		||||
		crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
 | 
			
		||||
		crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
 | 
			
		||||
		crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
 | 
			
		||||
		crtc_timing.usH_SyncWidth =
 | 
			
		||||
			adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
 | 
			
		||||
 | 
			
		||||
	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
 | 
			
		||||
		crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
 | 
			
		||||
		crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
 | 
			
		||||
		crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
 | 
			
		||||
		crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
 | 
			
		||||
		crtc_timing.usV_SyncWidth =
 | 
			
		||||
			adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
 | 
			
		||||
 | 
			
		||||
	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
 | 
			
		||||
		crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
 | 
			
		||||
		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
 | 
			
		||||
			crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
 | 
			
		||||
 | 
			
		||||
	if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
 | 
			
		||||
		crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
 | 
			
		||||
		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
 | 
			
		||||
			crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
 | 
			
		||||
 | 
			
		||||
	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
 | 
			
		||||
		crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
 | 
			
		||||
		if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
 | 
			
		||||
			crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
 | 
			
		||||
 | 
			
		||||
	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 | 
			
		||||
		crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
 | 
			
		||||
		if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
 | 
			
		||||
			crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
 | 
			
		||||
 | 
			
		||||
		if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 | 
			
		||||
			crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	atombios_crtc_set_pll(crtc, adjusted_mode);
 | 
			
		||||
	atombios_crtc_set_timing(crtc, &crtc_timing);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,6 +66,7 @@ extern int radeon_gart_size;
 | 
			
		|||
extern int radeon_benchmarking;
 | 
			
		||||
extern int radeon_testing;
 | 
			
		||||
extern int radeon_connector_table;
 | 
			
		||||
extern int radeon_tv;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copy from radeon_drv.h so we don't have to include both and have conflicting
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -471,11 +471,6 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
 | 
			
		|||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (i == ATOM_DEVICE_TV1_INDEX) {
 | 
			
		||||
			DRM_DEBUG("Skipping TV Out\n");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bios_connectors[i].connector_type =
 | 
			
		||||
		    supported_devices_connector_convert[ci.sucConnectorInfo.
 | 
			
		||||
							sbfAccess.
 | 
			
		||||
| 
						 | 
				
			
			@ -858,6 +853,72 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
 | 
			
		|||
	return p_dac;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
 | 
			
		||||
				SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
 | 
			
		||||
				int32_t *pixel_clock)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_mode_info *mode_info = &rdev->mode_info;
 | 
			
		||||
	ATOM_ANALOG_TV_INFO *tv_info;
 | 
			
		||||
	ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
 | 
			
		||||
	ATOM_DTD_FORMAT *dtd_timings;
 | 
			
		||||
	int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
 | 
			
		||||
	u8 frev, crev;
 | 
			
		||||
	uint16_t data_offset;
 | 
			
		||||
 | 
			
		||||
	atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
 | 
			
		||||
 | 
			
		||||
	switch (crev) {
 | 
			
		||||
	case 1:
 | 
			
		||||
		tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
 | 
			
		||||
		if (index > MAX_SUPPORTED_TV_TIMING)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
 | 
			
		||||
		crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
 | 
			
		||||
		crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
 | 
			
		||||
		crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
 | 
			
		||||
 | 
			
		||||
		crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
 | 
			
		||||
		crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
 | 
			
		||||
		crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
 | 
			
		||||
		crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
 | 
			
		||||
 | 
			
		||||
		crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
 | 
			
		||||
 | 
			
		||||
		crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight);
 | 
			
		||||
		crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft);
 | 
			
		||||
		crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom);
 | 
			
		||||
		crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop);
 | 
			
		||||
		*pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
 | 
			
		||||
 | 
			
		||||
		if (index == 1) {
 | 
			
		||||
			/* PAL timings appear to have wrong values for totals */
 | 
			
		||||
			crtc_timing->usH_Total -= 1;
 | 
			
		||||
			crtc_timing->usV_Total -= 1;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
 | 
			
		||||
		if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		dtd_timings = &tv_info_v1_2->aModeTimings[index];
 | 
			
		||||
		crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time);
 | 
			
		||||
		crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive);
 | 
			
		||||
		crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset);
 | 
			
		||||
		crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth);
 | 
			
		||||
		crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time);
 | 
			
		||||
		crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive);
 | 
			
		||||
		crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset);
 | 
			
		||||
		crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth);
 | 
			
		||||
 | 
			
		||||
		crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
 | 
			
		||||
		*pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct radeon_encoder_tv_dac *
 | 
			
		||||
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -948,10 +1009,10 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
 | 
			
		|||
	uint32_t bios_2_scratch, bios_6_scratch;
 | 
			
		||||
 | 
			
		||||
	if (rdev->family >= CHIP_R600) {
 | 
			
		||||
		bios_2_scratch = RREG32(R600_BIOS_0_SCRATCH);
 | 
			
		||||
		bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
 | 
			
		||||
		bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
 | 
			
		||||
	} else {
 | 
			
		||||
		bios_2_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
 | 
			
		||||
		bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
 | 
			
		||||
		bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,6 +94,54 @@ struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
 | 
			
		|||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * radeon_connector_analog_encoder_conflict_solve
 | 
			
		||||
 * - search for other connectors sharing this encoder
 | 
			
		||||
 *   if priority is true, then set them disconnected if this is connected
 | 
			
		||||
 *   if priority is false, set us disconnected if they are connected
 | 
			
		||||
 */
 | 
			
		||||
static enum drm_connector_status
 | 
			
		||||
radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
 | 
			
		||||
					       struct drm_encoder *encoder,
 | 
			
		||||
					       enum drm_connector_status current_status,
 | 
			
		||||
					       bool priority)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = connector->dev;
 | 
			
		||||
	struct drm_connector *conflict;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
 | 
			
		||||
		if (conflict == connector)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 | 
			
		||||
			if (conflict->encoder_ids[i] == 0)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			/* if the IDs match */
 | 
			
		||||
			if (conflict->encoder_ids[i] == encoder->base.id) {
 | 
			
		||||
				if (conflict->status != connector_status_connected)
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				if (priority == true) {
 | 
			
		||||
					DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict));
 | 
			
		||||
					DRM_INFO("in favor of %s\n", drm_get_connector_name(connector));
 | 
			
		||||
					conflict->status = connector_status_disconnected;
 | 
			
		||||
					radeon_connector_update_scratch_regs(conflict, connector_status_disconnected);
 | 
			
		||||
				} else {
 | 
			
		||||
					DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector));
 | 
			
		||||
					DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict));
 | 
			
		||||
					current_status = connector_status_disconnected;
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return current_status;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
| 
						 | 
				
			
			@ -213,7 +261,6 @@ static int radeon_vga_get_modes(struct drm_connector *connector)
 | 
			
		|||
static int radeon_vga_mode_valid(struct drm_connector *connector,
 | 
			
		||||
				  struct drm_display_mode *mode)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	return MODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -225,22 +272,22 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
 | 
			
		|||
	bool dret;
 | 
			
		||||
	enum drm_connector_status ret = connector_status_disconnected;
 | 
			
		||||
 | 
			
		||||
	encoder = radeon_best_single_encoder(connector);
 | 
			
		||||
	if (!encoder)
 | 
			
		||||
		ret = connector_status_disconnected;
 | 
			
		||||
 | 
			
		||||
	radeon_i2c_do_lock(radeon_connector, 1);
 | 
			
		||||
	dret = radeon_ddc_probe(radeon_connector);
 | 
			
		||||
	radeon_i2c_do_lock(radeon_connector, 0);
 | 
			
		||||
	if (dret)
 | 
			
		||||
		ret = connector_status_connected;
 | 
			
		||||
	else {
 | 
			
		||||
		/* if EDID fails to a load detect */
 | 
			
		||||
		encoder = radeon_best_single_encoder(connector);
 | 
			
		||||
		if (!encoder)
 | 
			
		||||
			ret = connector_status_disconnected;
 | 
			
		||||
		else {
 | 
			
		||||
			encoder_funcs = encoder->helper_private;
 | 
			
		||||
			ret = encoder_funcs->detect(encoder, connector);
 | 
			
		||||
		}
 | 
			
		||||
		encoder_funcs = encoder->helper_private;
 | 
			
		||||
		ret = encoder_funcs->detect(encoder, connector);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ret == connector_status_connected)
 | 
			
		||||
		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
 | 
			
		||||
	radeon_connector_update_scratch_regs(connector, ret);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -259,21 +306,87 @@ struct drm_connector_funcs radeon_vga_connector_funcs = {
 | 
			
		|||
	.set_property = radeon_connector_set_property,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct drm_display_mode tv_fixed_mode = {
 | 
			
		||||
	DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 38250, 800, 832,
 | 
			
		||||
		 912, 1024, 0, 600, 603, 607, 624, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int radeon_tv_get_modes(struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = connector->dev;
 | 
			
		||||
	struct drm_display_mode *tv_mode;
 | 
			
		||||
 | 
			
		||||
	tv_mode = drm_mode_duplicate(dev, &tv_fixed_mode);
 | 
			
		||||
	tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 | 
			
		||||
 | 
			
		||||
	drm_mode_probed_add(connector, tv_mode);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int radeon_tv_mode_valid(struct drm_connector *connector,
 | 
			
		||||
				struct drm_display_mode *mode)
 | 
			
		||||
{
 | 
			
		||||
	return MODE_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_encoder *encoder;
 | 
			
		||||
	struct drm_encoder_helper_funcs *encoder_funcs;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	encoder = radeon_best_single_encoder(connector);
 | 
			
		||||
	if (!encoder)
 | 
			
		||||
		ret = connector_status_disconnected;
 | 
			
		||||
	else {
 | 
			
		||||
		encoder_funcs = encoder->helper_private;
 | 
			
		||||
		ret = encoder_funcs->detect(encoder, connector);
 | 
			
		||||
	}
 | 
			
		||||
	if (ret == connector_status_connected)
 | 
			
		||||
		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
 | 
			
		||||
	radeon_connector_update_scratch_regs(connector, ret);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = {
 | 
			
		||||
	.get_modes = radeon_tv_get_modes,
 | 
			
		||||
	.mode_valid = radeon_tv_mode_valid,
 | 
			
		||||
	.best_encoder = radeon_best_single_encoder,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct drm_connector_funcs radeon_tv_connector_funcs = {
 | 
			
		||||
	.dpms = drm_helper_connector_dpms,
 | 
			
		||||
	.detect = radeon_tv_detect,
 | 
			
		||||
	.fill_modes = drm_helper_probe_single_connector_modes,
 | 
			
		||||
	.destroy = radeon_connector_destroy,
 | 
			
		||||
	.set_property = radeon_connector_set_property,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int radeon_dvi_get_modes(struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = radeon_ddc_get_modes(radeon_connector);
 | 
			
		||||
	/* reset scratch regs here since radeon_dvi_detect doesn't check digital bit */
 | 
			
		||||
	radeon_connector_update_scratch_regs(connector, connector_status_connected);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DVI is complicated
 | 
			
		||||
 * Do a DDC probe, if DDC probe passes, get the full EDID so
 | 
			
		||||
 * we can do analog/digital monitor detection at this point.
 | 
			
		||||
 * If the monitor is an analog monitor or we got no DDC,
 | 
			
		||||
 * we need to find the DAC encoder object for this connector.
 | 
			
		||||
 * If we got no DDC, we do load detection on the DAC encoder object.
 | 
			
		||||
 * If we got analog DDC or load detection passes on the DAC encoder
 | 
			
		||||
 * we have to check if this analog encoder is shared with anyone else (TV)
 | 
			
		||||
 * if its shared we have to set the other connector to disconnected.
 | 
			
		||||
 */
 | 
			
		||||
static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 | 
			
		||||
	struct drm_encoder *encoder;
 | 
			
		||||
	struct drm_encoder *encoder = NULL;
 | 
			
		||||
	struct drm_encoder_helper_funcs *encoder_funcs;
 | 
			
		||||
	struct drm_mode_object *obj;
 | 
			
		||||
	int i;
 | 
			
		||||
| 
						 | 
				
			
			@ -283,32 +396,58 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
 | 
			
		|||
	radeon_i2c_do_lock(radeon_connector, 1);
 | 
			
		||||
	dret = radeon_ddc_probe(radeon_connector);
 | 
			
		||||
	radeon_i2c_do_lock(radeon_connector, 0);
 | 
			
		||||
	if (dret)
 | 
			
		||||
		ret = connector_status_connected;
 | 
			
		||||
	else {
 | 
			
		||||
		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 | 
			
		||||
			if (connector->encoder_ids[i] == 0)
 | 
			
		||||
				break;
 | 
			
		||||
	if (dret) {
 | 
			
		||||
		radeon_i2c_do_lock(radeon_connector, 1);
 | 
			
		||||
		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
 | 
			
		||||
		radeon_i2c_do_lock(radeon_connector, 0);
 | 
			
		||||
 | 
			
		||||
			obj = drm_mode_object_find(connector->dev,
 | 
			
		||||
						   connector->encoder_ids[i],
 | 
			
		||||
						   DRM_MODE_OBJECT_ENCODER);
 | 
			
		||||
			if (!obj)
 | 
			
		||||
				continue;
 | 
			
		||||
		if (!radeon_connector->edid) {
 | 
			
		||||
			DRM_ERROR("DDC responded but not EDID found for %s\n",
 | 
			
		||||
				  drm_get_connector_name(connector));
 | 
			
		||||
		} else {
 | 
			
		||||
			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
 | 
			
		||||
 | 
			
		||||
			encoder = obj_to_encoder(obj);
 | 
			
		||||
 | 
			
		||||
			encoder_funcs = encoder->helper_private;
 | 
			
		||||
			if (encoder_funcs->detect) {
 | 
			
		||||
				ret = encoder_funcs->detect(encoder, connector);
 | 
			
		||||
				if (ret == connector_status_connected) {
 | 
			
		||||
					radeon_connector->use_digital = 0;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			/* if this isn't a digital monitor
 | 
			
		||||
			   then we need to make sure we don't have any
 | 
			
		||||
			   TV conflicts */
 | 
			
		||||
			ret = connector_status_connected;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	/* find analog encoder */
 | 
			
		||||
	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 | 
			
		||||
		if (connector->encoder_ids[i] == 0)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		obj = drm_mode_object_find(connector->dev,
 | 
			
		||||
					   connector->encoder_ids[i],
 | 
			
		||||
					   DRM_MODE_OBJECT_ENCODER);
 | 
			
		||||
		if (!obj)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		encoder = obj_to_encoder(obj);
 | 
			
		||||
 | 
			
		||||
		encoder_funcs = encoder->helper_private;
 | 
			
		||||
		if (encoder_funcs->detect) {
 | 
			
		||||
			if (ret != connector_status_connected) {
 | 
			
		||||
				ret = encoder_funcs->detect(encoder, connector);
 | 
			
		||||
				if (ret == connector_status_connected) {
 | 
			
		||||
					radeon_connector->use_digital = false;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) &&
 | 
			
		||||
	    encoder) {
 | 
			
		||||
		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	/* updated in get modes as well since we need to know if it's analog or digital */
 | 
			
		||||
	radeon_connector_update_scratch_regs(connector, ret);
 | 
			
		||||
	return ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -332,7 +471,7 @@ struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
 | 
			
		|||
 | 
			
		||||
		encoder = obj_to_encoder(obj);
 | 
			
		||||
 | 
			
		||||
		if (radeon_connector->use_digital) {
 | 
			
		||||
		if (radeon_connector->use_digital == true) {
 | 
			
		||||
			if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
 | 
			
		||||
				return encoder;
 | 
			
		||||
		} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -385,10 +524,7 @@ radeon_add_atom_connector(struct drm_device *dev,
 | 
			
		|||
	uint32_t subpixel_order = SubPixelNone;
 | 
			
		||||
 | 
			
		||||
	/* fixme - tv/cv/din */
 | 
			
		||||
	if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
 | 
			
		||||
	    (connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
 | 
			
		||||
	    (connector_type == DRM_MODE_CONNECTOR_Composite) ||
 | 
			
		||||
	    (connector_type == DRM_MODE_CONNECTOR_9PinDIN))
 | 
			
		||||
	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* see if we already added it */
 | 
			
		||||
| 
						 | 
				
			
			@ -480,6 +616,10 @@ radeon_add_atom_connector(struct drm_device *dev,
 | 
			
		|||
	case DRM_MODE_CONNECTOR_SVIDEO:
 | 
			
		||||
	case DRM_MODE_CONNECTOR_Composite:
 | 
			
		||||
	case DRM_MODE_CONNECTOR_9PinDIN:
 | 
			
		||||
		if (radeon_tv == 1) {
 | 
			
		||||
			drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
 | 
			
		||||
			drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case DRM_MODE_CONNECTOR_LVDS:
 | 
			
		||||
		radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
 | 
			
		||||
| 
						 | 
				
			
			@ -522,10 +662,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 | 
			
		|||
	uint32_t subpixel_order = SubPixelNone;
 | 
			
		||||
 | 
			
		||||
	/* fixme - tv/cv/din */
 | 
			
		||||
	if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
 | 
			
		||||
	    (connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
 | 
			
		||||
	    (connector_type == DRM_MODE_CONNECTOR_Composite) ||
 | 
			
		||||
	    (connector_type == DRM_MODE_CONNECTOR_9PinDIN))
 | 
			
		||||
	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* see if we already added it */
 | 
			
		||||
| 
						 | 
				
			
			@ -578,6 +715,10 @@ radeon_add_legacy_connector(struct drm_device *dev,
 | 
			
		|||
	case DRM_MODE_CONNECTOR_SVIDEO:
 | 
			
		||||
	case DRM_MODE_CONNECTOR_Composite:
 | 
			
		||||
	case DRM_MODE_CONNECTOR_9PinDIN:
 | 
			
		||||
		if (radeon_tv == 1) {
 | 
			
		||||
			drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
 | 
			
		||||
			drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case DRM_MODE_CONNECTOR_LVDS:
 | 
			
		||||
		drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -312,7 +312,7 @@ static void radeon_print_display_setup(struct drm_device *dev)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool radeon_setup_enc_conn(struct drm_device *dev)
 | 
			
		||||
static bool radeon_setup_enc_conn(struct drm_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct drm_connector *drm_connector;
 | 
			
		||||
| 
						 | 
				
			
			@ -346,9 +346,13 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
 | 
			
		|||
 | 
			
		||||
	if (!radeon_connector->ddc_bus)
 | 
			
		||||
		return -1;
 | 
			
		||||
	radeon_i2c_do_lock(radeon_connector, 1);
 | 
			
		||||
	edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
 | 
			
		||||
	radeon_i2c_do_lock(radeon_connector, 0);
 | 
			
		||||
	if (!radeon_connector->edid) {
 | 
			
		||||
		radeon_i2c_do_lock(radeon_connector, 1);
 | 
			
		||||
		edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
 | 
			
		||||
		radeon_i2c_do_lock(radeon_connector, 0);
 | 
			
		||||
	} else
 | 
			
		||||
		edid = radeon_connector->edid;
 | 
			
		||||
 | 
			
		||||
	if (edid) {
 | 
			
		||||
		/* update digital bits here */
 | 
			
		||||
		if (edid->input & DRM_EDID_INPUT_DIGITAL)
 | 
			
		||||
| 
						 | 
				
			
			@ -677,7 +681,6 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
 | 
			
		|||
			continue;
 | 
			
		||||
		if (first) {
 | 
			
		||||
			radeon_crtc->rmx_type = radeon_encoder->rmx_type;
 | 
			
		||||
			radeon_crtc->devices = radeon_encoder->devices;
 | 
			
		||||
			memcpy(&radeon_crtc->native_mode,
 | 
			
		||||
				&radeon_encoder->native_mode,
 | 
			
		||||
				sizeof(struct radeon_native_mode));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,6 +91,7 @@ int radeon_gart_size = 512; /* default gart size */
 | 
			
		|||
int radeon_benchmarking = 0;
 | 
			
		||||
int radeon_testing = 0;
 | 
			
		||||
int radeon_connector_table = 0;
 | 
			
		||||
int radeon_tv = 1;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +124,9 @@ module_param_named(test, radeon_testing, int, 0444);
 | 
			
		|||
 | 
			
		||||
MODULE_PARM_DESC(connector_table, "Force connector table");
 | 
			
		||||
module_param_named(connector_table, radeon_connector_table, int, 0444);
 | 
			
		||||
 | 
			
		||||
MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
 | 
			
		||||
module_param_named(tv, radeon_tv, int, 0444);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,6 +126,23 @@ radeon_link_encoder_connector(struct drm_device *dev)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void radeon_encoder_set_active_device(struct drm_encoder *encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct drm_connector *connector;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 | 
			
		||||
		if (connector->encoder == encoder) {
 | 
			
		||||
			struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 | 
			
		||||
			radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
 | 
			
		||||
			DRM_INFO("setting active device to %08x from %08x %08x for encoder %d\n",
 | 
			
		||||
				 radeon_encoder->active_device, radeon_encoder->devices,
 | 
			
		||||
				 radeon_connector->devices, encoder->encoder_type);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct drm_connector *
 | 
			
		||||
radeon_get_connector_for_encoder(struct drm_encoder *encoder)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -244,9 +261,9 @@ atombios_dac_setup(struct drm_encoder *encoder, int action)
 | 
			
		|||
 | 
			
		||||
	args.ucAction = action;
 | 
			
		||||
 | 
			
		||||
	if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
 | 
			
		||||
	if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
 | 
			
		||||
		args.ucDacStandard = ATOM_DAC1_PS2;
 | 
			
		||||
	else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
		args.ucDacStandard = ATOM_DAC1_CV;
 | 
			
		||||
	else {
 | 
			
		||||
		switch (tv_std) {
 | 
			
		||||
| 
						 | 
				
			
			@ -288,7 +305,7 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)
 | 
			
		|||
 | 
			
		||||
	args.sTVEncoder.ucAction = action;
 | 
			
		||||
 | 
			
		||||
	if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
 | 
			
		||||
	else {
 | 
			
		||||
		switch (tv_std) {
 | 
			
		||||
| 
						 | 
				
			
			@ -825,10 +842,10 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
 | 
			
		|||
 | 
			
		||||
	/* XXX: fix up scratch reg handling */
 | 
			
		||||
	temp = RREG32(reg);
 | 
			
		||||
	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
		WREG32(reg, (ATOM_S3_TV1_ACTIVE |
 | 
			
		||||
			     (radeon_crtc->crtc_id << 18)));
 | 
			
		||||
	else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
		WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
 | 
			
		||||
	else
 | 
			
		||||
		WREG32(reg, 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -851,9 +868,19 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
 | 
			
		|||
	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
 | 
			
		||||
	int index = 0;
 | 
			
		||||
	bool is_dig = false;
 | 
			
		||||
	int devices;
 | 
			
		||||
 | 
			
		||||
	memset(&args, 0, sizeof(args));
 | 
			
		||||
 | 
			
		||||
	/* on DPMS off we have no idea if active device is meaningful */
 | 
			
		||||
	if (mode != DRM_MODE_DPMS_ON && !radeon_encoder->active_device)
 | 
			
		||||
		devices = radeon_encoder->devices;
 | 
			
		||||
	else
 | 
			
		||||
		devices = radeon_encoder->active_device;
 | 
			
		||||
 | 
			
		||||
	DRM_INFO("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
 | 
			
		||||
		 radeon_encoder->encoder_id, mode, radeon_encoder->devices,
 | 
			
		||||
		radeon_encoder->active_device);
 | 
			
		||||
	switch (radeon_encoder->encoder_id) {
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
 | 
			
		||||
| 
						 | 
				
			
			@ -881,18 +908,18 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
 | 
			
		|||
		break;
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 | 
			
		||||
		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
		if (devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
 | 
			
		||||
		else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
		else if (devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
 | 
			
		||||
		else
 | 
			
		||||
			index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
 | 
			
		||||
		break;
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 | 
			
		||||
		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
		if (devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
			index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
 | 
			
		||||
		else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
		else if (devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
			index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
 | 
			
		||||
		else
 | 
			
		||||
			index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
 | 
			
		||||
| 
						 | 
				
			
			@ -979,18 +1006,18 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
 | 
			
		|||
				break;
 | 
			
		||||
			case ENCODER_OBJECT_ID_INTERNAL_DAC1:
 | 
			
		||||
			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 | 
			
		||||
				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
 | 
			
		||||
				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
 | 
			
		||||
				else
 | 
			
		||||
					args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
 | 
			
		||||
				break;
 | 
			
		||||
			case ENCODER_OBJECT_ID_INTERNAL_DAC2:
 | 
			
		||||
			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 | 
			
		||||
				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
					args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
 | 
			
		||||
				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
					args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
 | 
			
		||||
				else
 | 
			
		||||
					args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
 | 
			
		||||
| 
						 | 
				
			
			@ -1019,17 +1046,17 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
 | 
			
		|||
				args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
 | 
			
		||||
				break;
 | 
			
		||||
			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 | 
			
		||||
				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 | 
			
		||||
				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 | 
			
		||||
				else
 | 
			
		||||
					args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
 | 
			
		||||
				break;
 | 
			
		||||
			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 | 
			
		||||
				if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
				if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 | 
			
		||||
				else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
				else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
					args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
 | 
			
		||||
				else
 | 
			
		||||
					args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
 | 
			
		||||
| 
						 | 
				
			
			@ -1097,7 +1124,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 | 
			
		|||
	atombios_set_encoder_crtc_source(encoder);
 | 
			
		||||
 | 
			
		||||
	if (ASIC_IS_AVIVO(rdev)) {
 | 
			
		||||
		if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
			atombios_yuv_setup(encoder, true);
 | 
			
		||||
		else
 | 
			
		||||
			atombios_yuv_setup(encoder, false);
 | 
			
		||||
| 
						 | 
				
			
			@ -1135,7 +1162,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 | 
			
		|||
	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 | 
			
		||||
		atombios_dac_setup(encoder, ATOM_ENABLE);
 | 
			
		||||
		if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
		if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
 | 
			
		||||
			atombios_tv_setup(encoder, ATOM_ENABLE);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1143,11 +1170,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
atombios_dac_load_detect(struct drm_encoder *encoder)
 | 
			
		||||
atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 | 
			
		||||
 | 
			
		||||
	if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
 | 
			
		||||
				       ATOM_DEVICE_CV_SUPPORT |
 | 
			
		||||
| 
						 | 
				
			
			@ -1168,15 +1196,15 @@ atombios_dac_load_detect(struct drm_encoder *encoder)
 | 
			
		|||
		else
 | 
			
		||||
			args.sDacload.ucDacType = ATOM_DAC_B;
 | 
			
		||||
 | 
			
		||||
		if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT)
 | 
			
		||||
		if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
 | 
			
		||||
			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
 | 
			
		||||
		else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT)
 | 
			
		||||
		else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
 | 
			
		||||
			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
 | 
			
		||||
		else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
 | 
			
		||||
		else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
 | 
			
		||||
			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
 | 
			
		||||
			if (crev >= 3)
 | 
			
		||||
				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
 | 
			
		||||
		} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
 | 
			
		||||
		} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
 | 
			
		||||
			args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
 | 
			
		||||
			if (crev >= 3)
 | 
			
		||||
				args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
 | 
			
		||||
| 
						 | 
				
			
			@ -1195,9 +1223,10 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
 | 
			
		|||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 | 
			
		||||
	uint32_t bios_0_scratch;
 | 
			
		||||
 | 
			
		||||
	if (!atombios_dac_load_detect(encoder)) {
 | 
			
		||||
	if (!atombios_dac_load_detect(encoder, connector)) {
 | 
			
		||||
		DRM_DEBUG("detect returned false \n");
 | 
			
		||||
		return connector_status_unknown;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1207,17 +1236,20 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
 | 
			
		|||
	else
 | 
			
		||||
		bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
 | 
			
		||||
 | 
			
		||||
	DRM_DEBUG("Bios 0 scratch %x\n", bios_0_scratch);
 | 
			
		||||
	if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
 | 
			
		||||
	DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
 | 
			
		||||
	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
 | 
			
		||||
		if (bios_0_scratch & ATOM_S0_CRT1_MASK)
 | 
			
		||||
			return connector_status_connected;
 | 
			
		||||
	} else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
 | 
			
		||||
	}
 | 
			
		||||
	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
 | 
			
		||||
		if (bios_0_scratch & ATOM_S0_CRT2_MASK)
 | 
			
		||||
			return connector_status_connected;
 | 
			
		||||
	} else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
 | 
			
		||||
	}
 | 
			
		||||
	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
 | 
			
		||||
		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
 | 
			
		||||
			return connector_status_connected;
 | 
			
		||||
	} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
 | 
			
		||||
	}
 | 
			
		||||
	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
 | 
			
		||||
		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
 | 
			
		||||
			return connector_status_connected; /* CTV */
 | 
			
		||||
		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
 | 
			
		||||
| 
						 | 
				
			
			@ -1230,6 +1262,8 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 | 
			
		|||
{
 | 
			
		||||
	radeon_atom_output_lock(encoder, true);
 | 
			
		||||
	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
 | 
			
		||||
	radeon_encoder_set_active_device(encoder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
 | 
			
		||||
| 
						 | 
				
			
			@ -1238,12 +1272,21 @@ static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
 | 
			
		|||
	radeon_atom_output_lock(encoder, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
	DRM_INFO("setting active device to 0 for encoder %d\n", encoder->encoder_type);
 | 
			
		||||
	radeon_encoder->active_device = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
 | 
			
		||||
	.dpms = radeon_atom_encoder_dpms,
 | 
			
		||||
	.mode_fixup = radeon_atom_mode_fixup,
 | 
			
		||||
	.prepare = radeon_atom_encoder_prepare,
 | 
			
		||||
	.mode_set = radeon_atom_encoder_mode_set,
 | 
			
		||||
	.commit = radeon_atom_encoder_commit,
 | 
			
		||||
	.disable = radeon_atom_encoder_disable,
 | 
			
		||||
	/* no detect for TMDS/LVDS yet */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1268,6 +1311,18 @@ static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
 | 
			
		|||
	.destroy = radeon_enc_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct radeon_encoder_atom_dac *
 | 
			
		||||
radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
 | 
			
		||||
 | 
			
		||||
	if (!dac)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	dac->tv_std = TV_STD_NTSC;
 | 
			
		||||
	return dac;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct radeon_encoder_atom_dig *
 | 
			
		||||
radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1336,6 +1391,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
 | 
			
		|||
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
 | 
			
		||||
		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
 | 
			
		||||
		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
 | 
			
		||||
		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
 | 
			
		||||
		break;
 | 
			
		||||
	case ENCODER_OBJECT_ID_INTERNAL_DVO1:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,7 @@
 | 
			
		|||
#include <drm/radeon_drm.h>
 | 
			
		||||
#include "radeon_fixed.h"
 | 
			
		||||
#include "radeon.h"
 | 
			
		||||
#include "atom.h"
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
 | 
			
		||||
				       struct drm_display_mode *mode,
 | 
			
		||||
| 
						 | 
				
			
			@ -501,6 +502,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
 | 
			
		|||
	struct drm_device *dev = crtc->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 | 
			
		||||
	struct drm_encoder *encoder;
 | 
			
		||||
	int format;
 | 
			
		||||
	int hsync_start;
 | 
			
		||||
	int hsync_wid;
 | 
			
		||||
| 
						 | 
				
			
			@ -509,8 +511,19 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
 | 
			
		|||
	uint32_t crtc_h_sync_strt_wid;
 | 
			
		||||
	uint32_t crtc_v_total_disp;
 | 
			
		||||
	uint32_t crtc_v_sync_strt_wid;
 | 
			
		||||
	bool is_tv = false;
 | 
			
		||||
 | 
			
		||||
	DRM_DEBUG("\n");
 | 
			
		||||
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 | 
			
		||||
		if (encoder->crtc == crtc) {
 | 
			
		||||
			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
			if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
 | 
			
		||||
				is_tv = true;
 | 
			
		||||
				DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (crtc->fb->bits_per_pixel) {
 | 
			
		||||
	case 15:      /*  555 */
 | 
			
		||||
| 
						 | 
				
			
			@ -642,6 +655,11 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
 | 
			
		|||
		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (is_tv)
 | 
			
		||||
		radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp,
 | 
			
		||||
						 &crtc_h_sync_strt_wid, &crtc_v_total_disp,
 | 
			
		||||
						 &crtc_v_sync_strt_wid);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp);
 | 
			
		||||
	WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid);
 | 
			
		||||
	WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp);
 | 
			
		||||
| 
						 | 
				
			
			@ -668,7 +686,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 | 
			
		|||
	uint32_t pll_ref_div = 0;
 | 
			
		||||
	uint32_t pll_fb_post_div = 0;
 | 
			
		||||
	uint32_t htotal_cntl = 0;
 | 
			
		||||
 | 
			
		||||
	bool is_tv = false;
 | 
			
		||||
	struct radeon_pll *pll;
 | 
			
		||||
 | 
			
		||||
	struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -703,6 +721,13 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 | 
			
		|||
 | 
			
		||||
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 | 
			
		||||
		if (encoder->crtc == crtc) {
 | 
			
		||||
			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
 | 
			
		||||
			if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
 | 
			
		||||
				is_tv = true;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
 | 
			
		||||
				pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
 | 
			
		||||
			if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
 | 
			
		||||
| 
						 | 
				
			
			@ -766,6 +791,12 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 | 
			
		|||
					  ~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
 | 
			
		||||
					 RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
 | 
			
		||||
 | 
			
		||||
		if (is_tv) {
 | 
			
		||||
			radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl,
 | 
			
		||||
						     &pll_ref_div, &pll_fb_post_div,
 | 
			
		||||
						     &pixclks_cntl);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
 | 
			
		||||
			     RADEON_PIX2CLK_SRC_SEL_CPUCLK,
 | 
			
		||||
			     ~(RADEON_PIX2CLK_SRC_SEL_MASK));
 | 
			
		||||
| 
						 | 
				
			
			@ -820,6 +851,15 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 | 
			
		|||
 | 
			
		||||
		WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 | 
			
		||||
	} else {
 | 
			
		||||
		uint32_t pixclks_cntl;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		if (is_tv) {
 | 
			
		||||
			pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
 | 
			
		||||
			radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div,
 | 
			
		||||
						     &pll_fb_post_div, &pixclks_cntl);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (rdev->flags & RADEON_IS_MOBILITY) {
 | 
			
		||||
			/* A temporal workaround for the occational blanking on certain laptop panels.
 | 
			
		||||
			   This appears to related to the PLL divider registers (fail to lock?).
 | 
			
		||||
| 
						 | 
				
			
			@ -914,6 +954,8 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 | 
			
		|||
			     RADEON_VCLK_SRC_SEL_PPLLCLK,
 | 
			
		||||
			     ~(RADEON_VCLK_SRC_SEL_MASK));
 | 
			
		||||
 | 
			
		||||
		if (is_tv)
 | 
			
		||||
			WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,15 @@
 | 
			
		|||
#include "radeon.h"
 | 
			
		||||
#include "atom.h"
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct drm_encoder_helper_funcs *encoder_funcs;
 | 
			
		||||
 | 
			
		||||
	encoder_funcs = encoder->helper_private;
 | 
			
		||||
	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
	radeon_encoder->active_device = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -98,6 +107,8 @@ static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
 | 
			
		|||
	else
 | 
			
		||||
		radeon_combios_output_lock(encoder, true);
 | 
			
		||||
	radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
 | 
			
		||||
	radeon_encoder_set_active_device(encoder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
 | 
			
		||||
| 
						 | 
				
			
			@ -195,6 +206,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
 | 
			
		|||
	.prepare = radeon_legacy_lvds_prepare,
 | 
			
		||||
	.mode_set = radeon_legacy_lvds_mode_set,
 | 
			
		||||
	.commit = radeon_legacy_lvds_commit,
 | 
			
		||||
	.disable = radeon_legacy_encoder_disable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -260,6 +272,7 @@ static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
 | 
			
		|||
	else
 | 
			
		||||
		radeon_combios_output_lock(encoder, true);
 | 
			
		||||
	radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
	radeon_encoder_set_active_device(encoder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
 | 
			
		||||
| 
						 | 
				
			
			@ -402,6 +415,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_fu
 | 
			
		|||
	.mode_set = radeon_legacy_primary_dac_mode_set,
 | 
			
		||||
	.commit = radeon_legacy_primary_dac_commit,
 | 
			
		||||
	.detect = radeon_legacy_primary_dac_detect,
 | 
			
		||||
	.disable = radeon_legacy_encoder_disable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -454,6 +468,7 @@ static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
 | 
			
		|||
	else
 | 
			
		||||
		radeon_combios_output_lock(encoder, true);
 | 
			
		||||
	radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
	radeon_encoder_set_active_device(encoder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
 | 
			
		||||
| 
						 | 
				
			
			@ -566,6 +581,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs
 | 
			
		|||
	.prepare = radeon_legacy_tmds_int_prepare,
 | 
			
		||||
	.mode_set = radeon_legacy_tmds_int_mode_set,
 | 
			
		||||
	.commit = radeon_legacy_tmds_int_commit,
 | 
			
		||||
	.disable = radeon_legacy_encoder_disable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -620,6 +636,7 @@ static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
 | 
			
		|||
	else
 | 
			
		||||
		radeon_combios_output_lock(encoder, true);
 | 
			
		||||
	radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
	radeon_encoder_set_active_device(encoder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
 | 
			
		||||
| 
						 | 
				
			
			@ -706,6 +723,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs
 | 
			
		|||
	.prepare = radeon_legacy_tmds_ext_prepare,
 | 
			
		||||
	.mode_set = radeon_legacy_tmds_ext_mode_set,
 | 
			
		||||
	.commit = radeon_legacy_tmds_ext_commit,
 | 
			
		||||
	.disable = radeon_legacy_encoder_disable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -727,17 +745,21 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
 | 
			
		|||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
 | 
			
		||||
	/* uint32_t tv_master_cntl = 0; */
 | 
			
		||||
 | 
			
		||||
	uint32_t tv_master_cntl = 0;
 | 
			
		||||
	bool is_tv;
 | 
			
		||||
	DRM_DEBUG("\n");
 | 
			
		||||
 | 
			
		||||
	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
 | 
			
		||||
 | 
			
		||||
	if (rdev->family == CHIP_R200)
 | 
			
		||||
		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
 | 
			
		||||
	else {
 | 
			
		||||
		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
 | 
			
		||||
		/*  FIXME TV */
 | 
			
		||||
		/* tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); */
 | 
			
		||||
		if (is_tv)
 | 
			
		||||
			tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
 | 
			
		||||
		else
 | 
			
		||||
			crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
 | 
			
		||||
		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -746,20 +768,23 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
 | 
			
		|||
		if (rdev->family == CHIP_R200) {
 | 
			
		||||
			fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
 | 
			
		||||
		} else {
 | 
			
		||||
			crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
 | 
			
		||||
			/* tv_master_cntl |= RADEON_TV_ON; */
 | 
			
		||||
			if (is_tv)
 | 
			
		||||
				tv_master_cntl |= RADEON_TV_ON;
 | 
			
		||||
			else
 | 
			
		||||
				crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
 | 
			
		||||
 | 
			
		||||
			if (rdev->family == CHIP_R420 ||
 | 
			
		||||
					rdev->family == CHIP_R423 ||
 | 
			
		||||
					rdev->family == CHIP_RV410)
 | 
			
		||||
			    rdev->family == CHIP_R423 ||
 | 
			
		||||
			    rdev->family == CHIP_RV410)
 | 
			
		||||
				tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
 | 
			
		||||
						R420_TV_DAC_GDACPD |
 | 
			
		||||
						R420_TV_DAC_BDACPD |
 | 
			
		||||
						RADEON_TV_DAC_BGSLEEP);
 | 
			
		||||
						 R420_TV_DAC_GDACPD |
 | 
			
		||||
						 R420_TV_DAC_BDACPD |
 | 
			
		||||
						 RADEON_TV_DAC_BGSLEEP);
 | 
			
		||||
			else
 | 
			
		||||
				tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
 | 
			
		||||
						RADEON_TV_DAC_GDACPD |
 | 
			
		||||
						RADEON_TV_DAC_BDACPD |
 | 
			
		||||
						RADEON_TV_DAC_BGSLEEP);
 | 
			
		||||
						 RADEON_TV_DAC_GDACPD |
 | 
			
		||||
						 RADEON_TV_DAC_BDACPD |
 | 
			
		||||
						 RADEON_TV_DAC_BGSLEEP);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case DRM_MODE_DPMS_STANDBY:
 | 
			
		||||
| 
						 | 
				
			
			@ -768,8 +793,11 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
 | 
			
		|||
		if (rdev->family == CHIP_R200)
 | 
			
		||||
			fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
 | 
			
		||||
		else {
 | 
			
		||||
			crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
 | 
			
		||||
			/* tv_master_cntl &= ~RADEON_TV_ON; */
 | 
			
		||||
			if (is_tv)
 | 
			
		||||
				tv_master_cntl &= ~RADEON_TV_ON;
 | 
			
		||||
			else
 | 
			
		||||
				crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
 | 
			
		||||
 | 
			
		||||
			if (rdev->family == CHIP_R420 ||
 | 
			
		||||
					rdev->family == CHIP_R423 ||
 | 
			
		||||
					rdev->family == CHIP_RV410)
 | 
			
		||||
| 
						 | 
				
			
			@ -789,8 +817,10 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
 | 
			
		|||
	if (rdev->family == CHIP_R200) {
 | 
			
		||||
		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 | 
			
		||||
	} else {
 | 
			
		||||
		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
 | 
			
		||||
		/* WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); */
 | 
			
		||||
		if (is_tv)
 | 
			
		||||
			WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
 | 
			
		||||
		else
 | 
			
		||||
			WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
 | 
			
		||||
		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -809,6 +839,7 @@ static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
 | 
			
		|||
	else
 | 
			
		||||
		radeon_combios_output_lock(encoder, true);
 | 
			
		||||
	radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
 | 
			
		||||
	radeon_encoder_set_active_device(encoder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
 | 
			
		||||
| 
						 | 
				
			
			@ -831,11 +862,15 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
 | 
			
		|||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
	uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
 | 
			
		||||
	uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0;
 | 
			
		||||
	uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0;
 | 
			
		||||
	bool is_tv = false;
 | 
			
		||||
 | 
			
		||||
	DRM_DEBUG("\n");
 | 
			
		||||
 | 
			
		||||
	is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
 | 
			
		||||
 | 
			
		||||
	if (rdev->family != CHIP_R200) {
 | 
			
		||||
		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
		if (rdev->family == CHIP_R420 ||
 | 
			
		||||
| 
						 | 
				
			
			@ -858,7 +893,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		/*  FIXME TV */
 | 
			
		||||
		if (radeon_encoder->enc_priv) {
 | 
			
		||||
		if (tv_dac) {
 | 
			
		||||
			struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
			tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
 | 
			
		||||
					RADEON_TV_DAC_NHOLD |
 | 
			
		||||
| 
						 | 
				
			
			@ -875,44 +910,93 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
 | 
			
		|||
	if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
		gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
 | 
			
		||||
		disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
 | 
			
		||||
	} else if (rdev->family == CHIP_R200)
 | 
			
		||||
		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev))
 | 
			
		||||
		disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
 | 
			
		||||
	else
 | 
			
		||||
		disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
 | 
			
		||||
 | 
			
		||||
	dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
 | 
			
		||||
	if (rdev->family == CHIP_R200)
 | 
			
		||||
		fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
 | 
			
		||||
 | 
			
		||||
	if (radeon_crtc->crtc_id == 0) {
 | 
			
		||||
		if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
			disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
 | 
			
		||||
			disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
 | 
			
		||||
		} else if (rdev->family == CHIP_R200) {
 | 
			
		||||
			fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
 | 
			
		||||
					  RADEON_FP2_DVO_RATE_SEL_SDR);
 | 
			
		||||
		} else
 | 
			
		||||
			disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
 | 
			
		||||
	if (is_tv) {
 | 
			
		||||
		uint32_t dac_cntl;
 | 
			
		||||
 | 
			
		||||
		dac_cntl = RREG32(RADEON_DAC_CNTL);
 | 
			
		||||
		dac_cntl &= ~RADEON_DAC_TVO_EN;
 | 
			
		||||
		WREG32(RADEON_DAC_CNTL, dac_cntl);
 | 
			
		||||
 | 
			
		||||
		if (ASIC_IS_R300(rdev))
 | 
			
		||||
			gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1;
 | 
			
		||||
 | 
			
		||||
		dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL;
 | 
			
		||||
		if (radeon_crtc->crtc_id == 0) {
 | 
			
		||||
			if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
 | 
			
		||||
				disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC |
 | 
			
		||||
						     RADEON_DISP_TV_SOURCE_CRTC);
 | 
			
		||||
			}
 | 
			
		||||
			if (rdev->family >= CHIP_R200) {
 | 
			
		||||
				disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
 | 
			
		||||
			} else {
 | 
			
		||||
				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
 | 
			
		||||
				disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
 | 
			
		||||
			}
 | 
			
		||||
			if (rdev->family >= CHIP_R200) {
 | 
			
		||||
				disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
 | 
			
		||||
			} else {
 | 
			
		||||
				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
			disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
 | 
			
		||||
			disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
 | 
			
		||||
		} else if (rdev->family == CHIP_R200) {
 | 
			
		||||
			fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
 | 
			
		||||
					  RADEON_FP2_DVO_RATE_SEL_SDR);
 | 
			
		||||
			fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
 | 
			
		||||
		} else
 | 
			
		||||
			disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_DAC_CNTL2, dac2_cntl);
 | 
			
		||||
		dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
 | 
			
		||||
 | 
			
		||||
		if (radeon_crtc->crtc_id == 0) {
 | 
			
		||||
			if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
 | 
			
		||||
				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
 | 
			
		||||
			} else if (rdev->family == CHIP_R200) {
 | 
			
		||||
				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
 | 
			
		||||
						  RADEON_FP2_DVO_RATE_SEL_SDR);
 | 
			
		||||
			} else
 | 
			
		||||
				disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
				disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
 | 
			
		||||
				disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
 | 
			
		||||
			} else if (rdev->family == CHIP_R200) {
 | 
			
		||||
				fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
 | 
			
		||||
						  RADEON_FP2_DVO_RATE_SEL_SDR);
 | 
			
		||||
				fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
 | 
			
		||||
			} else
 | 
			
		||||
				disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
 | 
			
		||||
		}
 | 
			
		||||
		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ASIC_IS_R300(rdev)) {
 | 
			
		||||
		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
 | 
			
		||||
		WREG32(RADEON_DISP_TV_OUT_CNTL, disp_output_cntl);
 | 
			
		||||
	} else if (rdev->family == CHIP_R200)
 | 
			
		||||
		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 | 
			
		||||
		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rdev->family >= CHIP_R200)
 | 
			
		||||
		WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
 | 
			
		||||
	else
 | 
			
		||||
		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
 | 
			
		||||
 | 
			
		||||
	if (rdev->family == CHIP_R200)
 | 
			
		||||
		WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 | 
			
		||||
 | 
			
		||||
	if (is_tv)
 | 
			
		||||
		radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
 | 
			
		||||
 | 
			
		||||
	if (rdev->is_atom_bios)
 | 
			
		||||
		radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
 | 
			
		||||
	else
 | 
			
		||||
| 
						 | 
				
			
			@ -920,6 +1004,141 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool r300_legacy_tv_detect(struct drm_encoder *encoder,
 | 
			
		||||
				  struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
 | 
			
		||||
	uint32_t disp_output_cntl, gpiopad_a, tmp;
 | 
			
		||||
	bool found = false;
 | 
			
		||||
 | 
			
		||||
	/* save regs needed */
 | 
			
		||||
	gpiopad_a = RREG32(RADEON_GPIOPAD_A);
 | 
			
		||||
	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
 | 
			
		||||
	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
 | 
			
		||||
	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
 | 
			
		||||
	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
 | 
			
		||||
 | 
			
		||||
	WREG32_P(RADEON_GPIOPAD_A, 0, ~1);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_CRTC2_GEN_CNTL,
 | 
			
		||||
	       RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
 | 
			
		||||
 | 
			
		||||
	tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
 | 
			
		||||
	tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
 | 
			
		||||
	WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_DAC_EXT_CNTL,
 | 
			
		||||
	       RADEON_DAC2_FORCE_BLANK_OFF_EN |
 | 
			
		||||
	       RADEON_DAC2_FORCE_DATA_EN |
 | 
			
		||||
	       RADEON_DAC_FORCE_DATA_SEL_RGB |
 | 
			
		||||
	       (0xec << RADEON_DAC_FORCE_DATA_SHIFT));
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_DAC_CNTL,
 | 
			
		||||
	       RADEON_TV_DAC_STD_NTSC |
 | 
			
		||||
	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
 | 
			
		||||
	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
 | 
			
		||||
 | 
			
		||||
	RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	mdelay(4);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_DAC_CNTL,
 | 
			
		||||
	       RADEON_TV_DAC_NBLANK |
 | 
			
		||||
	       RADEON_TV_DAC_NHOLD |
 | 
			
		||||
	       RADEON_TV_MONITOR_DETECT_EN |
 | 
			
		||||
	       RADEON_TV_DAC_STD_NTSC |
 | 
			
		||||
	       (8 << RADEON_TV_DAC_BGADJ_SHIFT) |
 | 
			
		||||
	       (6 << RADEON_TV_DAC_DACADJ_SHIFT));
 | 
			
		||||
 | 
			
		||||
	RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	mdelay(6);
 | 
			
		||||
 | 
			
		||||
	tmp = RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
 | 
			
		||||
		found = true;
 | 
			
		||||
		DRM_DEBUG("S-video TV connection detected\n");
 | 
			
		||||
	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
 | 
			
		||||
		found = true;
 | 
			
		||||
		DRM_DEBUG("Composite TV connection detected\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
 | 
			
		||||
	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
 | 
			
		||||
	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
 | 
			
		||||
	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
 | 
			
		||||
	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
 | 
			
		||||
	WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
 | 
			
		||||
	return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
 | 
			
		||||
				    struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	uint32_t tv_dac_cntl, dac_cntl2;
 | 
			
		||||
	uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp;
 | 
			
		||||
	bool found = false;
 | 
			
		||||
 | 
			
		||||
	if (ASIC_IS_R300(rdev))
 | 
			
		||||
		return r300_legacy_tv_detect(encoder, connector);
 | 
			
		||||
 | 
			
		||||
	dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
 | 
			
		||||
	tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
 | 
			
		||||
	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	config_cntl = RREG32(RADEON_CONFIG_CNTL);
 | 
			
		||||
	tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL);
 | 
			
		||||
 | 
			
		||||
	tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
 | 
			
		||||
	WREG32(RADEON_DAC_CNTL2, tmp);
 | 
			
		||||
 | 
			
		||||
	tmp = tv_master_cntl | RADEON_TV_ON;
 | 
			
		||||
	tmp &= ~(RADEON_TV_ASYNC_RST |
 | 
			
		||||
		 RADEON_RESTART_PHASE_FIX |
 | 
			
		||||
		 RADEON_CRT_FIFO_CE_EN |
 | 
			
		||||
		 RADEON_TV_FIFO_CE_EN |
 | 
			
		||||
		 RADEON_RE_SYNC_NOW_SEL_MASK);
 | 
			
		||||
	tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
 | 
			
		||||
	WREG32(RADEON_TV_MASTER_CNTL, tmp);
 | 
			
		||||
 | 
			
		||||
	tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
 | 
			
		||||
		RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
 | 
			
		||||
		(8 << RADEON_TV_DAC_BGADJ_SHIFT);
 | 
			
		||||
 | 
			
		||||
	if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
 | 
			
		||||
		tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
 | 
			
		||||
	else
 | 
			
		||||
		tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
 | 
			
		||||
	WREG32(RADEON_TV_DAC_CNTL, tmp);
 | 
			
		||||
 | 
			
		||||
	tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
 | 
			
		||||
		RADEON_RED_MX_FORCE_DAC_DATA |
 | 
			
		||||
		RADEON_GRN_MX_FORCE_DAC_DATA |
 | 
			
		||||
		RADEON_BLU_MX_FORCE_DAC_DATA |
 | 
			
		||||
		(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
 | 
			
		||||
	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
 | 
			
		||||
 | 
			
		||||
	mdelay(3);
 | 
			
		||||
	tmp = RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	if (tmp & RADEON_TV_DAC_GDACDET) {
 | 
			
		||||
		found = true;
 | 
			
		||||
		DRM_DEBUG("S-video TV connection detected\n");
 | 
			
		||||
	} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
 | 
			
		||||
		found = true;
 | 
			
		||||
		DRM_DEBUG("Composite TV connection detected\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
 | 
			
		||||
	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
 | 
			
		||||
	WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
 | 
			
		||||
	WREG32(RADEON_DAC_CNTL2, dac_cntl2);
 | 
			
		||||
	return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
 | 
			
		||||
							     struct drm_connector *connector)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -928,9 +1147,29 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
 | 
			
		|||
	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
 | 
			
		||||
	uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
 | 
			
		||||
	enum drm_connector_status found = connector_status_disconnected;
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
	bool color = true;
 | 
			
		||||
 | 
			
		||||
	/*  FIXME tv */
 | 
			
		||||
	if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
 | 
			
		||||
	    connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
 | 
			
		||||
	    connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) {
 | 
			
		||||
		bool tv_detect;
 | 
			
		||||
 | 
			
		||||
		if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT))
 | 
			
		||||
			return connector_status_disconnected;
 | 
			
		||||
 | 
			
		||||
		tv_detect = radeon_legacy_tv_detect(encoder, connector);
 | 
			
		||||
		if (tv_detect && tv_dac)
 | 
			
		||||
			found = connector_status_connected;
 | 
			
		||||
		return found;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* don't probe if the encoder is being used for something else not CRT related */
 | 
			
		||||
	if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) {
 | 
			
		||||
		DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device);
 | 
			
		||||
		return connector_status_disconnected;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* save the regs we need */
 | 
			
		||||
	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
 | 
			
		||||
| 
						 | 
				
			
			@ -1013,8 +1252,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
 | 
			
		|||
	}
 | 
			
		||||
	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 | 
			
		||||
 | 
			
		||||
	/* return found; */
 | 
			
		||||
	return connector_status_disconnected;
 | 
			
		||||
	return found;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1025,6 +1263,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs =
 | 
			
		|||
	.mode_set = radeon_legacy_tv_dac_mode_set,
 | 
			
		||||
	.commit = radeon_legacy_tv_dac_commit,
 | 
			
		||||
	.detect = radeon_legacy_tv_dac_detect,
 | 
			
		||||
	.disable = radeon_legacy_encoder_disable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										904
									
								
								drivers/gpu/drm/radeon/radeon_legacy_tv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										904
									
								
								drivers/gpu/drm/radeon/radeon_legacy_tv.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,904 @@
 | 
			
		|||
#include "drmP.h"
 | 
			
		||||
#include "drm_crtc_helper.h"
 | 
			
		||||
#include "radeon.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Integrated TV out support based on the GATOS code by
 | 
			
		||||
 * Federico Ulivi <fulivi@lycos.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Limits of h/v positions (hPos & vPos)
 | 
			
		||||
 */
 | 
			
		||||
#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */
 | 
			
		||||
#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Unit for hPos (in TV clock periods)
 | 
			
		||||
 */
 | 
			
		||||
#define H_POS_UNIT 10
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Indexes in h. code timing table for horizontal line position adjustment
 | 
			
		||||
 */
 | 
			
		||||
#define H_TABLE_POS1 6
 | 
			
		||||
#define H_TABLE_POS2 8
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Limits of hor. size (hSize)
 | 
			
		||||
 */
 | 
			
		||||
#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */
 | 
			
		||||
 | 
			
		||||
/* tv standard constants */
 | 
			
		||||
#define NTSC_TV_CLOCK_T 233
 | 
			
		||||
#define NTSC_TV_VFTOTAL 1
 | 
			
		||||
#define NTSC_TV_LINES_PER_FRAME 525
 | 
			
		||||
#define NTSC_TV_ZERO_H_SIZE 479166
 | 
			
		||||
#define NTSC_TV_H_SIZE_UNIT 9478
 | 
			
		||||
 | 
			
		||||
#define PAL_TV_CLOCK_T 188
 | 
			
		||||
#define PAL_TV_VFTOTAL 3
 | 
			
		||||
#define PAL_TV_LINES_PER_FRAME 625
 | 
			
		||||
#define PAL_TV_ZERO_H_SIZE 473200
 | 
			
		||||
#define PAL_TV_H_SIZE_UNIT 9360
 | 
			
		||||
 | 
			
		||||
/* tv pll setting for 27 mhz ref clk */
 | 
			
		||||
#define NTSC_TV_PLL_M_27 22
 | 
			
		||||
#define NTSC_TV_PLL_N_27 175
 | 
			
		||||
#define NTSC_TV_PLL_P_27 5
 | 
			
		||||
 | 
			
		||||
#define PAL_TV_PLL_M_27 113
 | 
			
		||||
#define PAL_TV_PLL_N_27 668
 | 
			
		||||
#define PAL_TV_PLL_P_27 3
 | 
			
		||||
 | 
			
		||||
/* tv pll setting for 14 mhz ref clk */
 | 
			
		||||
#define NTSC_TV_PLL_M_14 33
 | 
			
		||||
#define NTSC_TV_PLL_N_14 693
 | 
			
		||||
#define NTSC_TV_PLL_P_14 7
 | 
			
		||||
 | 
			
		||||
#define VERT_LEAD_IN_LINES 2
 | 
			
		||||
#define FRAC_BITS 0xe
 | 
			
		||||
#define FRAC_MASK 0x3fff
 | 
			
		||||
 | 
			
		||||
struct radeon_tv_mode_constants {
 | 
			
		||||
	uint16_t hor_resolution;
 | 
			
		||||
	uint16_t ver_resolution;
 | 
			
		||||
	enum radeon_tv_std standard;
 | 
			
		||||
	uint16_t hor_total;
 | 
			
		||||
	uint16_t ver_total;
 | 
			
		||||
	uint16_t hor_start;
 | 
			
		||||
	uint16_t hor_syncstart;
 | 
			
		||||
	uint16_t ver_syncstart;
 | 
			
		||||
	unsigned def_restart;
 | 
			
		||||
	uint16_t crtcPLL_N;
 | 
			
		||||
	uint8_t  crtcPLL_M;
 | 
			
		||||
	uint8_t  crtcPLL_post_div;
 | 
			
		||||
	unsigned pix_to_tv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint16_t hor_timing_NTSC[] = {
 | 
			
		||||
	0x0007,
 | 
			
		||||
	0x003f,
 | 
			
		||||
	0x0263,
 | 
			
		||||
	0x0a24,
 | 
			
		||||
	0x2a6b,
 | 
			
		||||
	0x0a36,
 | 
			
		||||
	0x126d, /* H_TABLE_POS1 */
 | 
			
		||||
	0x1bfe,
 | 
			
		||||
	0x1a8f, /* H_TABLE_POS2 */
 | 
			
		||||
	0x1ec7,
 | 
			
		||||
	0x3863,
 | 
			
		||||
	0x1bfe,
 | 
			
		||||
	0x1bfe,
 | 
			
		||||
	0x1a2a,
 | 
			
		||||
	0x1e95,
 | 
			
		||||
	0x0e31,
 | 
			
		||||
	0x201b,
 | 
			
		||||
	0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint16_t vert_timing_NTSC[] = {
 | 
			
		||||
	0x2001,
 | 
			
		||||
	0x200d,
 | 
			
		||||
	0x1006,
 | 
			
		||||
	0x0c06,
 | 
			
		||||
	0x1006,
 | 
			
		||||
	0x1818,
 | 
			
		||||
	0x21e3,
 | 
			
		||||
	0x1006,
 | 
			
		||||
	0x0c06,
 | 
			
		||||
	0x1006,
 | 
			
		||||
	0x1817,
 | 
			
		||||
	0x21d4,
 | 
			
		||||
	0x0002,
 | 
			
		||||
	0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint16_t hor_timing_PAL[] = {
 | 
			
		||||
	0x0007,
 | 
			
		||||
	0x0058,
 | 
			
		||||
	0x027c,
 | 
			
		||||
	0x0a31,
 | 
			
		||||
	0x2a77,
 | 
			
		||||
	0x0a95,
 | 
			
		||||
	0x124f, /* H_TABLE_POS1 */
 | 
			
		||||
	0x1bfe,
 | 
			
		||||
	0x1b22, /* H_TABLE_POS2 */
 | 
			
		||||
	0x1ef9,
 | 
			
		||||
	0x387c,
 | 
			
		||||
	0x1bfe,
 | 
			
		||||
	0x1bfe,
 | 
			
		||||
	0x1b31,
 | 
			
		||||
	0x1eb5,
 | 
			
		||||
	0x0e43,
 | 
			
		||||
	0x201b,
 | 
			
		||||
	0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint16_t vert_timing_PAL[] = 	{
 | 
			
		||||
	0x2001,
 | 
			
		||||
	0x200c,
 | 
			
		||||
	0x1005,
 | 
			
		||||
	0x0c05,
 | 
			
		||||
	0x1005,
 | 
			
		||||
	0x1401,
 | 
			
		||||
	0x1821,
 | 
			
		||||
	0x2240,
 | 
			
		||||
	0x1005,
 | 
			
		||||
	0x0c05,
 | 
			
		||||
	0x1005,
 | 
			
		||||
	0x1401,
 | 
			
		||||
	0x1822,
 | 
			
		||||
	0x2230,
 | 
			
		||||
	0x0002,
 | 
			
		||||
	0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**********************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 * availableModes
 | 
			
		||||
 *
 | 
			
		||||
 * Table of all allowed modes for tv output
 | 
			
		||||
 *
 | 
			
		||||
 **********************************************************************/
 | 
			
		||||
static const struct radeon_tv_mode_constants available_tv_modes[] = {
 | 
			
		||||
	{   /* NTSC timing for 27 Mhz ref clk */
 | 
			
		||||
		800,                /* horResolution */
 | 
			
		||||
		600,                /* verResolution */
 | 
			
		||||
		TV_STD_NTSC,        /* standard */
 | 
			
		||||
		990,                /* horTotal */
 | 
			
		||||
		740,                /* verTotal */
 | 
			
		||||
		813,                /* horStart */
 | 
			
		||||
		824,                /* horSyncStart */
 | 
			
		||||
		632,                /* verSyncStart */
 | 
			
		||||
		625592,             /* defRestart */
 | 
			
		||||
		592,                /* crtcPLL_N */
 | 
			
		||||
		91,                 /* crtcPLL_M */
 | 
			
		||||
		4,                  /* crtcPLL_postDiv */
 | 
			
		||||
		1022,               /* pixToTV */
 | 
			
		||||
	},
 | 
			
		||||
	{   /* PAL timing for 27 Mhz ref clk */
 | 
			
		||||
		800,               /* horResolution */
 | 
			
		||||
		600,               /* verResolution */
 | 
			
		||||
		TV_STD_PAL,        /* standard */
 | 
			
		||||
		1144,              /* horTotal */
 | 
			
		||||
		706,               /* verTotal */
 | 
			
		||||
		812,               /* horStart */
 | 
			
		||||
		824,               /* horSyncStart */
 | 
			
		||||
		669,               /* verSyncStart */
 | 
			
		||||
		696700,            /* defRestart */
 | 
			
		||||
		1382,              /* crtcPLL_N */
 | 
			
		||||
		231,               /* crtcPLL_M */
 | 
			
		||||
		4,                 /* crtcPLL_postDiv */
 | 
			
		||||
		759,               /* pixToTV */
 | 
			
		||||
	},
 | 
			
		||||
	{   /* NTSC timing for 14 Mhz ref clk */
 | 
			
		||||
		800,                /* horResolution */
 | 
			
		||||
		600,                /* verResolution */
 | 
			
		||||
		TV_STD_NTSC,        /* standard */
 | 
			
		||||
		1018,               /* horTotal */
 | 
			
		||||
		727,                /* verTotal */
 | 
			
		||||
		813,                /* horStart */
 | 
			
		||||
		840,                /* horSyncStart */
 | 
			
		||||
		633,                /* verSyncStart */
 | 
			
		||||
		630627,             /* defRestart */
 | 
			
		||||
		347,                /* crtcPLL_N */
 | 
			
		||||
		14,                 /* crtcPLL_M */
 | 
			
		||||
			8,                  /* crtcPLL_postDiv */
 | 
			
		||||
		1022,               /* pixToTV */
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
 | 
			
		||||
 | 
			
		||||
static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder,
 | 
			
		||||
									    uint16_t *pll_ref_freq)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = radeon_encoder->base.dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_crtc *radeon_crtc;
 | 
			
		||||
	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
	const struct radeon_tv_mode_constants *const_ptr;
 | 
			
		||||
	struct radeon_pll *pll;
 | 
			
		||||
 | 
			
		||||
	radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
 | 
			
		||||
	if (radeon_crtc->crtc_id == 1)
 | 
			
		||||
		pll = &rdev->clock.p2pll;
 | 
			
		||||
	else
 | 
			
		||||
		pll = &rdev->clock.p1pll;
 | 
			
		||||
 | 
			
		||||
	if (pll_ref_freq)
 | 
			
		||||
		*pll_ref_freq = pll->reference_freq;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M) {
 | 
			
		||||
		if (pll->reference_freq == 2700)
 | 
			
		||||
			const_ptr = &available_tv_modes[0];
 | 
			
		||||
		else
 | 
			
		||||
			const_ptr = &available_tv_modes[2];
 | 
			
		||||
	} else {
 | 
			
		||||
		if (pll->reference_freq == 2700)
 | 
			
		||||
			const_ptr = &available_tv_modes[1];
 | 
			
		||||
		else
 | 
			
		||||
			const_ptr = &available_tv_modes[1]; /* FIX ME */
 | 
			
		||||
	}
 | 
			
		||||
	return const_ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static long YCOEF_value[5] = { 2, 2, 0, 4, 0 };
 | 
			
		||||
static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 };
 | 
			
		||||
static long SLOPE_value[5] = { 1, 2, 2, 4, 8 };
 | 
			
		||||
static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 };
 | 
			
		||||
 | 
			
		||||
static void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests,
 | 
			
		||||
				 unsigned n_wait_loops, unsigned cnt_threshold)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	uint32_t save_pll_test;
 | 
			
		||||
	unsigned int i, j;
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
 | 
			
		||||
	save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL);
 | 
			
		||||
	WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B);
 | 
			
		||||
 | 
			
		||||
	WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
 | 
			
		||||
	for (i = 0; i < n_tests; i++) {
 | 
			
		||||
		WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
 | 
			
		||||
		for (j = 0; j < n_wait_loops; j++)
 | 
			
		||||
			if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold)
 | 
			
		||||
				break;
 | 
			
		||||
	}
 | 
			
		||||
	WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test);
 | 
			
		||||
	WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder,
 | 
			
		||||
					uint16_t addr, uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = radeon_encoder->base.dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	uint32_t tmp;
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_HOST_WRITE_DATA, value);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
 | 
			
		||||
	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
 | 
			
		||||
		if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
		i++;
 | 
			
		||||
	} while (i < 10000);
 | 
			
		||||
	WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0 /* included for completeness */
 | 
			
		||||
static uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = radeon_encoder->base.dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	uint32_t tmp;
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
 | 
			
		||||
	WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
 | 
			
		||||
		if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
		i++;
 | 
			
		||||
	} while (i < 10000);
 | 
			
		||||
	WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
 | 
			
		||||
	return RREG32(RADEON_TV_HOST_READ_DATA);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr)
 | 
			
		||||
{
 | 
			
		||||
	uint16_t h_table;
 | 
			
		||||
 | 
			
		||||
	switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
		h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		h_table = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return h_table;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr)
 | 
			
		||||
{
 | 
			
		||||
	uint16_t v_table;
 | 
			
		||||
 | 
			
		||||
	switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
		v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		v_table = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return v_table;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = radeon_encoder->base.dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
	uint16_t h_table, v_table;
 | 
			
		||||
	uint32_t tmp;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr);
 | 
			
		||||
	h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr);
 | 
			
		||||
	v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) {
 | 
			
		||||
		tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]);
 | 
			
		||||
		radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp);
 | 
			
		||||
		if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) {
 | 
			
		||||
		tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]);
 | 
			
		||||
		radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp);
 | 
			
		||||
		if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = radeon_encoder->base.dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
	WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart);
 | 
			
		||||
	WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart);
 | 
			
		||||
	WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
	struct radeon_crtc *radeon_crtc;
 | 
			
		||||
	int restart;
 | 
			
		||||
	unsigned int h_total, v_total, f_total;
 | 
			
		||||
	int v_offset, h_offset;
 | 
			
		||||
	u16 p1, p2, h_inc;
 | 
			
		||||
	bool h_changed;
 | 
			
		||||
	const struct radeon_tv_mode_constants *const_ptr;
 | 
			
		||||
	struct radeon_pll *pll;
 | 
			
		||||
 | 
			
		||||
	radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
 | 
			
		||||
	if (radeon_crtc->crtc_id == 1)
 | 
			
		||||
		pll = &rdev->clock.p2pll;
 | 
			
		||||
	else
 | 
			
		||||
		pll = &rdev->clock.p1pll;
 | 
			
		||||
 | 
			
		||||
	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
 | 
			
		||||
	if (!const_ptr)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	h_total = const_ptr->hor_total;
 | 
			
		||||
	v_total = const_ptr->ver_total;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_60)
 | 
			
		||||
		f_total = NTSC_TV_VFTOTAL + 1;
 | 
			
		||||
	else
 | 
			
		||||
		f_total = PAL_TV_VFTOTAL + 1;
 | 
			
		||||
 | 
			
		||||
	/* adjust positions 1&2 in hor. cod timing table */
 | 
			
		||||
	h_offset = tv_dac->h_pos * H_POS_UNIT;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M) {
 | 
			
		||||
		h_offset -= 50;
 | 
			
		||||
		p1 = hor_timing_NTSC[H_TABLE_POS1];
 | 
			
		||||
		p2 = hor_timing_NTSC[H_TABLE_POS2];
 | 
			
		||||
	} else {
 | 
			
		||||
		p1 = hor_timing_PAL[H_TABLE_POS1];
 | 
			
		||||
		p2 = hor_timing_PAL[H_TABLE_POS2];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p1 = (u16)((int)p1 + h_offset);
 | 
			
		||||
	p2 = (u16)((int)p2 - h_offset);
 | 
			
		||||
 | 
			
		||||
	h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] ||
 | 
			
		||||
		     p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]);
 | 
			
		||||
 | 
			
		||||
	tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1;
 | 
			
		||||
	tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2;
 | 
			
		||||
 | 
			
		||||
	/* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */
 | 
			
		||||
	h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000;
 | 
			
		||||
 | 
			
		||||
	/* adjust restart */
 | 
			
		||||
	restart = const_ptr->def_restart;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * convert v_pos TV lines to n. of CRTC pixels
 | 
			
		||||
	 */
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_60)
 | 
			
		||||
		v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME);
 | 
			
		||||
	else
 | 
			
		||||
		v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME);
 | 
			
		||||
 | 
			
		||||
	restart -= v_offset + h_offset;
 | 
			
		||||
 | 
			
		||||
	DRM_DEBUG("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n",
 | 
			
		||||
		  const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart);
 | 
			
		||||
 | 
			
		||||
	tv_dac->tv.hrestart = restart % h_total;
 | 
			
		||||
	restart /= h_total;
 | 
			
		||||
	tv_dac->tv.vrestart = restart % v_total;
 | 
			
		||||
	restart /= v_total;
 | 
			
		||||
	tv_dac->tv.frestart = restart % f_total;
 | 
			
		||||
 | 
			
		||||
	DRM_DEBUG("compute_restart: F/H/V=%u,%u,%u\n",
 | 
			
		||||
		  (unsigned)tv_dac->tv.frestart,
 | 
			
		||||
		  (unsigned)tv_dac->tv.vrestart,
 | 
			
		||||
		  (unsigned)tv_dac->tv.hrestart);
 | 
			
		||||
 | 
			
		||||
	/* compute h_inc from hsize */
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M)
 | 
			
		||||
		h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) /
 | 
			
		||||
			      (tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE)));
 | 
			
		||||
	else
 | 
			
		||||
		h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) /
 | 
			
		||||
			      (tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE)));
 | 
			
		||||
 | 
			
		||||
	tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) |
 | 
			
		||||
		((u32)h_inc << RADEON_H_INC_SHIFT);
 | 
			
		||||
 | 
			
		||||
	DRM_DEBUG("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc);
 | 
			
		||||
 | 
			
		||||
	return h_changed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
 | 
			
		||||
			       struct drm_display_mode *mode,
 | 
			
		||||
			       struct drm_display_mode *adjusted_mode)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = encoder->dev;
 | 
			
		||||
	struct radeon_device *rdev = dev->dev_private;
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
 | 
			
		||||
	const struct radeon_tv_mode_constants *const_ptr;
 | 
			
		||||
	struct radeon_crtc *radeon_crtc;
 | 
			
		||||
	int i;
 | 
			
		||||
	uint16_t pll_ref_freq;
 | 
			
		||||
	uint32_t vert_space, flicker_removal, tmp;
 | 
			
		||||
	uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl;
 | 
			
		||||
	uint32_t tv_modulator_cntl1, tv_modulator_cntl2;
 | 
			
		||||
	uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2;
 | 
			
		||||
	uint32_t tv_pll_cntl, tv_pll_cntl1, tv_ftotal;
 | 
			
		||||
	uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl;
 | 
			
		||||
	uint32_t m, n, p;
 | 
			
		||||
	const uint16_t *hor_timing;
 | 
			
		||||
	const uint16_t *vert_timing;
 | 
			
		||||
 | 
			
		||||
	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq);
 | 
			
		||||
	if (!const_ptr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	radeon_crtc = to_radeon_crtc(encoder->crtc);
 | 
			
		||||
 | 
			
		||||
	tv_master_cntl = (RADEON_VIN_ASYNC_RST |
 | 
			
		||||
			  RADEON_CRT_FIFO_CE_EN |
 | 
			
		||||
			  RADEON_TV_FIFO_CE_EN |
 | 
			
		||||
			  RADEON_TV_ON);
 | 
			
		||||
 | 
			
		||||
	if (!ASIC_IS_R300(rdev))
 | 
			
		||||
		tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J)
 | 
			
		||||
		tv_master_cntl |= RADEON_RESTART_PHASE_FIX;
 | 
			
		||||
 | 
			
		||||
	tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT |
 | 
			
		||||
			      RADEON_SYNC_TIP_LEVEL |
 | 
			
		||||
			      RADEON_YFLT_EN |
 | 
			
		||||
			      RADEON_UVFLT_EN |
 | 
			
		||||
			      (6 << RADEON_CY_FILT_BLEND_SHIFT));
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J) {
 | 
			
		||||
		tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) |
 | 
			
		||||
			(0x3b << RADEON_BLANK_LEVEL_SHIFT);
 | 
			
		||||
		tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) |
 | 
			
		||||
			((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
 | 
			
		||||
	} else if (tv_dac->tv_std == TV_STD_SCART_PAL) {
 | 
			
		||||
		tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN;
 | 
			
		||||
		tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) |
 | 
			
		||||
			((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
 | 
			
		||||
	} else {
 | 
			
		||||
		tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN |
 | 
			
		||||
			(0x3b << RADEON_SET_UP_LEVEL_SHIFT) |
 | 
			
		||||
			(0x3b << RADEON_BLANK_LEVEL_SHIFT);
 | 
			
		||||
		tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) |
 | 
			
		||||
			((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	tv_rgb_cntl = (RADEON_RGB_DITHER_EN
 | 
			
		||||
		       | RADEON_TVOUT_SCALE_EN
 | 
			
		||||
		       | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT)
 | 
			
		||||
		       | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)
 | 
			
		||||
		       | RADEON_RGB_ATTEN_SEL(0x3)
 | 
			
		||||
		       | RADEON_RGB_ATTEN_VAL(0xc));
 | 
			
		||||
 | 
			
		||||
	if (radeon_crtc->crtc_id == 1)
 | 
			
		||||
		tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2;
 | 
			
		||||
	else {
 | 
			
		||||
		if (radeon_crtc->rmx_type != RMX_OFF)
 | 
			
		||||
			tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX;
 | 
			
		||||
		else
 | 
			
		||||
			tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_60)
 | 
			
		||||
		vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME;
 | 
			
		||||
	else
 | 
			
		||||
		vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME;
 | 
			
		||||
 | 
			
		||||
	tmp = RREG32(RADEON_TV_VSCALER_CNTL1);
 | 
			
		||||
	tmp &= 0xe3ff0000;
 | 
			
		||||
	tmp |= (vert_space * (1 << FRAC_BITS) / 10000);
 | 
			
		||||
	tv_vscaler_cntl1 = tmp;
 | 
			
		||||
 | 
			
		||||
	if (pll_ref_freq == 2700)
 | 
			
		||||
		tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
 | 
			
		||||
 | 
			
		||||
	if (const_ptr->hor_resolution == 1024)
 | 
			
		||||
		tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT);
 | 
			
		||||
	else
 | 
			
		||||
		tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT);
 | 
			
		||||
 | 
			
		||||
	/* scale up for int divide */
 | 
			
		||||
	tmp = const_ptr->ver_total * 2 * 1000;
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_60) {
 | 
			
		||||
		tmp /= NTSC_TV_LINES_PER_FRAME;
 | 
			
		||||
	} else {
 | 
			
		||||
		tmp /= PAL_TV_LINES_PER_FRAME;
 | 
			
		||||
	}
 | 
			
		||||
	flicker_removal = (tmp + 500) / 1000;
 | 
			
		||||
 | 
			
		||||
	if (flicker_removal < 3)
 | 
			
		||||
		flicker_removal = 3;
 | 
			
		||||
	for (i = 0; i < 6; ++i) {
 | 
			
		||||
		if (flicker_removal == SLOPE_limit[i])
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) +
 | 
			
		||||
				5001) / 10000 / 8 | ((SLOPE_value[i] *
 | 
			
		||||
				(1 << (FRAC_BITS - 1)) / 8) << 16);
 | 
			
		||||
	tv_y_fall_cntl =
 | 
			
		||||
		(YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) |
 | 
			
		||||
		RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) /
 | 
			
		||||
		1024;
 | 
			
		||||
	tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG|
 | 
			
		||||
		(flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024;
 | 
			
		||||
 | 
			
		||||
	tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0;
 | 
			
		||||
	tv_vscaler_cntl2 |= (0x10 << 24) |
 | 
			
		||||
		RADEON_DITHER_MODE |
 | 
			
		||||
		RADEON_Y_OUTPUT_DITHER_EN |
 | 
			
		||||
		RADEON_UV_OUTPUT_DITHER_EN |
 | 
			
		||||
		RADEON_UV_TO_BUF_DITHER_EN;
 | 
			
		||||
 | 
			
		||||
	tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK;
 | 
			
		||||
	tmp = ((16384 * 256 * 10) / tmp + 5) / 10;
 | 
			
		||||
	tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000;
 | 
			
		||||
	tv_dac->tv.timing_cntl = tmp;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_60)
 | 
			
		||||
		tv_dac_cntl = tv_dac->ntsc_tvdac_adj;
 | 
			
		||||
	else
 | 
			
		||||
		tv_dac_cntl = tv_dac->pal_tvdac_adj;
 | 
			
		||||
 | 
			
		||||
	tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J)
 | 
			
		||||
		tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
 | 
			
		||||
	else
 | 
			
		||||
		tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J) {
 | 
			
		||||
		if (pll_ref_freq == 2700) {
 | 
			
		||||
			m = NTSC_TV_PLL_M_27;
 | 
			
		||||
			n = NTSC_TV_PLL_N_27;
 | 
			
		||||
			p = NTSC_TV_PLL_P_27;
 | 
			
		||||
		} else {
 | 
			
		||||
			m = NTSC_TV_PLL_M_14;
 | 
			
		||||
			n = NTSC_TV_PLL_N_14;
 | 
			
		||||
			p = NTSC_TV_PLL_P_14;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (pll_ref_freq == 2700) {
 | 
			
		||||
			m = PAL_TV_PLL_M_27;
 | 
			
		||||
			n = PAL_TV_PLL_N_27;
 | 
			
		||||
			p = PAL_TV_PLL_P_27;
 | 
			
		||||
		} else {
 | 
			
		||||
			m = PAL_TV_PLL_M_27;
 | 
			
		||||
			n = PAL_TV_PLL_N_27;
 | 
			
		||||
			p = PAL_TV_PLL_P_27;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) |
 | 
			
		||||
		(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
 | 
			
		||||
		((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
 | 
			
		||||
		(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
 | 
			
		||||
		((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
 | 
			
		||||
 | 
			
		||||
	tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK) << RADEON_TVPCP_SHIFT) |
 | 
			
		||||
			((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) |
 | 
			
		||||
			((1 & RADEON_TVPDC_MASK) << RADEON_TVPDC_SHIFT) |
 | 
			
		||||
			RADEON_TVCLK_SRC_SEL_TVPLL |
 | 
			
		||||
			RADEON_TVPLL_TEST_DIS);
 | 
			
		||||
 | 
			
		||||
	tv_dac->tv.tv_uv_adr = 0xc8;
 | 
			
		||||
 | 
			
		||||
	if (tv_dac->tv_std == TV_STD_NTSC ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_NTSC_J ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_M ||
 | 
			
		||||
	    tv_dac->tv_std == TV_STD_PAL_60) {
 | 
			
		||||
		tv_ftotal = NTSC_TV_VFTOTAL;
 | 
			
		||||
		hor_timing = hor_timing_NTSC;
 | 
			
		||||
		vert_timing = vert_timing_NTSC;
 | 
			
		||||
	} else {
 | 
			
		||||
		hor_timing = hor_timing_PAL;
 | 
			
		||||
		vert_timing = vert_timing_PAL;
 | 
			
		||||
		tv_ftotal = PAL_TV_VFTOTAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) {
 | 
			
		||||
		if ((tv_dac->tv.h_code_timing[i] = hor_timing[i]) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) {
 | 
			
		||||
		if ((tv_dac->tv.v_code_timing[i] = vert_timing[i]) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	radeon_legacy_tv_init_restarts(encoder);
 | 
			
		||||
 | 
			
		||||
	/* play with DAC_CNTL */
 | 
			
		||||
	/* play with GPIOPAD_A */
 | 
			
		||||
	/* DISP_OUTPUT_CNTL */
 | 
			
		||||
	/* use reference freq */
 | 
			
		||||
 | 
			
		||||
	/* program the TV registers */
 | 
			
		||||
	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
 | 
			
		||||
				       RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST));
 | 
			
		||||
 | 
			
		||||
	tmp = RREG32(RADEON_TV_DAC_CNTL);
 | 
			
		||||
	tmp &= ~RADEON_TV_DAC_NBLANK;
 | 
			
		||||
	tmp |= RADEON_TV_DAC_BGSLEEP |
 | 
			
		||||
		RADEON_TV_DAC_RDACPD |
 | 
			
		||||
		RADEON_TV_DAC_GDACPD |
 | 
			
		||||
		RADEON_TV_DAC_BDACPD;
 | 
			
		||||
	WREG32(RADEON_TV_DAC_CNTL, tmp);
 | 
			
		||||
 | 
			
		||||
	/* TV PLL */
 | 
			
		||||
	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
 | 
			
		||||
	WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl);
 | 
			
		||||
	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
 | 
			
		||||
 | 
			
		||||
	radeon_wait_pll_lock(encoder, 200, 800, 135);
 | 
			
		||||
 | 
			
		||||
	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
 | 
			
		||||
 | 
			
		||||
	radeon_wait_pll_lock(encoder, 300, 160, 27);
 | 
			
		||||
	radeon_wait_pll_lock(encoder, 200, 800, 135);
 | 
			
		||||
 | 
			
		||||
	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf);
 | 
			
		||||
	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
 | 
			
		||||
 | 
			
		||||
	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
 | 
			
		||||
	WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
 | 
			
		||||
 | 
			
		||||
	/* TV HV */
 | 
			
		||||
	WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl);
 | 
			
		||||
	WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1);
 | 
			
		||||
	WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1);
 | 
			
		||||
	WREG32(RADEON_TV_HSTART, const_ptr->hor_start);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1);
 | 
			
		||||
	WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1);
 | 
			
		||||
	WREG32(RADEON_TV_FTOTAL, tv_ftotal);
 | 
			
		||||
	WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1);
 | 
			
		||||
	WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl);
 | 
			
		||||
	WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl);
 | 
			
		||||
	WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
 | 
			
		||||
				       RADEON_CRT_ASYNC_RST));
 | 
			
		||||
 | 
			
		||||
	/* TV restarts */
 | 
			
		||||
	radeon_legacy_write_tv_restarts(radeon_encoder);
 | 
			
		||||
 | 
			
		||||
	/* tv timings */
 | 
			
		||||
	radeon_restore_tv_timing_tables(radeon_encoder);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST));
 | 
			
		||||
 | 
			
		||||
	/* tv std */
 | 
			
		||||
	WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE));
 | 
			
		||||
	WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl);
 | 
			
		||||
	WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1);
 | 
			
		||||
	WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2);
 | 
			
		||||
	WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN |
 | 
			
		||||
					    RADEON_C_GRN_EN |
 | 
			
		||||
					    RADEON_CMP_BLU_EN |
 | 
			
		||||
					    RADEON_DAC_DITHER_EN));
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_CRC_CNTL, 0);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) |
 | 
			
		||||
					       (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT)));
 | 
			
		||||
	WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) |
 | 
			
		||||
						(0x100 << RADEON_Y_GAIN_SHIFT)));
 | 
			
		||||
 | 
			
		||||
	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
 | 
			
		||||
				      uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
 | 
			
		||||
				      uint32_t *v_total_disp, uint32_t *v_sync_strt_wid)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	const struct radeon_tv_mode_constants *const_ptr;
 | 
			
		||||
	uint32_t tmp;
 | 
			
		||||
 | 
			
		||||
	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
 | 
			
		||||
	if (!const_ptr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	*h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
 | 
			
		||||
		(((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
 | 
			
		||||
 | 
			
		||||
	tmp = *h_sync_strt_wid;
 | 
			
		||||
	tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR);
 | 
			
		||||
	tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
 | 
			
		||||
		(const_ptr->hor_syncstart & 7);
 | 
			
		||||
	*h_sync_strt_wid = tmp;
 | 
			
		||||
 | 
			
		||||
	*v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
 | 
			
		||||
		((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
 | 
			
		||||
 | 
			
		||||
	tmp = *v_sync_strt_wid;
 | 
			
		||||
	tmp &= ~RADEON_CRTC_V_SYNC_STRT;
 | 
			
		||||
	tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
 | 
			
		||||
	*v_sync_strt_wid = tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int get_post_div(int value)
 | 
			
		||||
{
 | 
			
		||||
	int post_div;
 | 
			
		||||
	switch (value) {
 | 
			
		||||
	case 1: post_div = 0; break;
 | 
			
		||||
	case 2: post_div = 1; break;
 | 
			
		||||
	case 3: post_div = 4; break;
 | 
			
		||||
	case 4: post_div = 2; break;
 | 
			
		||||
	case 6: post_div = 6; break;
 | 
			
		||||
	case 8: post_div = 3; break;
 | 
			
		||||
	case 12: post_div = 7; break;
 | 
			
		||||
	case 16:
 | 
			
		||||
	default: post_div = 5; break;
 | 
			
		||||
	}
 | 
			
		||||
	return post_div;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
 | 
			
		||||
				  uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
 | 
			
		||||
				  uint32_t *ppll_div_3, uint32_t *pixclks_cntl)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	const struct radeon_tv_mode_constants *const_ptr;
 | 
			
		||||
 | 
			
		||||
	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
 | 
			
		||||
	if (!const_ptr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	*htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN;
 | 
			
		||||
 | 
			
		||||
	*ppll_ref_div = const_ptr->crtcPLL_M;
 | 
			
		||||
 | 
			
		||||
	*ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
 | 
			
		||||
	*pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL);
 | 
			
		||||
	*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
 | 
			
		||||
				  uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
 | 
			
		||||
				  uint32_t *p2pll_div_0, uint32_t *pixclks_cntl)
 | 
			
		||||
{
 | 
			
		||||
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 | 
			
		||||
	const struct radeon_tv_mode_constants *const_ptr;
 | 
			
		||||
 | 
			
		||||
	const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
 | 
			
		||||
	if (!const_ptr)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	*htotal2_cntl = (const_ptr->hor_total & 0x7);
 | 
			
		||||
 | 
			
		||||
	*p2pll_ref_div = const_ptr->crtcPLL_M;
 | 
			
		||||
 | 
			
		||||
	*p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
 | 
			
		||||
	*pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
 | 
			
		||||
	*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -188,6 +188,21 @@ struct radeon_native_mode {
 | 
			
		|||
	uint32_t flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_H_CODE_TIMING_LEN 32
 | 
			
		||||
#define MAX_V_CODE_TIMING_LEN 32
 | 
			
		||||
 | 
			
		||||
/* need to store these as reading
 | 
			
		||||
   back code tables is excessive */
 | 
			
		||||
struct radeon_tv_regs {
 | 
			
		||||
	uint32_t tv_uv_adr;
 | 
			
		||||
	uint32_t timing_cntl;
 | 
			
		||||
	uint32_t hrestart;
 | 
			
		||||
	uint32_t vrestart;
 | 
			
		||||
	uint32_t frestart;
 | 
			
		||||
	uint16_t h_code_timing[MAX_H_CODE_TIMING_LEN];
 | 
			
		||||
	uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct radeon_crtc {
 | 
			
		||||
	struct drm_crtc base;
 | 
			
		||||
	int crtc_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +217,6 @@ struct radeon_crtc {
 | 
			
		|||
	uint32_t legacy_display_base_addr;
 | 
			
		||||
	uint32_t legacy_cursor_offset;
 | 
			
		||||
	enum radeon_rmx_type rmx_type;
 | 
			
		||||
	uint32_t devices;
 | 
			
		||||
	fixed20_12 vsc;
 | 
			
		||||
	fixed20_12 hsc;
 | 
			
		||||
	struct radeon_native_mode native_mode;
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +248,13 @@ struct radeon_encoder_tv_dac {
 | 
			
		|||
	uint32_t ntsc_tvdac_adj;
 | 
			
		||||
	uint32_t pal_tvdac_adj;
 | 
			
		||||
 | 
			
		||||
	int               h_pos;
 | 
			
		||||
	int               v_pos;
 | 
			
		||||
	int               h_size;
 | 
			
		||||
	int               supported_tv_stds;
 | 
			
		||||
	bool              tv_on;
 | 
			
		||||
	enum radeon_tv_std tv_std;
 | 
			
		||||
	struct radeon_tv_regs tv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct radeon_encoder_int_tmds {
 | 
			
		||||
| 
						 | 
				
			
			@ -253,10 +273,15 @@ struct radeon_encoder_atom_dig {
 | 
			
		|||
	struct radeon_native_mode native_mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct radeon_encoder_atom_dac {
 | 
			
		||||
	enum radeon_tv_std tv_std;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct radeon_encoder {
 | 
			
		||||
	struct drm_encoder base;
 | 
			
		||||
	uint32_t encoder_id;
 | 
			
		||||
	uint32_t devices;
 | 
			
		||||
	uint32_t active_device;
 | 
			
		||||
	uint32_t flags;
 | 
			
		||||
	uint32_t pixel_clock;
 | 
			
		||||
	enum radeon_rmx_type rmx_type;
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +299,10 @@ struct radeon_connector {
 | 
			
		|||
	uint32_t connector_id;
 | 
			
		||||
	uint32_t devices;
 | 
			
		||||
	struct radeon_i2c_chan *ddc_bus;
 | 
			
		||||
	int use_digital;
 | 
			
		||||
	bool use_digital;
 | 
			
		||||
	/* we need to mind the EDID between detect
 | 
			
		||||
	   and get modes due to analog/digital/tvencoder */
 | 
			
		||||
	struct edid *edid;
 | 
			
		||||
	void *con_priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -308,6 +336,7 @@ struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, i
 | 
			
		|||
struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index);
 | 
			
		||||
extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action);
 | 
			
		||||
extern int atombios_get_encoder_mode(struct drm_encoder *encoder);
 | 
			
		||||
extern void radeon_encoder_set_active_device(struct drm_encoder *encoder);
 | 
			
		||||
 | 
			
		||||
extern void radeon_crtc_load_lut(struct drm_crtc *crtc);
 | 
			
		||||
extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 | 
			
		||||
| 
						 | 
				
			
			@ -394,6 +423,19 @@ extern int radeon_static_clocks_init(struct drm_device *dev);
 | 
			
		|||
bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
 | 
			
		||||
					struct drm_display_mode *mode,
 | 
			
		||||
					struct drm_display_mode *adjusted_mode);
 | 
			
		||||
void atom_rv515_force_tv_scaler(struct radeon_device *rdev);
 | 
			
		||||
void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc);
 | 
			
		||||
 | 
			
		||||
/* legacy tv */
 | 
			
		||||
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
 | 
			
		||||
				      uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
 | 
			
		||||
				      uint32_t *v_total_disp, uint32_t *v_sync_strt_wid);
 | 
			
		||||
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
 | 
			
		||||
				  uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
 | 
			
		||||
				  uint32_t *ppll_div_3, uint32_t *pixclks_cntl);
 | 
			
		||||
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
 | 
			
		||||
				  uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
 | 
			
		||||
				  uint32_t *p2pll_div_0, uint32_t *pixclks_cntl);
 | 
			
		||||
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
 | 
			
		||||
			       struct drm_display_mode *mode,
 | 
			
		||||
			       struct drm_display_mode *adjusted_mode);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3462,7 +3462,9 @@
 | 
			
		|||
#       define RADEON_RGB_CONVERT_BY_PASS	  (1 << 10)
 | 
			
		||||
#       define RADEON_UVRAM_READ_MARGIN_SHIFT	  16
 | 
			
		||||
#       define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT	  20
 | 
			
		||||
#	define RADEON_TVOUT_SCALE_EN		  (1 << 26)
 | 
			
		||||
#       define RADEON_RGB_ATTEN_SEL(x)            ((x) << 24)
 | 
			
		||||
#       define RADEON_TVOUT_SCALE_EN              (1 << 26)
 | 
			
		||||
#       define RADEON_RGB_ATTEN_VAL(x)            ((x) << 28)
 | 
			
		||||
#define RADEON_TV_SYNC_CNTL                          0x0808
 | 
			
		||||
#       define RADEON_SYNC_OE                     (1 <<  0)
 | 
			
		||||
#       define RADEON_SYNC_OUT                    (1 <<  1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -475,232 +475,234 @@ int rv515_init(struct radeon_device *rdev)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void atom_rv515_force_tv_scaler(struct radeon_device *rdev)
 | 
			
		||||
void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *crtc)
 | 
			
		||||
{
 | 
			
		||||
	int index_reg = 0x6578 + crtc->crtc_offset;
 | 
			
		||||
	int data_reg = 0x657c + crtc->crtc_offset;
 | 
			
		||||
 | 
			
		||||
	WREG32(0x659C, 0x0);
 | 
			
		||||
	WREG32(0x6594, 0x705);
 | 
			
		||||
	WREG32(0x65A4, 0x10001);
 | 
			
		||||
	WREG32(0x65D8, 0x0);
 | 
			
		||||
	WREG32(0x65B0, 0x0);
 | 
			
		||||
	WREG32(0x65C0, 0x0);
 | 
			
		||||
	WREG32(0x65D4, 0x0);
 | 
			
		||||
	WREG32(0x6578, 0x0);
 | 
			
		||||
	WREG32(0x657C, 0x841880A8);
 | 
			
		||||
	WREG32(0x6578, 0x1);
 | 
			
		||||
	WREG32(0x657C, 0x84208680);
 | 
			
		||||
	WREG32(0x6578, 0x2);
 | 
			
		||||
	WREG32(0x657C, 0xBFF880B0);
 | 
			
		||||
	WREG32(0x6578, 0x100);
 | 
			
		||||
	WREG32(0x657C, 0x83D88088);
 | 
			
		||||
	WREG32(0x6578, 0x101);
 | 
			
		||||
	WREG32(0x657C, 0x84608680);
 | 
			
		||||
	WREG32(0x6578, 0x102);
 | 
			
		||||
	WREG32(0x657C, 0xBFF080D0);
 | 
			
		||||
	WREG32(0x6578, 0x200);
 | 
			
		||||
	WREG32(0x657C, 0x83988068);
 | 
			
		||||
	WREG32(0x6578, 0x201);
 | 
			
		||||
	WREG32(0x657C, 0x84A08680);
 | 
			
		||||
	WREG32(0x6578, 0x202);
 | 
			
		||||
	WREG32(0x657C, 0xBFF080F8);
 | 
			
		||||
	WREG32(0x6578, 0x300);
 | 
			
		||||
	WREG32(0x657C, 0x83588058);
 | 
			
		||||
	WREG32(0x6578, 0x301);
 | 
			
		||||
	WREG32(0x657C, 0x84E08660);
 | 
			
		||||
	WREG32(0x6578, 0x302);
 | 
			
		||||
	WREG32(0x657C, 0xBFF88120);
 | 
			
		||||
	WREG32(0x6578, 0x400);
 | 
			
		||||
	WREG32(0x657C, 0x83188040);
 | 
			
		||||
	WREG32(0x6578, 0x401);
 | 
			
		||||
	WREG32(0x657C, 0x85008660);
 | 
			
		||||
	WREG32(0x6578, 0x402);
 | 
			
		||||
	WREG32(0x657C, 0xBFF88150);
 | 
			
		||||
	WREG32(0x6578, 0x500);
 | 
			
		||||
	WREG32(0x657C, 0x82D88030);
 | 
			
		||||
	WREG32(0x6578, 0x501);
 | 
			
		||||
	WREG32(0x657C, 0x85408640);
 | 
			
		||||
	WREG32(0x6578, 0x502);
 | 
			
		||||
	WREG32(0x657C, 0xBFF88180);
 | 
			
		||||
	WREG32(0x6578, 0x600);
 | 
			
		||||
	WREG32(0x657C, 0x82A08018);
 | 
			
		||||
	WREG32(0x6578, 0x601);
 | 
			
		||||
	WREG32(0x657C, 0x85808620);
 | 
			
		||||
	WREG32(0x6578, 0x602);
 | 
			
		||||
	WREG32(0x657C, 0xBFF081B8);
 | 
			
		||||
	WREG32(0x6578, 0x700);
 | 
			
		||||
	WREG32(0x657C, 0x82608010);
 | 
			
		||||
	WREG32(0x6578, 0x701);
 | 
			
		||||
	WREG32(0x657C, 0x85A08600);
 | 
			
		||||
	WREG32(0x6578, 0x702);
 | 
			
		||||
	WREG32(0x657C, 0x800081F0);
 | 
			
		||||
	WREG32(0x6578, 0x800);
 | 
			
		||||
	WREG32(0x657C, 0x8228BFF8);
 | 
			
		||||
	WREG32(0x6578, 0x801);
 | 
			
		||||
	WREG32(0x657C, 0x85E085E0);
 | 
			
		||||
	WREG32(0x6578, 0x802);
 | 
			
		||||
	WREG32(0x657C, 0xBFF88228);
 | 
			
		||||
	WREG32(0x6578, 0x10000);
 | 
			
		||||
	WREG32(0x657C, 0x82A8BF00);
 | 
			
		||||
	WREG32(0x6578, 0x10001);
 | 
			
		||||
	WREG32(0x657C, 0x82A08CC0);
 | 
			
		||||
	WREG32(0x6578, 0x10002);
 | 
			
		||||
	WREG32(0x657C, 0x8008BEF8);
 | 
			
		||||
	WREG32(0x6578, 0x10100);
 | 
			
		||||
	WREG32(0x657C, 0x81F0BF28);
 | 
			
		||||
	WREG32(0x6578, 0x10101);
 | 
			
		||||
	WREG32(0x657C, 0x83608CA0);
 | 
			
		||||
	WREG32(0x6578, 0x10102);
 | 
			
		||||
	WREG32(0x657C, 0x8018BED0);
 | 
			
		||||
	WREG32(0x6578, 0x10200);
 | 
			
		||||
	WREG32(0x657C, 0x8148BF38);
 | 
			
		||||
	WREG32(0x6578, 0x10201);
 | 
			
		||||
	WREG32(0x657C, 0x84408C80);
 | 
			
		||||
	WREG32(0x6578, 0x10202);
 | 
			
		||||
	WREG32(0x657C, 0x8008BEB8);
 | 
			
		||||
	WREG32(0x6578, 0x10300);
 | 
			
		||||
	WREG32(0x657C, 0x80B0BF78);
 | 
			
		||||
	WREG32(0x6578, 0x10301);
 | 
			
		||||
	WREG32(0x657C, 0x85008C20);
 | 
			
		||||
	WREG32(0x6578, 0x10302);
 | 
			
		||||
	WREG32(0x657C, 0x8020BEA0);
 | 
			
		||||
	WREG32(0x6578, 0x10400);
 | 
			
		||||
	WREG32(0x657C, 0x8028BF90);
 | 
			
		||||
	WREG32(0x6578, 0x10401);
 | 
			
		||||
	WREG32(0x657C, 0x85E08BC0);
 | 
			
		||||
	WREG32(0x6578, 0x10402);
 | 
			
		||||
	WREG32(0x657C, 0x8018BE90);
 | 
			
		||||
	WREG32(0x6578, 0x10500);
 | 
			
		||||
	WREG32(0x657C, 0xBFB8BFB0);
 | 
			
		||||
	WREG32(0x6578, 0x10501);
 | 
			
		||||
	WREG32(0x657C, 0x86C08B40);
 | 
			
		||||
	WREG32(0x6578, 0x10502);
 | 
			
		||||
	WREG32(0x657C, 0x8010BE90);
 | 
			
		||||
	WREG32(0x6578, 0x10600);
 | 
			
		||||
	WREG32(0x657C, 0xBF58BFC8);
 | 
			
		||||
	WREG32(0x6578, 0x10601);
 | 
			
		||||
	WREG32(0x657C, 0x87A08AA0);
 | 
			
		||||
	WREG32(0x6578, 0x10602);
 | 
			
		||||
	WREG32(0x657C, 0x8010BE98);
 | 
			
		||||
	WREG32(0x6578, 0x10700);
 | 
			
		||||
	WREG32(0x657C, 0xBF10BFF0);
 | 
			
		||||
	WREG32(0x6578, 0x10701);
 | 
			
		||||
	WREG32(0x657C, 0x886089E0);
 | 
			
		||||
	WREG32(0x6578, 0x10702);
 | 
			
		||||
	WREG32(0x657C, 0x8018BEB0);
 | 
			
		||||
	WREG32(0x6578, 0x10800);
 | 
			
		||||
	WREG32(0x657C, 0xBED8BFE8);
 | 
			
		||||
	WREG32(0x6578, 0x10801);
 | 
			
		||||
	WREG32(0x657C, 0x89408940);
 | 
			
		||||
	WREG32(0x6578, 0x10802);
 | 
			
		||||
	WREG32(0x657C, 0xBFE8BED8);
 | 
			
		||||
	WREG32(0x6578, 0x20000);
 | 
			
		||||
	WREG32(0x657C, 0x80008000);
 | 
			
		||||
	WREG32(0x6578, 0x20001);
 | 
			
		||||
	WREG32(0x657C, 0x90008000);
 | 
			
		||||
	WREG32(0x6578, 0x20002);
 | 
			
		||||
	WREG32(0x657C, 0x80008000);
 | 
			
		||||
	WREG32(0x6578, 0x20003);
 | 
			
		||||
	WREG32(0x657C, 0x80008000);
 | 
			
		||||
	WREG32(0x6578, 0x20100);
 | 
			
		||||
	WREG32(0x657C, 0x80108000);
 | 
			
		||||
	WREG32(0x6578, 0x20101);
 | 
			
		||||
	WREG32(0x657C, 0x8FE0BF70);
 | 
			
		||||
	WREG32(0x6578, 0x20102);
 | 
			
		||||
	WREG32(0x657C, 0xBFE880C0);
 | 
			
		||||
	WREG32(0x6578, 0x20103);
 | 
			
		||||
	WREG32(0x657C, 0x80008000);
 | 
			
		||||
	WREG32(0x6578, 0x20200);
 | 
			
		||||
	WREG32(0x657C, 0x8018BFF8);
 | 
			
		||||
	WREG32(0x6578, 0x20201);
 | 
			
		||||
	WREG32(0x657C, 0x8F80BF08);
 | 
			
		||||
	WREG32(0x6578, 0x20202);
 | 
			
		||||
	WREG32(0x657C, 0xBFD081A0);
 | 
			
		||||
	WREG32(0x6578, 0x20203);
 | 
			
		||||
	WREG32(0x657C, 0xBFF88000);
 | 
			
		||||
	WREG32(0x6578, 0x20300);
 | 
			
		||||
	WREG32(0x657C, 0x80188000);
 | 
			
		||||
	WREG32(0x6578, 0x20301);
 | 
			
		||||
	WREG32(0x657C, 0x8EE0BEC0);
 | 
			
		||||
	WREG32(0x6578, 0x20302);
 | 
			
		||||
	WREG32(0x657C, 0xBFB082A0);
 | 
			
		||||
	WREG32(0x6578, 0x20303);
 | 
			
		||||
	WREG32(0x657C, 0x80008000);
 | 
			
		||||
	WREG32(0x6578, 0x20400);
 | 
			
		||||
	WREG32(0x657C, 0x80188000);
 | 
			
		||||
	WREG32(0x6578, 0x20401);
 | 
			
		||||
	WREG32(0x657C, 0x8E00BEA0);
 | 
			
		||||
	WREG32(0x6578, 0x20402);
 | 
			
		||||
	WREG32(0x657C, 0xBF8883C0);
 | 
			
		||||
	WREG32(0x6578, 0x20403);
 | 
			
		||||
	WREG32(0x657C, 0x80008000);
 | 
			
		||||
	WREG32(0x6578, 0x20500);
 | 
			
		||||
	WREG32(0x657C, 0x80188000);
 | 
			
		||||
	WREG32(0x6578, 0x20501);
 | 
			
		||||
	WREG32(0x657C, 0x8D00BE90);
 | 
			
		||||
	WREG32(0x6578, 0x20502);
 | 
			
		||||
	WREG32(0x657C, 0xBF588500);
 | 
			
		||||
	WREG32(0x6578, 0x20503);
 | 
			
		||||
	WREG32(0x657C, 0x80008008);
 | 
			
		||||
	WREG32(0x6578, 0x20600);
 | 
			
		||||
	WREG32(0x657C, 0x80188000);
 | 
			
		||||
	WREG32(0x6578, 0x20601);
 | 
			
		||||
	WREG32(0x657C, 0x8BC0BE98);
 | 
			
		||||
	WREG32(0x6578, 0x20602);
 | 
			
		||||
	WREG32(0x657C, 0xBF308660);
 | 
			
		||||
	WREG32(0x6578, 0x20603);
 | 
			
		||||
	WREG32(0x657C, 0x80008008);
 | 
			
		||||
	WREG32(0x6578, 0x20700);
 | 
			
		||||
	WREG32(0x657C, 0x80108000);
 | 
			
		||||
	WREG32(0x6578, 0x20701);
 | 
			
		||||
	WREG32(0x657C, 0x8A80BEB0);
 | 
			
		||||
	WREG32(0x6578, 0x20702);
 | 
			
		||||
	WREG32(0x657C, 0xBF0087C0);
 | 
			
		||||
	WREG32(0x6578, 0x20703);
 | 
			
		||||
	WREG32(0x657C, 0x80008008);
 | 
			
		||||
	WREG32(0x6578, 0x20800);
 | 
			
		||||
	WREG32(0x657C, 0x80108000);
 | 
			
		||||
	WREG32(0x6578, 0x20801);
 | 
			
		||||
	WREG32(0x657C, 0x8920BED0);
 | 
			
		||||
	WREG32(0x6578, 0x20802);
 | 
			
		||||
	WREG32(0x657C, 0xBED08920);
 | 
			
		||||
	WREG32(0x6578, 0x20803);
 | 
			
		||||
	WREG32(0x657C, 0x80008010);
 | 
			
		||||
	WREG32(0x6578, 0x30000);
 | 
			
		||||
	WREG32(0x657C, 0x90008000);
 | 
			
		||||
	WREG32(0x6578, 0x30001);
 | 
			
		||||
	WREG32(0x657C, 0x80008000);
 | 
			
		||||
	WREG32(0x6578, 0x30100);
 | 
			
		||||
	WREG32(0x657C, 0x8FE0BF90);
 | 
			
		||||
	WREG32(0x6578, 0x30101);
 | 
			
		||||
	WREG32(0x657C, 0xBFF880A0);
 | 
			
		||||
	WREG32(0x6578, 0x30200);
 | 
			
		||||
	WREG32(0x657C, 0x8F60BF40);
 | 
			
		||||
	WREG32(0x6578, 0x30201);
 | 
			
		||||
	WREG32(0x657C, 0xBFE88180);
 | 
			
		||||
	WREG32(0x6578, 0x30300);
 | 
			
		||||
	WREG32(0x657C, 0x8EC0BF00);
 | 
			
		||||
	WREG32(0x6578, 0x30301);
 | 
			
		||||
	WREG32(0x657C, 0xBFC88280);
 | 
			
		||||
	WREG32(0x6578, 0x30400);
 | 
			
		||||
	WREG32(0x657C, 0x8DE0BEE0);
 | 
			
		||||
	WREG32(0x6578, 0x30401);
 | 
			
		||||
	WREG32(0x657C, 0xBFA083A0);
 | 
			
		||||
	WREG32(0x6578, 0x30500);
 | 
			
		||||
	WREG32(0x657C, 0x8CE0BED0);
 | 
			
		||||
	WREG32(0x6578, 0x30501);
 | 
			
		||||
	WREG32(0x657C, 0xBF7884E0);
 | 
			
		||||
	WREG32(0x6578, 0x30600);
 | 
			
		||||
	WREG32(0x657C, 0x8BA0BED8);
 | 
			
		||||
	WREG32(0x6578, 0x30601);
 | 
			
		||||
	WREG32(0x657C, 0xBF508640);
 | 
			
		||||
	WREG32(0x6578, 0x30700);
 | 
			
		||||
	WREG32(0x657C, 0x8A60BEE8);
 | 
			
		||||
	WREG32(0x6578, 0x30701);
 | 
			
		||||
	WREG32(0x657C, 0xBF2087A0);
 | 
			
		||||
	WREG32(0x6578, 0x30800);
 | 
			
		||||
	WREG32(0x657C, 0x8900BF00);
 | 
			
		||||
	WREG32(0x6578, 0x30801);
 | 
			
		||||
	WREG32(0x657C, 0xBF008900);
 | 
			
		||||
	WREG32(0x659C + crtc->crtc_offset, 0x0);
 | 
			
		||||
	WREG32(0x6594 + crtc->crtc_offset, 0x705);
 | 
			
		||||
	WREG32(0x65A4 + crtc->crtc_offset, 0x10001);
 | 
			
		||||
	WREG32(0x65D8 + crtc->crtc_offset, 0x0);
 | 
			
		||||
	WREG32(0x65B0 + crtc->crtc_offset, 0x0);
 | 
			
		||||
	WREG32(0x65C0 + crtc->crtc_offset, 0x0);
 | 
			
		||||
	WREG32(0x65D4 + crtc->crtc_offset, 0x0);
 | 
			
		||||
	WREG32(index_reg, 0x0);
 | 
			
		||||
	WREG32(data_reg, 0x841880A8);
 | 
			
		||||
	WREG32(index_reg, 0x1);
 | 
			
		||||
	WREG32(data_reg, 0x84208680);
 | 
			
		||||
	WREG32(index_reg, 0x2);
 | 
			
		||||
	WREG32(data_reg, 0xBFF880B0);
 | 
			
		||||
	WREG32(index_reg, 0x100);
 | 
			
		||||
	WREG32(data_reg, 0x83D88088);
 | 
			
		||||
	WREG32(index_reg, 0x101);
 | 
			
		||||
	WREG32(data_reg, 0x84608680);
 | 
			
		||||
	WREG32(index_reg, 0x102);
 | 
			
		||||
	WREG32(data_reg, 0xBFF080D0);
 | 
			
		||||
	WREG32(index_reg, 0x200);
 | 
			
		||||
	WREG32(data_reg, 0x83988068);
 | 
			
		||||
	WREG32(index_reg, 0x201);
 | 
			
		||||
	WREG32(data_reg, 0x84A08680);
 | 
			
		||||
	WREG32(index_reg, 0x202);
 | 
			
		||||
	WREG32(data_reg, 0xBFF080F8);
 | 
			
		||||
	WREG32(index_reg, 0x300);
 | 
			
		||||
	WREG32(data_reg, 0x83588058);
 | 
			
		||||
	WREG32(index_reg, 0x301);
 | 
			
		||||
	WREG32(data_reg, 0x84E08660);
 | 
			
		||||
	WREG32(index_reg, 0x302);
 | 
			
		||||
	WREG32(data_reg, 0xBFF88120);
 | 
			
		||||
	WREG32(index_reg, 0x400);
 | 
			
		||||
	WREG32(data_reg, 0x83188040);
 | 
			
		||||
	WREG32(index_reg, 0x401);
 | 
			
		||||
	WREG32(data_reg, 0x85008660);
 | 
			
		||||
	WREG32(index_reg, 0x402);
 | 
			
		||||
	WREG32(data_reg, 0xBFF88150);
 | 
			
		||||
	WREG32(index_reg, 0x500);
 | 
			
		||||
	WREG32(data_reg, 0x82D88030);
 | 
			
		||||
	WREG32(index_reg, 0x501);
 | 
			
		||||
	WREG32(data_reg, 0x85408640);
 | 
			
		||||
	WREG32(index_reg, 0x502);
 | 
			
		||||
	WREG32(data_reg, 0xBFF88180);
 | 
			
		||||
	WREG32(index_reg, 0x600);
 | 
			
		||||
	WREG32(data_reg, 0x82A08018);
 | 
			
		||||
	WREG32(index_reg, 0x601);
 | 
			
		||||
	WREG32(data_reg, 0x85808620);
 | 
			
		||||
	WREG32(index_reg, 0x602);
 | 
			
		||||
	WREG32(data_reg, 0xBFF081B8);
 | 
			
		||||
	WREG32(index_reg, 0x700);
 | 
			
		||||
	WREG32(data_reg, 0x82608010);
 | 
			
		||||
	WREG32(index_reg, 0x701);
 | 
			
		||||
	WREG32(data_reg, 0x85A08600);
 | 
			
		||||
	WREG32(index_reg, 0x702);
 | 
			
		||||
	WREG32(data_reg, 0x800081F0);
 | 
			
		||||
	WREG32(index_reg, 0x800);
 | 
			
		||||
	WREG32(data_reg, 0x8228BFF8);
 | 
			
		||||
	WREG32(index_reg, 0x801);
 | 
			
		||||
	WREG32(data_reg, 0x85E085E0);
 | 
			
		||||
	WREG32(index_reg, 0x802);
 | 
			
		||||
	WREG32(data_reg, 0xBFF88228);
 | 
			
		||||
	WREG32(index_reg, 0x10000);
 | 
			
		||||
	WREG32(data_reg, 0x82A8BF00);
 | 
			
		||||
	WREG32(index_reg, 0x10001);
 | 
			
		||||
	WREG32(data_reg, 0x82A08CC0);
 | 
			
		||||
	WREG32(index_reg, 0x10002);
 | 
			
		||||
	WREG32(data_reg, 0x8008BEF8);
 | 
			
		||||
	WREG32(index_reg, 0x10100);
 | 
			
		||||
	WREG32(data_reg, 0x81F0BF28);
 | 
			
		||||
	WREG32(index_reg, 0x10101);
 | 
			
		||||
	WREG32(data_reg, 0x83608CA0);
 | 
			
		||||
	WREG32(index_reg, 0x10102);
 | 
			
		||||
	WREG32(data_reg, 0x8018BED0);
 | 
			
		||||
	WREG32(index_reg, 0x10200);
 | 
			
		||||
	WREG32(data_reg, 0x8148BF38);
 | 
			
		||||
	WREG32(index_reg, 0x10201);
 | 
			
		||||
	WREG32(data_reg, 0x84408C80);
 | 
			
		||||
	WREG32(index_reg, 0x10202);
 | 
			
		||||
	WREG32(data_reg, 0x8008BEB8);
 | 
			
		||||
	WREG32(index_reg, 0x10300);
 | 
			
		||||
	WREG32(data_reg, 0x80B0BF78);
 | 
			
		||||
	WREG32(index_reg, 0x10301);
 | 
			
		||||
	WREG32(data_reg, 0x85008C20);
 | 
			
		||||
	WREG32(index_reg, 0x10302);
 | 
			
		||||
	WREG32(data_reg, 0x8020BEA0);
 | 
			
		||||
	WREG32(index_reg, 0x10400);
 | 
			
		||||
	WREG32(data_reg, 0x8028BF90);
 | 
			
		||||
	WREG32(index_reg, 0x10401);
 | 
			
		||||
	WREG32(data_reg, 0x85E08BC0);
 | 
			
		||||
	WREG32(index_reg, 0x10402);
 | 
			
		||||
	WREG32(data_reg, 0x8018BE90);
 | 
			
		||||
	WREG32(index_reg, 0x10500);
 | 
			
		||||
	WREG32(data_reg, 0xBFB8BFB0);
 | 
			
		||||
	WREG32(index_reg, 0x10501);
 | 
			
		||||
	WREG32(data_reg, 0x86C08B40);
 | 
			
		||||
	WREG32(index_reg, 0x10502);
 | 
			
		||||
	WREG32(data_reg, 0x8010BE90);
 | 
			
		||||
	WREG32(index_reg, 0x10600);
 | 
			
		||||
	WREG32(data_reg, 0xBF58BFC8);
 | 
			
		||||
	WREG32(index_reg, 0x10601);
 | 
			
		||||
	WREG32(data_reg, 0x87A08AA0);
 | 
			
		||||
	WREG32(index_reg, 0x10602);
 | 
			
		||||
	WREG32(data_reg, 0x8010BE98);
 | 
			
		||||
	WREG32(index_reg, 0x10700);
 | 
			
		||||
	WREG32(data_reg, 0xBF10BFF0);
 | 
			
		||||
	WREG32(index_reg, 0x10701);
 | 
			
		||||
	WREG32(data_reg, 0x886089E0);
 | 
			
		||||
	WREG32(index_reg, 0x10702);
 | 
			
		||||
	WREG32(data_reg, 0x8018BEB0);
 | 
			
		||||
	WREG32(index_reg, 0x10800);
 | 
			
		||||
	WREG32(data_reg, 0xBED8BFE8);
 | 
			
		||||
	WREG32(index_reg, 0x10801);
 | 
			
		||||
	WREG32(data_reg, 0x89408940);
 | 
			
		||||
	WREG32(index_reg, 0x10802);
 | 
			
		||||
	WREG32(data_reg, 0xBFE8BED8);
 | 
			
		||||
	WREG32(index_reg, 0x20000);
 | 
			
		||||
	WREG32(data_reg, 0x80008000);
 | 
			
		||||
	WREG32(index_reg, 0x20001);
 | 
			
		||||
	WREG32(data_reg, 0x90008000);
 | 
			
		||||
	WREG32(index_reg, 0x20002);
 | 
			
		||||
	WREG32(data_reg, 0x80008000);
 | 
			
		||||
	WREG32(index_reg, 0x20003);
 | 
			
		||||
	WREG32(data_reg, 0x80008000);
 | 
			
		||||
	WREG32(index_reg, 0x20100);
 | 
			
		||||
	WREG32(data_reg, 0x80108000);
 | 
			
		||||
	WREG32(index_reg, 0x20101);
 | 
			
		||||
	WREG32(data_reg, 0x8FE0BF70);
 | 
			
		||||
	WREG32(index_reg, 0x20102);
 | 
			
		||||
	WREG32(data_reg, 0xBFE880C0);
 | 
			
		||||
	WREG32(index_reg, 0x20103);
 | 
			
		||||
	WREG32(data_reg, 0x80008000);
 | 
			
		||||
	WREG32(index_reg, 0x20200);
 | 
			
		||||
	WREG32(data_reg, 0x8018BFF8);
 | 
			
		||||
	WREG32(index_reg, 0x20201);
 | 
			
		||||
	WREG32(data_reg, 0x8F80BF08);
 | 
			
		||||
	WREG32(index_reg, 0x20202);
 | 
			
		||||
	WREG32(data_reg, 0xBFD081A0);
 | 
			
		||||
	WREG32(index_reg, 0x20203);
 | 
			
		||||
	WREG32(data_reg, 0xBFF88000);
 | 
			
		||||
	WREG32(index_reg, 0x20300);
 | 
			
		||||
	WREG32(data_reg, 0x80188000);
 | 
			
		||||
	WREG32(index_reg, 0x20301);
 | 
			
		||||
	WREG32(data_reg, 0x8EE0BEC0);
 | 
			
		||||
	WREG32(index_reg, 0x20302);
 | 
			
		||||
	WREG32(data_reg, 0xBFB082A0);
 | 
			
		||||
	WREG32(index_reg, 0x20303);
 | 
			
		||||
	WREG32(data_reg, 0x80008000);
 | 
			
		||||
	WREG32(index_reg, 0x20400);
 | 
			
		||||
	WREG32(data_reg, 0x80188000);
 | 
			
		||||
	WREG32(index_reg, 0x20401);
 | 
			
		||||
	WREG32(data_reg, 0x8E00BEA0);
 | 
			
		||||
	WREG32(index_reg, 0x20402);
 | 
			
		||||
	WREG32(data_reg, 0xBF8883C0);
 | 
			
		||||
	WREG32(index_reg, 0x20403);
 | 
			
		||||
	WREG32(data_reg, 0x80008000);
 | 
			
		||||
	WREG32(index_reg, 0x20500);
 | 
			
		||||
	WREG32(data_reg, 0x80188000);
 | 
			
		||||
	WREG32(index_reg, 0x20501);
 | 
			
		||||
	WREG32(data_reg, 0x8D00BE90);
 | 
			
		||||
	WREG32(index_reg, 0x20502);
 | 
			
		||||
	WREG32(data_reg, 0xBF588500);
 | 
			
		||||
	WREG32(index_reg, 0x20503);
 | 
			
		||||
	WREG32(data_reg, 0x80008008);
 | 
			
		||||
	WREG32(index_reg, 0x20600);
 | 
			
		||||
	WREG32(data_reg, 0x80188000);
 | 
			
		||||
	WREG32(index_reg, 0x20601);
 | 
			
		||||
	WREG32(data_reg, 0x8BC0BE98);
 | 
			
		||||
	WREG32(index_reg, 0x20602);
 | 
			
		||||
	WREG32(data_reg, 0xBF308660);
 | 
			
		||||
	WREG32(index_reg, 0x20603);
 | 
			
		||||
	WREG32(data_reg, 0x80008008);
 | 
			
		||||
	WREG32(index_reg, 0x20700);
 | 
			
		||||
	WREG32(data_reg, 0x80108000);
 | 
			
		||||
	WREG32(index_reg, 0x20701);
 | 
			
		||||
	WREG32(data_reg, 0x8A80BEB0);
 | 
			
		||||
	WREG32(index_reg, 0x20702);
 | 
			
		||||
	WREG32(data_reg, 0xBF0087C0);
 | 
			
		||||
	WREG32(index_reg, 0x20703);
 | 
			
		||||
	WREG32(data_reg, 0x80008008);
 | 
			
		||||
	WREG32(index_reg, 0x20800);
 | 
			
		||||
	WREG32(data_reg, 0x80108000);
 | 
			
		||||
	WREG32(index_reg, 0x20801);
 | 
			
		||||
	WREG32(data_reg, 0x8920BED0);
 | 
			
		||||
	WREG32(index_reg, 0x20802);
 | 
			
		||||
	WREG32(data_reg, 0xBED08920);
 | 
			
		||||
	WREG32(index_reg, 0x20803);
 | 
			
		||||
	WREG32(data_reg, 0x80008010);
 | 
			
		||||
	WREG32(index_reg, 0x30000);
 | 
			
		||||
	WREG32(data_reg, 0x90008000);
 | 
			
		||||
	WREG32(index_reg, 0x30001);
 | 
			
		||||
	WREG32(data_reg, 0x80008000);
 | 
			
		||||
	WREG32(index_reg, 0x30100);
 | 
			
		||||
	WREG32(data_reg, 0x8FE0BF90);
 | 
			
		||||
	WREG32(index_reg, 0x30101);
 | 
			
		||||
	WREG32(data_reg, 0xBFF880A0);
 | 
			
		||||
	WREG32(index_reg, 0x30200);
 | 
			
		||||
	WREG32(data_reg, 0x8F60BF40);
 | 
			
		||||
	WREG32(index_reg, 0x30201);
 | 
			
		||||
	WREG32(data_reg, 0xBFE88180);
 | 
			
		||||
	WREG32(index_reg, 0x30300);
 | 
			
		||||
	WREG32(data_reg, 0x8EC0BF00);
 | 
			
		||||
	WREG32(index_reg, 0x30301);
 | 
			
		||||
	WREG32(data_reg, 0xBFC88280);
 | 
			
		||||
	WREG32(index_reg, 0x30400);
 | 
			
		||||
	WREG32(data_reg, 0x8DE0BEE0);
 | 
			
		||||
	WREG32(index_reg, 0x30401);
 | 
			
		||||
	WREG32(data_reg, 0xBFA083A0);
 | 
			
		||||
	WREG32(index_reg, 0x30500);
 | 
			
		||||
	WREG32(data_reg, 0x8CE0BED0);
 | 
			
		||||
	WREG32(index_reg, 0x30501);
 | 
			
		||||
	WREG32(data_reg, 0xBF7884E0);
 | 
			
		||||
	WREG32(index_reg, 0x30600);
 | 
			
		||||
	WREG32(data_reg, 0x8BA0BED8);
 | 
			
		||||
	WREG32(index_reg, 0x30601);
 | 
			
		||||
	WREG32(data_reg, 0xBF508640);
 | 
			
		||||
	WREG32(index_reg, 0x30700);
 | 
			
		||||
	WREG32(data_reg, 0x8A60BEE8);
 | 
			
		||||
	WREG32(index_reg, 0x30701);
 | 
			
		||||
	WREG32(data_reg, 0xBF2087A0);
 | 
			
		||||
	WREG32(index_reg, 0x30800);
 | 
			
		||||
	WREG32(data_reg, 0x8900BF00);
 | 
			
		||||
	WREG32(index_reg, 0x30801);
 | 
			
		||||
	WREG32(data_reg, 0xBF008900);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct rv515_watermark {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue