Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1267 → Rev 1268

/drivers/video/drm/radeon/radeon_atombios.c
46,7 → 46,8
uint32_t supported_device,
int connector_type,
struct radeon_i2c_bus_rec *i2c_bus,
bool linkb, uint32_t igp_lane_info);
bool linkb, uint32_t igp_lane_info,
uint16_t connector_object_id);
 
/* from radeon_legacy_encoder.c */
extern void
193,6 → 194,23
DRM_MODE_CONNECTOR_DisplayPort
};
 
const uint16_t supported_devices_connector_object_id_convert[] = {
CONNECTOR_OBJECT_ID_NONE,
CONNECTOR_OBJECT_ID_VGA,
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, /* not all boards support DL */
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D, /* not all boards support DL */
CONNECTOR_OBJECT_ID_VGA, /* technically DVI-A */
CONNECTOR_OBJECT_ID_COMPOSITE,
CONNECTOR_OBJECT_ID_SVIDEO,
CONNECTOR_OBJECT_ID_LVDS,
CONNECTOR_OBJECT_ID_9PIN_DIN,
CONNECTOR_OBJECT_ID_9PIN_DIN,
CONNECTOR_OBJECT_ID_DISPLAYPORT,
CONNECTOR_OBJECT_ID_HDMI_TYPE_A,
CONNECTOR_OBJECT_ID_HDMI_TYPE_B,
CONNECTOR_OBJECT_ID_SVIDEO
};
 
const int object_connector_convert[] = {
DRM_MODE_CONNECTOR_Unknown,
DRM_MODE_CONNECTOR_DVII,
229,7 → 247,7
ATOM_OBJECT_HEADER *obj_header;
int i, j, path_size, device_support;
int connector_type;
uint16_t igp_lane_info, conn_id;
uint16_t igp_lane_info, conn_id, connector_object_id;
bool linkb;
struct radeon_i2c_bus_rec ddc_bus;
 
277,7 → 295,8
ATOM_DEVICE_CV_SUPPORT)
continue;
 
if ((rdev->family == CHIP_RS780) &&
/* IGP chips */
if ((rdev->flags & RADEON_IS_IGP) &&
(con_obj_id ==
CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) {
uint16_t igp_offset = 0;
311,6 → 330,7
connector_type =
object_connector_convert
[ct];
connector_object_id = ct;
igp_lane_info =
slot_config & 0xffff;
} else
321,6 → 341,7
igp_lane_info = 0;
connector_type =
object_connector_convert[con_obj_id];
connector_object_id = con_obj_id;
}
 
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
425,7 → 446,8
le16_to_cpu(path->
usDeviceTag),
connector_type, &ddc_bus,
linkb, igp_lane_info);
linkb, igp_lane_info,
connector_object_id);
 
}
}
435,6 → 457,45
return true;
}
 
static uint16_t atombios_get_connector_object_id(struct drm_device *dev,
int connector_type,
uint16_t devices)
{
struct radeon_device *rdev = dev->dev_private;
 
if (rdev->flags & RADEON_IS_IGP) {
return supported_devices_connector_object_id_convert
[connector_type];
} else if (((connector_type == DRM_MODE_CONNECTOR_DVII) ||
(connector_type == DRM_MODE_CONNECTOR_DVID)) &&
(devices & ATOM_DEVICE_DFP2_SUPPORT)) {
struct radeon_mode_info *mode_info = &rdev->mode_info;
struct atom_context *ctx = mode_info->atom_context;
int index = GetIndexIntoMasterTable(DATA, XTMDS_Info);
uint16_t size, data_offset;
uint8_t frev, crev;
ATOM_XTMDS_INFO *xtmds;
 
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
xtmds = (ATOM_XTMDS_INFO *)(ctx->bios + data_offset);
 
if (xtmds->ucSupportedLink & ATOM_XTMDS_SUPPORTED_DUALLINK) {
if (connector_type == DRM_MODE_CONNECTOR_DVII)
return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I;
else
return CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D;
} else {
if (connector_type == DRM_MODE_CONNECTOR_DVII)
return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I;
else
return CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D;
}
} else {
return supported_devices_connector_object_id_convert
[connector_type];
}
}
 
