aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_atombios.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_atombios.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c114
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
1279static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct 1279bool 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
1315union 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
1321bool 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
1324union lvds_info { 1392union 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