diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_atombios.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 114 |
1 files changed, 91 insertions, 23 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 89ce9b6d89d9..2b44cbcb031b 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -1276,36 +1276,27 @@ bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, | |||
1276 | return false; | 1276 | return false; |
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct | 1279 | bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, |
1280 | radeon_encoder | 1280 | struct radeon_atom_ss *ss, |
1281 | *encoder, | 1281 | int id) |
1282 | int id) | ||
1283 | { | 1282 | { |
1284 | struct drm_device *dev = encoder->base.dev; | ||
1285 | struct radeon_device *rdev = dev->dev_private; | ||
1286 | struct radeon_mode_info *mode_info = &rdev->mode_info; | 1283 | struct radeon_mode_info *mode_info = &rdev->mode_info; |
1287 | int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info); | 1284 | int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info); |
1288 | uint16_t data_offset; | 1285 | uint16_t data_offset, size; |
1289 | struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; | 1286 | struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; |
1290 | uint8_t frev, crev; | 1287 | uint8_t frev, crev; |
1291 | struct radeon_atom_ss *ss = NULL; | 1288 | int i, num_indices; |
1292 | int i; | ||
1293 | |||
1294 | if (id > ATOM_MAX_SS_ENTRY) | ||
1295 | return NULL; | ||
1296 | 1289 | ||
1297 | if (atom_parse_data_header(mode_info->atom_context, index, NULL, | 1290 | memset(ss, 0, sizeof(struct radeon_atom_ss)); |
1291 | if (atom_parse_data_header(mode_info->atom_context, index, &size, | ||
1298 | &frev, &crev, &data_offset)) { | 1292 | &frev, &crev, &data_offset)) { |
1299 | ss_info = | 1293 | ss_info = |
1300 | (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset); | 1294 | (struct _ATOM_SPREAD_SPECTRUM_INFO *)(mode_info->atom_context->bios + data_offset); |
1301 | 1295 | ||
1302 | ss = | 1296 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / |
1303 | kzalloc(sizeof(struct radeon_atom_ss), GFP_KERNEL); | 1297 | sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); |
1304 | |||
1305 | if (!ss) | ||
1306 | return NULL; | ||
1307 | 1298 | ||
1308 | for (i = 0; i < ATOM_MAX_SS_ENTRY; i++) { | 1299 | for (i = 0; i < num_indices; i++) { |
1309 | if (ss_info->asSS_Info[i].ucSS_Id == id) { | 1300 | if (ss_info->asSS_Info[i].ucSS_Id == id) { |
1310 | ss->percentage = | 1301 | ss->percentage = |
1311 | le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); | 1302 | le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); |
@@ -1314,11 +1305,88 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct | |||
1314 | ss->delay = ss_info->asSS_Info[i].ucSS_Delay; | 1305 | ss->delay = ss_info->asSS_Info[i].ucSS_Delay; |
1315 | ss->range = ss_info->asSS_Info[i].ucSS_Range; | 1306 | ss->range = ss_info->asSS_Info[i].ucSS_Range; |
1316 | ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; | 1307 | ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; |
1317 | break; | 1308 | return true; |
1309 | } | ||
1310 | } | ||
1311 | } | ||
1312 | return false; | ||
1313 | } | ||
1314 | |||
1315 | union asic_ss_info { | ||
1316 | struct _ATOM_ASIC_INTERNAL_SS_INFO info; | ||
1317 | struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; | ||
1318 | struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3; | ||
1319 | }; | ||
1320 | |||
1321 | bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, | ||
1322 | struct radeon_atom_ss *ss, | ||
1323 | int id, u32 clock) | ||
1324 | { | ||
1325 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
1326 | int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info); | ||
1327 | uint16_t data_offset, size; | ||
1328 | union asic_ss_info *ss_info; | ||
1329 | uint8_t frev, crev; | ||
1330 | int i, num_indices; | ||
1331 | |||
1332 | memset(ss, 0, sizeof(struct radeon_atom_ss)); | ||
1333 | if (atom_parse_data_header(mode_info->atom_context, index, &size, | ||
1334 | &frev, &crev, &data_offset)) { | ||
1335 | |||
1336 | ss_info = | ||
1337 | (union asic_ss_info *)(mode_info->atom_context->bios + data_offset); | ||
1338 | |||
1339 | switch (frev) { | ||
1340 | case 1: | ||
1341 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
1342 | sizeof(ATOM_ASIC_SS_ASSIGNMENT); | ||
1343 | |||
1344 | for (i = 0; i < num_indices; i++) { | ||
1345 | if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) && | ||
1346 | (clock <= ss_info->info.asSpreadSpectrum[i].ulTargetClockRange)) { | ||
1347 | ss->percentage = | ||
1348 | le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | ||
1349 | ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode; | ||
1350 | ss->rate = le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz); | ||
1351 | return true; | ||
1352 | } | ||
1318 | } | 1353 | } |
1354 | break; | ||
1355 | case 2: | ||
1356 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
1357 | sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); | ||
1358 | for (i = 0; i < num_indices; i++) { | ||
1359 | if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) && | ||
1360 | (clock <= ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange)) { | ||
1361 | ss->percentage = | ||
1362 | le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | ||
1363 | ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode; | ||
1364 | ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz); | ||
1365 | return true; | ||
1366 | } | ||
1367 | } | ||
1368 | break; | ||
1369 | case 3: | ||
1370 | num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / | ||
1371 | sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); | ||
1372 | for (i = 0; i < num_indices; i++) { | ||
1373 | if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) && | ||
1374 | (clock <= ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange)) { | ||
1375 | ss->percentage = | ||
1376 | le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | ||
1377 | ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; | ||
1378 | ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); | ||
1379 | return true; | ||
1380 | } | ||
1381 | } | ||
1382 | break; | ||
1383 | default: | ||
1384 | DRM_ERROR("Unsupported ASIC_InternalSS_Info table: %d %d\n", frev, crev); | ||
1385 | break; | ||
1319 | } | 1386 | } |
1387 | |||
1320 | } | 1388 | } |
1321 | return ss; | 1389 | return false; |
1322 | } | 1390 | } |
1323 | 1391 | ||
1324 | union lvds_info { | 1392 | union lvds_info { |
@@ -1370,7 +1438,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | |||
1370 | le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); | 1438 | le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); |
1371 | lvds->panel_pwr_delay = | 1439 | lvds->panel_pwr_delay = |
1372 | le16_to_cpu(lvds_info->info.usOffDelayInMs); | 1440 | le16_to_cpu(lvds_info->info.usOffDelayInMs); |
1373 | lvds->lvds_misc = lvds_info->info.ucLVDS_Misc; | 1441 | lvds->lcd_misc = lvds_info->info.ucLVDS_Misc; |
1374 | 1442 | ||
1375 | misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess); | 1443 | misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess); |
1376 | if (misc & ATOM_VSYNC_POLARITY) | 1444 | if (misc & ATOM_VSYNC_POLARITY) |
@@ -1387,7 +1455,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | |||
1387 | /* set crtc values */ | 1455 | /* set crtc values */ |
1388 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); | 1456 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); |
1389 | 1457 | ||
1390 | lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id); | 1458 | lvds->lcd_ss_id = lvds_info->info.ucSS_Id; |
1391 | 1459 | ||
1392 | encoder->native_mode = lvds->native_mode; | 1460 | encoder->native_mode = lvds->native_mode; |
1393 | 1461 | ||