struct bios_connector {
bool valid;
uint16_t line_mux;
593,7 → 654,11
 
/* add the connectors */
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
if (bios_connectors[i].valid)
if (bios_connectors[i].valid) {
uint16_t connector_object_id =
atombios_get_connector_object_id(dev,
bios_connectors[i].connector_type,
bios_connectors[i].devices);
radeon_add_atom_connector(dev,
bios_connectors[i].line_mux,
bios_connectors[i].devices,
600,8 → 665,10
bios_connectors[i].
connector_type,
&bios_connectors[i].ddc_bus,
false, 0);
false, 0,
connector_object_id);
}
}
 
radeon_link_encoder_connector(dev);
 
641,8 → 708,12
le16_to_cpu(firmware_info->info.usReferenceClock);
p1pll->reference_div = 0;
 
if (crev < 2)
p1pll->pll_out_min =
le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
else
p1pll->pll_out_min =
le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
p1pll->pll_out_max =
le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
 
651,6 → 722,16
p1pll->pll_out_min = 64800;
else
p1pll->pll_out_min = 20000;
} else if (p1pll->pll_out_min > 64800) {
/* Limiting the pll output range is a good thing generally as
* it limits the number of possible pll combinations for a given
* frequency presumably to the ones that work best on each card.
* However, certain duallink DVI monitors seem to like
* pll combinations that would be limited by this at least on
* pre-DCE 3.0 r6xx hardware. This might need to be adjusted per
* family.
*/
p1pll->pll_out_min = 64800;
}
 
p1pll->pll_in_min =
767,6 → 848,46
return false;
}
 
static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct
radeon_encoder
*encoder,
int id)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_mode_info *mode_info = &rdev->mode_info;
int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
uint16_t data_offset;
struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
uint8_t frev, crev;
struct radeon_atom_ss *ss = NULL;
 
if (id > ATOM_MAX_SS_ENTRY)
return NULL;
 
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
&crev, &data_offset);
 
ss_info =
(struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset);
 
if (ss_info) {
ss =
kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL);
 
if (!ss)
return NULL;
 
ss->percentage = le16_to_cpu(ss_info->asSS_Info[id].usSpreadSpectrumPercentage);
ss->type = ss_info->asSS_Info[id].ucSpreadSpectrumType;
ss->step = ss_info->asSS_Info[id].ucSS_Step;
ss->delay = ss_info->asSS_Info[id].ucSS_Delay;
ss->range = ss_info->asSS_Info[id].ucSS_Range;
ss->refdiv = ss_info->asSS_Info[id].ucRecommendedRef_Div;
}
return ss;
}
 
union lvds_info {
struct _ATOM_LVDS_INFO info;
struct _ATOM_LVDS_INFO_V12 info_12;
798,28 → 919,32
if (!lvds)
return NULL;
 
lvds->native_mode.dotclock =
lvds->native_mode.clock =
le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
lvds->native_mode.panel_xres =
lvds->native_mode.hdisplay =
le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
lvds->native_mode.panel_yres =
lvds->native_mode.vdisplay =
le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
lvds->native_mode.hblank =
lvds->native_mode.htotal = lvds->native_mode.hdisplay +
le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
lvds->native_mode.hoverplus =
lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
lvds->native_mode.hsync_width =
lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
lvds->native_mode.vblank =
lvds->native_mode.vtotal = lvds->native_mode.vdisplay +
le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
lvds->native_mode.voverplus =
le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
lvds->native_mode.vsync_width =
lvds->native_mode.vsync_start = lvds->native_mode.vdisplay +
le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
lvds->native_mode.vsync_end = lvds->native_mode.vsync_start +
le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
lvds->panel_pwr_delay =
le16_to_cpu(lvds_info->info.usOffDelayInMs);
lvds->lvds_misc = lvds_info->info.ucLVDS_Misc;
/* set crtc values */
drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
 
lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id);
 
