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
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 New Issue