encoder->native_mode = lvds->native_mode;
}
return lvds;
857,8 → 982,7
}
 
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 drm_display_mode *mode)
{
struct radeon_mode_info *mode_info = &rdev->mode_info;
ATOM_ANALOG_TV_INFO *tv_info;
866,7 → 990,7
ATOM_DTD_FORMAT *dtd_timings;
int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
u8 frev, crev;
uint16_t data_offset;
u16 data_offset, misc;
 
atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
 
876,28 → 1000,37
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);
mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
mode->crtc_hsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart) +
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);
mode->crtc_vtotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
mode->crtc_vdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
mode->crtc_vsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
mode->crtc_vsync_end = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart) +
le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
 
crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
mode->flags = 0;
misc = le16_to_cpu(tv_info->aModeTimings[index].susModeMiscInfo.usAccess);
if (misc & ATOM_VSYNC_POLARITY)
mode->flags |= DRM_MODE_FLAG_NVSYNC;
if (misc & ATOM_HSYNC_POLARITY)
mode->flags |= DRM_MODE_FLAG_NHSYNC;
if (misc & ATOM_COMPOSITESYNC)
mode->flags |= DRM_MODE_FLAG_CSYNC;
if (misc & ATOM_INTERLACE)
mode->flags |= DRM_MODE_FLAG_INTERLACE;
if (misc & ATOM_DOUBLE_CLOCK_MODE)
mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 
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;
mode->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;
mode->crtc_htotal -= 1;
mode->crtc_vtotal -= 1;
}
break;
case 2:
906,17 → 1039,36
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);
mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
le16_to_cpu(dtd_timings->usHBlanking_Time);
mode->crtc_hdisplay = le16_to_cpu(dtd_timings->usHActive);
mode->crtc_hsync_start = le16_to_cpu(dtd_timings->usHActive) +
le16_to_cpu(dtd_timings->usHSyncOffset);
mode->crtc_hsync_end = mode->crtc_hsync_start +
le16_to_cpu(dtd_timings->usHSyncWidth);
 
crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
*pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
mode->crtc_vtotal = le16_to_cpu(dtd_timings->usVActive) +
le16_to_cpu(dtd_timings->usVBlanking_Time);
mode->crtc_vdisplay = le16_to_cpu(dtd_timings->usVActive);
mode->crtc_vsync_start = le16_to_cpu(dtd_timings->usVActive) +
le16_to_cpu(dtd_timings->usVSyncOffset);
mode->crtc_vsync_end = mode->crtc_vsync_start +
le16_to_cpu(dtd_timings->usVSyncWidth);
 
mode->flags = 0;
misc = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
if (misc & ATOM_VSYNC_POLARITY)
mode->flags |= DRM_MODE_FLAG_NVSYNC;
if (misc & ATOM_HSYNC_POLARITY)
mode->flags |= DRM_MODE_FLAG_NHSYNC;
if (misc & ATOM_COMPOSITESYNC)
mode->flags |= DRM_MODE_FLAG_CSYNC;
if (misc & ATOM_INTERLACE)
mode->flags |= DRM_MODE_FLAG_INTERLACE;
if (misc & ATOM_DOUBLE_CLOCK_MODE)
mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 
mode->clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
break;
}
return true;
981,6 → 1133,24
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
 
uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
{
GET_ENGINE_CLOCK_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
 
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
return args.ulReturnEngineClock;
}
 
uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev)
{
GET_MEMORY_CLOCK_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
 
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
return args.ulReturnMemoryClock;
}
 
void radeon_atom_set_engine_clock(struct radeon_device *rdev,
uint32_t eng_clock)
{