diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_atombios.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 1246 |
1 files changed, 755 insertions, 491 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index bc5a2c3382d9..1573202a6418 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -37,7 +37,7 @@ radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, | |||
37 | extern void radeon_link_encoder_connector(struct drm_device *dev); | 37 | extern void radeon_link_encoder_connector(struct drm_device *dev); |
38 | extern void | 38 | extern void |
39 | radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, | 39 | radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, |
40 | uint32_t supported_device); | 40 | uint32_t supported_device, u16 caps); |
41 | 41 | ||
42 | /* from radeon_connector.c */ | 42 | /* from radeon_connector.c */ |
43 | extern void | 43 | extern void |
@@ -313,7 +313,6 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
313 | uint16_t *line_mux, | 313 | uint16_t *line_mux, |
314 | struct radeon_hpd *hpd) | 314 | struct radeon_hpd *hpd) |
315 | { | 315 | { |
316 | struct radeon_device *rdev = dev->dev_private; | ||
317 | 316 | ||
318 | /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ | 317 | /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ |
319 | if ((dev->pdev->device == 0x791e) && | 318 | if ((dev->pdev->device == 0x791e) && |
@@ -388,6 +387,17 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
388 | *line_mux = 0x90; | 387 | *line_mux = 0x90; |
389 | } | 388 | } |
390 | 389 | ||
390 | /* mac rv630 */ | ||
391 | if ((dev->pdev->device == 0x9588) && | ||
392 | (dev->pdev->subsystem_vendor == 0x106b) && | ||
393 | (dev->pdev->subsystem_device == 0x00a6)) { | ||
394 | if ((supported_device == ATOM_DEVICE_TV1_SUPPORT) && | ||
395 | (*connector_type == DRM_MODE_CONNECTOR_DVII)) { | ||
396 | *connector_type = DRM_MODE_CONNECTOR_9PinDIN; | ||
397 | *line_mux = CONNECTOR_7PIN_DIN_ENUM_ID1; | ||
398 | } | ||
399 | } | ||
400 | |||
391 | /* ASUS HD 3600 XT board lists the DVI port as HDMI */ | 401 | /* ASUS HD 3600 XT board lists the DVI port as HDMI */ |
392 | if ((dev->pdev->device == 0x9598) && | 402 | if ((dev->pdev->device == 0x9598) && |
393 | (dev->pdev->subsystem_vendor == 0x1043) && | 403 | (dev->pdev->subsystem_vendor == 0x1043) && |
@@ -425,21 +435,23 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, | |||
425 | } | 435 | } |
426 | } | 436 | } |
427 | 437 | ||
428 | /* Acer laptop reports DVI-D as DVI-I and hpd pins reversed */ | 438 | /* Acer laptop (Acer TravelMate 5730G) has an HDMI port |
439 | * on the laptop and a DVI port on the docking station and | ||
440 | * both share the same encoder, hpd pin, and ddc line. | ||
441 | * So while the bios table is technically correct, | ||
442 | * we drop the DVI port here since xrandr has no concept of | ||
443 | * encoders and will try and drive both connectors | ||
444 | * with different crtcs which isn't possible on the hardware | ||
445 | * side and leaves no crtcs for LVDS or VGA. | ||
446 | */ | ||
429 | if ((dev->pdev->device == 0x95c4) && | 447 | if ((dev->pdev->device == 0x95c4) && |
430 | (dev->pdev->subsystem_vendor == 0x1025) && | 448 | (dev->pdev->subsystem_vendor == 0x1025) && |
431 | (dev->pdev->subsystem_device == 0x013c)) { | 449 | (dev->pdev->subsystem_device == 0x013c)) { |
432 | struct radeon_gpio_rec gpio; | ||
433 | |||
434 | if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && | 450 | if ((*connector_type == DRM_MODE_CONNECTOR_DVII) && |
435 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { | 451 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { |
436 | gpio = radeon_lookup_gpio(rdev, 6); | 452 | /* actually it's a DVI-D port not DVI-I */ |
437 | *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); | ||
438 | *connector_type = DRM_MODE_CONNECTOR_DVID; | 453 | *connector_type = DRM_MODE_CONNECTOR_DVID; |
439 | } else if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && | 454 | return false; |
440 | (supported_device == ATOM_DEVICE_DFP1_SUPPORT)) { | ||
441 | gpio = radeon_lookup_gpio(rdev, 7); | ||
442 | *hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio); | ||
443 | } | 455 | } |
444 | } | 456 | } |
445 | 457 | ||
@@ -525,6 +537,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
525 | u16 size, data_offset; | 537 | u16 size, data_offset; |
526 | u8 frev, crev; | 538 | u8 frev, crev; |
527 | ATOM_CONNECTOR_OBJECT_TABLE *con_obj; | 539 | ATOM_CONNECTOR_OBJECT_TABLE *con_obj; |
540 | ATOM_ENCODER_OBJECT_TABLE *enc_obj; | ||
528 | ATOM_OBJECT_TABLE *router_obj; | 541 | ATOM_OBJECT_TABLE *router_obj; |
529 | ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; | 542 | ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; |
530 | ATOM_OBJECT_HEADER *obj_header; | 543 | ATOM_OBJECT_HEADER *obj_header; |
@@ -549,6 +562,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
549 | con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) | 562 | con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) |
550 | (ctx->bios + data_offset + | 563 | (ctx->bios + data_offset + |
551 | le16_to_cpu(obj_header->usConnectorObjectTableOffset)); | 564 | le16_to_cpu(obj_header->usConnectorObjectTableOffset)); |
565 | enc_obj = (ATOM_ENCODER_OBJECT_TABLE *) | ||
566 | (ctx->bios + data_offset + | ||
567 | le16_to_cpu(obj_header->usEncoderObjectTableOffset)); | ||
552 | router_obj = (ATOM_OBJECT_TABLE *) | 568 | router_obj = (ATOM_OBJECT_TABLE *) |
553 | (ctx->bios + data_offset + | 569 | (ctx->bios + data_offset + |
554 | le16_to_cpu(obj_header->usRouterObjectTableOffset)); | 570 | le16_to_cpu(obj_header->usRouterObjectTableOffset)); |
@@ -654,14 +670,35 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
654 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; | 670 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; |
655 | 671 | ||
656 | if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { | 672 | if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { |
657 | u16 encoder_obj = le16_to_cpu(path->usGraphicObjIds[j]); | 673 | for (k = 0; k < enc_obj->ucNumberOfObjects; k++) { |
658 | 674 | u16 encoder_obj = le16_to_cpu(enc_obj->asObjects[k].usObjectID); | |
659 | radeon_add_atom_encoder(dev, | 675 | if (le16_to_cpu(path->usGraphicObjIds[j]) == encoder_obj) { |
660 | encoder_obj, | 676 | ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *) |
661 | le16_to_cpu | 677 | (ctx->bios + data_offset + |
662 | (path-> | 678 | le16_to_cpu(enc_obj->asObjects[k].usRecordOffset)); |
663 | usDeviceTag)); | 679 | ATOM_ENCODER_CAP_RECORD *cap_record; |
680 | u16 caps = 0; | ||
664 | 681 | ||
682 | while (record->ucRecordType > 0 && | ||
683 | record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { | ||
684 | switch (record->ucRecordType) { | ||
685 | case ATOM_ENCODER_CAP_RECORD_TYPE: | ||
686 | cap_record =(ATOM_ENCODER_CAP_RECORD *) | ||
687 | record; | ||
688 | caps = le16_to_cpu(cap_record->usEncoderCap); | ||
689 | break; | ||
690 | } | ||
691 | record = (ATOM_COMMON_RECORD_HEADER *) | ||
692 | ((char *)record + record->ucRecordSize); | ||
693 | } | ||
694 | radeon_add_atom_encoder(dev, | ||
695 | encoder_obj, | ||
696 | le16_to_cpu | ||
697 | (path-> | ||
698 | usDeviceTag), | ||
699 | caps); | ||
700 | } | ||
701 | } | ||
665 | } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { | 702 | } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) { |
666 | for (k = 0; k < router_obj->ucNumberOfObjects; k++) { | 703 | for (k = 0; k < router_obj->ucNumberOfObjects; k++) { |
667 | u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID); | 704 | u16 router_obj_id = le16_to_cpu(router_obj->asObjects[k].usObjectID); |
@@ -995,7 +1032,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
995 | radeon_get_encoder_enum(dev, | 1032 | radeon_get_encoder_enum(dev, |
996 | (1 << i), | 1033 | (1 << i), |
997 | dac), | 1034 | dac), |
998 | (1 << i)); | 1035 | (1 << i), |
1036 | 0); | ||
999 | else | 1037 | else |
1000 | radeon_add_legacy_encoder(dev, | 1038 | radeon_add_legacy_encoder(dev, |
1001 | radeon_get_encoder_enum(dev, | 1039 | radeon_get_encoder_enum(dev, |
@@ -1074,6 +1112,7 @@ union firmware_info { | |||
1074 | ATOM_FIRMWARE_INFO_V1_3 info_13; | 1112 | ATOM_FIRMWARE_INFO_V1_3 info_13; |
1075 | ATOM_FIRMWARE_INFO_V1_4 info_14; | 1113 | ATOM_FIRMWARE_INFO_V1_4 info_14; |
1076 | ATOM_FIRMWARE_INFO_V2_1 info_21; | 1114 | ATOM_FIRMWARE_INFO_V2_1 info_21; |
1115 | ATOM_FIRMWARE_INFO_V2_2 info_22; | ||
1077 | }; | 1116 | }; |
1078 | 1117 | ||
1079 | bool radeon_atom_get_clock_info(struct drm_device *dev) | 1118 | bool radeon_atom_get_clock_info(struct drm_device *dev) |
@@ -1148,8 +1187,12 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) | |||
1148 | *p2pll = *p1pll; | 1187 | *p2pll = *p1pll; |
1149 | 1188 | ||
1150 | /* system clock */ | 1189 | /* system clock */ |
1151 | spll->reference_freq = | 1190 | if (ASIC_IS_DCE4(rdev)) |
1152 | le16_to_cpu(firmware_info->info.usReferenceClock); | 1191 | spll->reference_freq = |
1192 | le16_to_cpu(firmware_info->info_21.usCoreReferenceClock); | ||
1193 | else | ||
1194 | spll->reference_freq = | ||
1195 | le16_to_cpu(firmware_info->info.usReferenceClock); | ||
1153 | spll->reference_div = 0; | 1196 | spll->reference_div = 0; |
1154 | 1197 | ||
1155 | spll->pll_out_min = | 1198 | spll->pll_out_min = |
@@ -1171,8 +1214,12 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) | |||
1171 | le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input); | 1214 | le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input); |
1172 | 1215 | ||
1173 | /* memory clock */ | 1216 | /* memory clock */ |
1174 | mpll->reference_freq = | 1217 | if (ASIC_IS_DCE4(rdev)) |
1175 | le16_to_cpu(firmware_info->info.usReferenceClock); | 1218 | mpll->reference_freq = |
1219 | le16_to_cpu(firmware_info->info_21.usMemoryReferenceClock); | ||
1220 | else | ||
1221 | mpll->reference_freq = | ||
1222 | le16_to_cpu(firmware_info->info.usReferenceClock); | ||
1176 | mpll->reference_div = 0; | 1223 | mpll->reference_div = 0; |
1177 | 1224 | ||
1178 | mpll->pll_out_min = | 1225 | mpll->pll_out_min = |
@@ -1201,8 +1248,12 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) | |||
1201 | if (ASIC_IS_DCE4(rdev)) { | 1248 | if (ASIC_IS_DCE4(rdev)) { |
1202 | rdev->clock.default_dispclk = | 1249 | rdev->clock.default_dispclk = |
1203 | le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq); | 1250 | le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq); |
1204 | if (rdev->clock.default_dispclk == 0) | 1251 | if (rdev->clock.default_dispclk == 0) { |
1205 | rdev->clock.default_dispclk = 60000; /* 600 Mhz */ | 1252 | if (ASIC_IS_DCE5(rdev)) |
1253 | rdev->clock.default_dispclk = 54000; /* 540 Mhz */ | ||
1254 | else | ||
1255 | rdev->clock.default_dispclk = 60000; /* 600 Mhz */ | ||
1256 | } | ||
1206 | rdev->clock.dp_extclk = | 1257 | rdev->clock.dp_extclk = |
1207 | le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq); | 1258 | le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq); |
1208 | } | 1259 | } |
@@ -1337,6 +1388,43 @@ bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev, | |||
1337 | return false; | 1388 | return false; |
1338 | } | 1389 | } |
1339 | 1390 | ||
1391 | static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev, | ||
1392 | struct radeon_atom_ss *ss, | ||
1393 | int id) | ||
1394 | { | ||
1395 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
1396 | int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); | ||
1397 | u16 data_offset, size; | ||
1398 | struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; | ||
1399 | u8 frev, crev; | ||
1400 | u16 percentage = 0, rate = 0; | ||
1401 | |||
1402 | /* get any igp specific overrides */ | ||
1403 | if (atom_parse_data_header(mode_info->atom_context, index, &size, | ||
1404 | &frev, &crev, &data_offset)) { | ||
1405 | igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) | ||
1406 | (mode_info->atom_context->bios + data_offset); | ||
1407 | switch (id) { | ||
1408 | case ASIC_INTERNAL_SS_ON_TMDS: | ||
1409 | percentage = le16_to_cpu(igp_info->usDVISSPercentage); | ||
1410 | rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); | ||
1411 | break; | ||
1412 | case ASIC_INTERNAL_SS_ON_HDMI: | ||
1413 | percentage = le16_to_cpu(igp_info->usHDMISSPercentage); | ||
1414 | rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); | ||
1415 | break; | ||
1416 | case ASIC_INTERNAL_SS_ON_LVDS: | ||
1417 | percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); | ||
1418 | rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); | ||
1419 | break; | ||
1420 | } | ||
1421 | if (percentage) | ||
1422 | ss->percentage = percentage; | ||
1423 | if (rate) | ||
1424 | ss->rate = rate; | ||
1425 | } | ||
1426 | } | ||
1427 | |||
1340 | union asic_ss_info { | 1428 | union asic_ss_info { |
1341 | struct _ATOM_ASIC_INTERNAL_SS_INFO info; | 1429 | struct _ATOM_ASIC_INTERNAL_SS_INFO info; |
1342 | struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; | 1430 | struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; |
@@ -1401,6 +1489,8 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev, | |||
1401 | le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); | 1489 | le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); |
1402 | ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; | 1490 | ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; |
1403 | ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); | 1491 | ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); |
1492 | if (rdev->flags & RADEON_IS_IGP) | ||
1493 | radeon_atombios_get_igp_ss_overrides(rdev, ss, id); | ||
1404 | return true; | 1494 | return true; |
1405 | } | 1495 | } |
1406 | } | 1496 | } |
@@ -1477,6 +1567,9 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | |||
1477 | if (misc & ATOM_DOUBLE_CLOCK_MODE) | 1567 | if (misc & ATOM_DOUBLE_CLOCK_MODE) |
1478 | lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN; | 1568 | lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN; |
1479 | 1569 | ||
1570 | lvds->native_mode.width_mm = lvds_info->info.sLCDTiming.usImageHSize; | ||
1571 | lvds->native_mode.height_mm = lvds_info->info.sLCDTiming.usImageVSize; | ||
1572 | |||
1480 | /* set crtc values */ | 1573 | /* set crtc values */ |
1481 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); | 1574 | drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V); |
1482 | 1575 | ||
@@ -1489,6 +1582,59 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | |||
1489 | else | 1582 | else |
1490 | lvds->linkb = false; | 1583 | lvds->linkb = false; |
1491 | 1584 | ||
1585 | /* parse the lcd record table */ | ||
1586 | if (lvds_info->info.usModePatchTableOffset) { | ||
1587 | ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record; | ||
1588 | ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record; | ||
1589 | bool bad_record = false; | ||
1590 | u8 *record = (u8 *)(mode_info->atom_context->bios + | ||
1591 | data_offset + | ||
1592 | lvds_info->info.usModePatchTableOffset); | ||
1593 | while (*record != ATOM_RECORD_END_TYPE) { | ||
1594 | switch (*record) { | ||
1595 | case LCD_MODE_PATCH_RECORD_MODE_TYPE: | ||
1596 | record += sizeof(ATOM_PATCH_RECORD_MODE); | ||
1597 | break; | ||
1598 | case LCD_RTS_RECORD_TYPE: | ||
1599 | record += sizeof(ATOM_LCD_RTS_RECORD); | ||
1600 | break; | ||
1601 | case LCD_CAP_RECORD_TYPE: | ||
1602 | record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); | ||
1603 | break; | ||
1604 | case LCD_FAKE_EDID_PATCH_RECORD_TYPE: | ||
1605 | fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; | ||
1606 | if (fake_edid_record->ucFakeEDIDLength) { | ||
1607 | struct edid *edid; | ||
1608 | int edid_size = | ||
1609 | max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength); | ||
1610 | edid = kmalloc(edid_size, GFP_KERNEL); | ||
1611 | if (edid) { | ||
1612 | memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], | ||
1613 | fake_edid_record->ucFakeEDIDLength); | ||
1614 | |||
1615 | if (drm_edid_is_valid(edid)) | ||
1616 | rdev->mode_info.bios_hardcoded_edid = edid; | ||
1617 | else | ||
1618 | kfree(edid); | ||
1619 | } | ||
1620 | } | ||
1621 | record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); | ||
1622 | break; | ||
1623 | case LCD_PANEL_RESOLUTION_RECORD_TYPE: | ||
1624 | panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; | ||
1625 | lvds->native_mode.width_mm = panel_res_record->usHSize; | ||
1626 | lvds->native_mode.height_mm = panel_res_record->usVSize; | ||
1627 | record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); | ||
1628 | break; | ||
1629 | default: | ||
1630 | DRM_ERROR("Bad LCD record %d\n", *record); | ||
1631 | bad_record = true; | ||
1632 | break; | ||
1633 | } | ||
1634 | if (bad_record) | ||
1635 | break; | ||
1636 | } | ||
1637 | } | ||
1492 | } | 1638 | } |
1493 | return lvds; | 1639 | return lvds; |
1494 | } | 1640 | } |
@@ -1740,496 +1886,614 @@ static const char *pp_lib_thermal_controller_names[] = { | |||
1740 | "RV6xx", | 1886 | "RV6xx", |
1741 | "RV770", | 1887 | "RV770", |
1742 | "adt7473", | 1888 | "adt7473", |
1889 | "NONE", | ||
1743 | "External GPIO", | 1890 | "External GPIO", |
1744 | "Evergreen", | 1891 | "Evergreen", |
1745 | "adt7473 with internal", | 1892 | "emc2103", |
1746 | 1893 | "Sumo", | |
1894 | "Northern Islands", | ||
1747 | }; | 1895 | }; |
1748 | 1896 | ||
1749 | union power_info { | 1897 | union power_info { |
1750 | struct _ATOM_POWERPLAY_INFO info; | 1898 | struct _ATOM_POWERPLAY_INFO info; |
1751 | struct _ATOM_POWERPLAY_INFO_V2 info_2; | 1899 | struct _ATOM_POWERPLAY_INFO_V2 info_2; |
1752 | struct _ATOM_POWERPLAY_INFO_V3 info_3; | 1900 | struct _ATOM_POWERPLAY_INFO_V3 info_3; |
1753 | struct _ATOM_PPLIB_POWERPLAYTABLE info_4; | 1901 | struct _ATOM_PPLIB_POWERPLAYTABLE pplib; |
1902 | struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; | ||
1903 | struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; | ||
1754 | }; | 1904 | }; |
1755 | 1905 | ||
1756 | void radeon_atombios_get_power_modes(struct radeon_device *rdev) | 1906 | union pplib_clock_info { |
1907 | struct _ATOM_PPLIB_R600_CLOCK_INFO r600; | ||
1908 | struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; | ||
1909 | struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; | ||
1910 | struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; | ||
1911 | }; | ||
1912 | |||
1913 | union pplib_power_state { | ||
1914 | struct _ATOM_PPLIB_STATE v1; | ||
1915 | struct _ATOM_PPLIB_STATE_V2 v2; | ||
1916 | }; | ||
1917 | |||
1918 | static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev, | ||
1919 | int state_index, | ||
1920 | u32 misc, u32 misc2) | ||
1921 | { | ||
1922 | rdev->pm.power_state[state_index].misc = misc; | ||
1923 | rdev->pm.power_state[state_index].misc2 = misc2; | ||
1924 | /* order matters! */ | ||
1925 | if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) | ||
1926 | rdev->pm.power_state[state_index].type = | ||
1927 | POWER_STATE_TYPE_POWERSAVE; | ||
1928 | if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) | ||
1929 | rdev->pm.power_state[state_index].type = | ||
1930 | POWER_STATE_TYPE_BATTERY; | ||
1931 | if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) | ||
1932 | rdev->pm.power_state[state_index].type = | ||
1933 | POWER_STATE_TYPE_BATTERY; | ||
1934 | if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) | ||
1935 | rdev->pm.power_state[state_index].type = | ||
1936 | POWER_STATE_TYPE_BALANCED; | ||
1937 | if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { | ||
1938 | rdev->pm.power_state[state_index].type = | ||
1939 | POWER_STATE_TYPE_PERFORMANCE; | ||
1940 | rdev->pm.power_state[state_index].flags &= | ||
1941 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1942 | } | ||
1943 | if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) | ||
1944 | rdev->pm.power_state[state_index].type = | ||
1945 | POWER_STATE_TYPE_BALANCED; | ||
1946 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { | ||
1947 | rdev->pm.power_state[state_index].type = | ||
1948 | POWER_STATE_TYPE_DEFAULT; | ||
1949 | rdev->pm.default_power_state_index = state_index; | ||
1950 | rdev->pm.power_state[state_index].default_clock_mode = | ||
1951 | &rdev->pm.power_state[state_index].clock_info[0]; | ||
1952 | } else if (state_index == 0) { | ||
1953 | rdev->pm.power_state[state_index].clock_info[0].flags |= | ||
1954 | RADEON_PM_MODE_NO_DISPLAY; | ||
1955 | } | ||
1956 | } | ||
1957 | |||
1958 | static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) | ||
1757 | { | 1959 | { |
1758 | struct radeon_mode_info *mode_info = &rdev->mode_info; | 1960 | struct radeon_mode_info *mode_info = &rdev->mode_info; |
1961 | u32 misc, misc2 = 0; | ||
1962 | int num_modes = 0, i; | ||
1963 | int state_index = 0; | ||
1964 | struct radeon_i2c_bus_rec i2c_bus; | ||
1965 | union power_info *power_info; | ||
1759 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | 1966 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); |
1760 | u16 data_offset; | 1967 | u16 data_offset; |
1761 | u8 frev, crev; | 1968 | u8 frev, crev; |
1762 | u32 misc, misc2 = 0, sclk, mclk; | ||
1763 | union power_info *power_info; | ||
1764 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; | ||
1765 | struct _ATOM_PPLIB_STATE *power_state; | ||
1766 | int num_modes = 0, i, j; | ||
1767 | int state_index = 0, mode_index = 0; | ||
1768 | struct radeon_i2c_bus_rec i2c_bus; | ||
1769 | |||
1770 | rdev->pm.default_power_state_index = -1; | ||
1771 | 1969 | ||
1772 | if (atom_parse_data_header(mode_info->atom_context, index, NULL, | 1970 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, |
1773 | &frev, &crev, &data_offset)) { | 1971 | &frev, &crev, &data_offset)) |
1774 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); | 1972 | return state_index; |
1775 | if (frev < 4) { | 1973 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); |
1776 | /* add the i2c bus for thermal/fan chip */ | 1974 | |
1777 | if (power_info->info.ucOverdriveThermalController > 0) { | 1975 | /* add the i2c bus for thermal/fan chip */ |
1778 | DRM_INFO("Possible %s thermal controller at 0x%02x\n", | 1976 | if (power_info->info.ucOverdriveThermalController > 0) { |
1779 | thermal_controller_names[power_info->info.ucOverdriveThermalController], | 1977 | DRM_INFO("Possible %s thermal controller at 0x%02x\n", |
1780 | power_info->info.ucOverdriveControllerAddress >> 1); | 1978 | thermal_controller_names[power_info->info.ucOverdriveThermalController], |
1781 | i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); | 1979 | power_info->info.ucOverdriveControllerAddress >> 1); |
1782 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); | 1980 | i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); |
1783 | if (rdev->pm.i2c_bus) { | 1981 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
1784 | struct i2c_board_info info = { }; | 1982 | if (rdev->pm.i2c_bus) { |
1785 | const char *name = thermal_controller_names[power_info->info. | 1983 | struct i2c_board_info info = { }; |
1786 | ucOverdriveThermalController]; | 1984 | const char *name = thermal_controller_names[power_info->info. |
1787 | info.addr = power_info->info.ucOverdriveControllerAddress >> 1; | 1985 | ucOverdriveThermalController]; |
1788 | strlcpy(info.type, name, sizeof(info.type)); | 1986 | info.addr = power_info->info.ucOverdriveControllerAddress >> 1; |
1789 | i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); | 1987 | strlcpy(info.type, name, sizeof(info.type)); |
1790 | } | 1988 | i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); |
1989 | } | ||
1990 | } | ||
1991 | num_modes = power_info->info.ucNumOfPowerModeEntries; | ||
1992 | if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) | ||
1993 | num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; | ||
1994 | /* last mode is usually default, array is low to high */ | ||
1995 | for (i = 0; i < num_modes; i++) { | ||
1996 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; | ||
1997 | switch (frev) { | ||
1998 | case 1: | ||
1999 | rdev->pm.power_state[state_index].num_clock_modes = 1; | ||
2000 | rdev->pm.power_state[state_index].clock_info[0].mclk = | ||
2001 | le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); | ||
2002 | rdev->pm.power_state[state_index].clock_info[0].sclk = | ||
2003 | le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); | ||
2004 | /* skip invalid modes */ | ||
2005 | if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || | ||
2006 | (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) | ||
2007 | continue; | ||
2008 | rdev->pm.power_state[state_index].pcie_lanes = | ||
2009 | power_info->info.asPowerPlayInfo[i].ucNumPciELanes; | ||
2010 | misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); | ||
2011 | if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || | ||
2012 | (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { | ||
2013 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
2014 | VOLTAGE_GPIO; | ||
2015 | rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = | ||
2016 | radeon_lookup_gpio(rdev, | ||
2017 | power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); | ||
2018 | if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) | ||
2019 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
2020 | true; | ||
2021 | else | ||
2022 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
2023 | false; | ||
2024 | } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { | ||
2025 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
2026 | VOLTAGE_VDDC; | ||
2027 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = | ||
2028 | power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; | ||
1791 | } | 2029 | } |
1792 | num_modes = power_info->info.ucNumOfPowerModeEntries; | 2030 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1793 | if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) | 2031 | radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0); |
1794 | num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; | 2032 | state_index++; |
1795 | /* last mode is usually default, array is low to high */ | 2033 | break; |
1796 | for (i = 0; i < num_modes; i++) { | 2034 | case 2: |
1797 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; | 2035 | rdev->pm.power_state[state_index].num_clock_modes = 1; |
1798 | switch (frev) { | 2036 | rdev->pm.power_state[state_index].clock_info[0].mclk = |
1799 | case 1: | 2037 | le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); |
1800 | rdev->pm.power_state[state_index].num_clock_modes = 1; | 2038 | rdev->pm.power_state[state_index].clock_info[0].sclk = |
1801 | rdev->pm.power_state[state_index].clock_info[0].mclk = | 2039 | le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); |
1802 | le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); | 2040 | /* skip invalid modes */ |
1803 | rdev->pm.power_state[state_index].clock_info[0].sclk = | 2041 | if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || |
1804 | le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); | 2042 | (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) |
1805 | /* skip invalid modes */ | 2043 | continue; |
1806 | if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || | 2044 | rdev->pm.power_state[state_index].pcie_lanes = |
1807 | (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) | 2045 | power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; |
1808 | continue; | 2046 | misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); |
1809 | rdev->pm.power_state[state_index].pcie_lanes = | 2047 | misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); |
1810 | power_info->info.asPowerPlayInfo[i].ucNumPciELanes; | 2048 | if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || |
1811 | misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); | 2049 | (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { |
1812 | if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || | 2050 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = |
1813 | (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { | 2051 | VOLTAGE_GPIO; |
1814 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | 2052 | rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = |
1815 | VOLTAGE_GPIO; | 2053 | radeon_lookup_gpio(rdev, |
1816 | rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = | 2054 | power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); |
1817 | radeon_lookup_gpio(rdev, | 2055 | if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) |
1818 | power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); | 2056 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = |
1819 | if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) | 2057 | true; |
1820 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | 2058 | else |
1821 | true; | 2059 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = |
1822 | else | 2060 | false; |
1823 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | 2061 | } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { |
1824 | false; | 2062 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = |
1825 | } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { | 2063 | VOLTAGE_VDDC; |
1826 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | 2064 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = |
1827 | VOLTAGE_VDDC; | 2065 | power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; |
1828 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = | ||
1829 | power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; | ||
1830 | } | ||
1831 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1832 | rdev->pm.power_state[state_index].misc = misc; | ||
1833 | /* order matters! */ | ||
1834 | if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) | ||
1835 | rdev->pm.power_state[state_index].type = | ||
1836 | POWER_STATE_TYPE_POWERSAVE; | ||
1837 | if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) | ||
1838 | rdev->pm.power_state[state_index].type = | ||
1839 | POWER_STATE_TYPE_BATTERY; | ||
1840 | if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) | ||
1841 | rdev->pm.power_state[state_index].type = | ||
1842 | POWER_STATE_TYPE_BATTERY; | ||
1843 | if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) | ||
1844 | rdev->pm.power_state[state_index].type = | ||
1845 | POWER_STATE_TYPE_BALANCED; | ||
1846 | if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { | ||
1847 | rdev->pm.power_state[state_index].type = | ||
1848 | POWER_STATE_TYPE_PERFORMANCE; | ||
1849 | rdev->pm.power_state[state_index].flags &= | ||
1850 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1851 | } | ||
1852 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { | ||
1853 | rdev->pm.power_state[state_index].type = | ||
1854 | POWER_STATE_TYPE_DEFAULT; | ||
1855 | rdev->pm.default_power_state_index = state_index; | ||
1856 | rdev->pm.power_state[state_index].default_clock_mode = | ||
1857 | &rdev->pm.power_state[state_index].clock_info[0]; | ||
1858 | rdev->pm.power_state[state_index].flags &= | ||
1859 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1860 | } else if (state_index == 0) { | ||
1861 | rdev->pm.power_state[state_index].clock_info[0].flags |= | ||
1862 | RADEON_PM_MODE_NO_DISPLAY; | ||
1863 | } | ||
1864 | state_index++; | ||
1865 | break; | ||
1866 | case 2: | ||
1867 | rdev->pm.power_state[state_index].num_clock_modes = 1; | ||
1868 | rdev->pm.power_state[state_index].clock_info[0].mclk = | ||
1869 | le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); | ||
1870 | rdev->pm.power_state[state_index].clock_info[0].sclk = | ||
1871 | le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); | ||
1872 | /* skip invalid modes */ | ||
1873 | if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || | ||
1874 | (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) | ||
1875 | continue; | ||
1876 | rdev->pm.power_state[state_index].pcie_lanes = | ||
1877 | power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; | ||
1878 | misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); | ||
1879 | misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); | ||
1880 | if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || | ||
1881 | (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { | ||
1882 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
1883 | VOLTAGE_GPIO; | ||
1884 | rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = | ||
1885 | radeon_lookup_gpio(rdev, | ||
1886 | power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); | ||
1887 | if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) | ||
1888 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
1889 | true; | ||
1890 | else | ||
1891 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
1892 | false; | ||
1893 | } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { | ||
1894 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
1895 | VOLTAGE_VDDC; | ||
1896 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = | ||
1897 | power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; | ||
1898 | } | ||
1899 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1900 | rdev->pm.power_state[state_index].misc = misc; | ||
1901 | rdev->pm.power_state[state_index].misc2 = misc2; | ||
1902 | /* order matters! */ | ||
1903 | if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) | ||
1904 | rdev->pm.power_state[state_index].type = | ||
1905 | POWER_STATE_TYPE_POWERSAVE; | ||
1906 | if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) | ||
1907 | rdev->pm.power_state[state_index].type = | ||
1908 | POWER_STATE_TYPE_BATTERY; | ||
1909 | if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) | ||
1910 | rdev->pm.power_state[state_index].type = | ||
1911 | POWER_STATE_TYPE_BATTERY; | ||
1912 | if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) | ||
1913 | rdev->pm.power_state[state_index].type = | ||
1914 | POWER_STATE_TYPE_BALANCED; | ||
1915 | if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { | ||
1916 | rdev->pm.power_state[state_index].type = | ||
1917 | POWER_STATE_TYPE_PERFORMANCE; | ||
1918 | rdev->pm.power_state[state_index].flags &= | ||
1919 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1920 | } | ||
1921 | if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) | ||
1922 | rdev->pm.power_state[state_index].type = | ||
1923 | POWER_STATE_TYPE_BALANCED; | ||
1924 | if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT) | ||
1925 | rdev->pm.power_state[state_index].flags &= | ||
1926 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1927 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { | ||
1928 | rdev->pm.power_state[state_index].type = | ||
1929 | POWER_STATE_TYPE_DEFAULT; | ||
1930 | rdev->pm.default_power_state_index = state_index; | ||
1931 | rdev->pm.power_state[state_index].default_clock_mode = | ||
1932 | &rdev->pm.power_state[state_index].clock_info[0]; | ||
1933 | rdev->pm.power_state[state_index].flags &= | ||
1934 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1935 | } else if (state_index == 0) { | ||
1936 | rdev->pm.power_state[state_index].clock_info[0].flags |= | ||
1937 | RADEON_PM_MODE_NO_DISPLAY; | ||
1938 | } | ||
1939 | state_index++; | ||
1940 | break; | ||
1941 | case 3: | ||
1942 | rdev->pm.power_state[state_index].num_clock_modes = 1; | ||
1943 | rdev->pm.power_state[state_index].clock_info[0].mclk = | ||
1944 | le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); | ||
1945 | rdev->pm.power_state[state_index].clock_info[0].sclk = | ||
1946 | le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); | ||
1947 | /* skip invalid modes */ | ||
1948 | if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || | ||
1949 | (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) | ||
1950 | continue; | ||
1951 | rdev->pm.power_state[state_index].pcie_lanes = | ||
1952 | power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; | ||
1953 | misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); | ||
1954 | misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); | ||
1955 | if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || | ||
1956 | (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { | ||
1957 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
1958 | VOLTAGE_GPIO; | ||
1959 | rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = | ||
1960 | radeon_lookup_gpio(rdev, | ||
1961 | power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); | ||
1962 | if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) | ||
1963 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
1964 | true; | ||
1965 | else | ||
1966 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
1967 | false; | ||
1968 | } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { | ||
1969 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
1970 | VOLTAGE_VDDC; | ||
1971 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = | ||
1972 | power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; | ||
1973 | if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { | ||
1974 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = | ||
1975 | true; | ||
1976 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = | ||
1977 | power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; | ||
1978 | } | ||
1979 | } | ||
1980 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
1981 | rdev->pm.power_state[state_index].misc = misc; | ||
1982 | rdev->pm.power_state[state_index].misc2 = misc2; | ||
1983 | /* order matters! */ | ||
1984 | if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) | ||
1985 | rdev->pm.power_state[state_index].type = | ||
1986 | POWER_STATE_TYPE_POWERSAVE; | ||
1987 | if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) | ||
1988 | rdev->pm.power_state[state_index].type = | ||
1989 | POWER_STATE_TYPE_BATTERY; | ||
1990 | if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) | ||
1991 | rdev->pm.power_state[state_index].type = | ||
1992 | POWER_STATE_TYPE_BATTERY; | ||
1993 | if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) | ||
1994 | rdev->pm.power_state[state_index].type = | ||
1995 | POWER_STATE_TYPE_BALANCED; | ||
1996 | if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { | ||
1997 | rdev->pm.power_state[state_index].type = | ||
1998 | POWER_STATE_TYPE_PERFORMANCE; | ||
1999 | rdev->pm.power_state[state_index].flags &= | ||
2000 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
2001 | } | ||
2002 | if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) | ||
2003 | rdev->pm.power_state[state_index].type = | ||
2004 | POWER_STATE_TYPE_BALANCED; | ||
2005 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { | ||
2006 | rdev->pm.power_state[state_index].type = | ||
2007 | POWER_STATE_TYPE_DEFAULT; | ||
2008 | rdev->pm.default_power_state_index = state_index; | ||
2009 | rdev->pm.power_state[state_index].default_clock_mode = | ||
2010 | &rdev->pm.power_state[state_index].clock_info[0]; | ||
2011 | } else if (state_index == 0) { | ||
2012 | rdev->pm.power_state[state_index].clock_info[0].flags |= | ||
2013 | RADEON_PM_MODE_NO_DISPLAY; | ||
2014 | } | ||
2015 | state_index++; | ||
2016 | break; | ||
2017 | } | ||
2018 | } | 2066 | } |
2019 | /* last mode is usually default */ | 2067 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
2020 | if (rdev->pm.default_power_state_index == -1) { | 2068 | radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); |
2021 | rdev->pm.power_state[state_index - 1].type = | 2069 | state_index++; |
2022 | POWER_STATE_TYPE_DEFAULT; | 2070 | break; |
2023 | rdev->pm.default_power_state_index = state_index - 1; | 2071 | case 3: |
2024 | rdev->pm.power_state[state_index - 1].default_clock_mode = | 2072 | rdev->pm.power_state[state_index].num_clock_modes = 1; |
2025 | &rdev->pm.power_state[state_index - 1].clock_info[0]; | 2073 | rdev->pm.power_state[state_index].clock_info[0].mclk = |
2026 | rdev->pm.power_state[state_index].flags &= | 2074 | le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); |
2027 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | 2075 | rdev->pm.power_state[state_index].clock_info[0].sclk = |
2028 | rdev->pm.power_state[state_index].misc = 0; | 2076 | le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); |
2029 | rdev->pm.power_state[state_index].misc2 = 0; | 2077 | /* skip invalid modes */ |
2078 | if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || | ||
2079 | (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) | ||
2080 | continue; | ||
2081 | rdev->pm.power_state[state_index].pcie_lanes = | ||
2082 | power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; | ||
2083 | misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); | ||
2084 | misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); | ||
2085 | if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || | ||
2086 | (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { | ||
2087 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
2088 | VOLTAGE_GPIO; | ||
2089 | rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = | ||
2090 | radeon_lookup_gpio(rdev, | ||
2091 | power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); | ||
2092 | if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) | ||
2093 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
2094 | true; | ||
2095 | else | ||
2096 | rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = | ||
2097 | false; | ||
2098 | } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { | ||
2099 | rdev->pm.power_state[state_index].clock_info[0].voltage.type = | ||
2100 | VOLTAGE_VDDC; | ||
2101 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = | ||
2102 | power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; | ||
2103 | if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { | ||
2104 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = | ||
2105 | true; | ||
2106 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = | ||
2107 | power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; | ||
2108 | } | ||
2030 | } | 2109 | } |
2110 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
2111 | radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); | ||
2112 | state_index++; | ||
2113 | break; | ||
2114 | } | ||
2115 | } | ||
2116 | /* last mode is usually default */ | ||
2117 | if (rdev->pm.default_power_state_index == -1) { | ||
2118 | rdev->pm.power_state[state_index - 1].type = | ||
2119 | POWER_STATE_TYPE_DEFAULT; | ||
2120 | rdev->pm.default_power_state_index = state_index - 1; | ||
2121 | rdev->pm.power_state[state_index - 1].default_clock_mode = | ||
2122 | &rdev->pm.power_state[state_index - 1].clock_info[0]; | ||
2123 | rdev->pm.power_state[state_index].flags &= | ||
2124 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
2125 | rdev->pm.power_state[state_index].misc = 0; | ||
2126 | rdev->pm.power_state[state_index].misc2 = 0; | ||
2127 | } | ||
2128 | return state_index; | ||
2129 | } | ||
2130 | |||
2131 | static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev, | ||
2132 | ATOM_PPLIB_THERMALCONTROLLER *controller) | ||
2133 | { | ||
2134 | struct radeon_i2c_bus_rec i2c_bus; | ||
2135 | |||
2136 | /* add the i2c bus for thermal/fan chip */ | ||
2137 | if (controller->ucType > 0) { | ||
2138 | if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { | ||
2139 | DRM_INFO("Internal thermal controller %s fan control\n", | ||
2140 | (controller->ucFanParameters & | ||
2141 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2142 | rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; | ||
2143 | } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { | ||
2144 | DRM_INFO("Internal thermal controller %s fan control\n", | ||
2145 | (controller->ucFanParameters & | ||
2146 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2147 | rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; | ||
2148 | } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { | ||
2149 | DRM_INFO("Internal thermal controller %s fan control\n", | ||
2150 | (controller->ucFanParameters & | ||
2151 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2152 | rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; | ||
2153 | } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { | ||
2154 | DRM_INFO("Internal thermal controller %s fan control\n", | ||
2155 | (controller->ucFanParameters & | ||
2156 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2157 | rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO; | ||
2158 | } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { | ||
2159 | DRM_INFO("Internal thermal controller %s fan control\n", | ||
2160 | (controller->ucFanParameters & | ||
2161 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2162 | rdev->pm.int_thermal_type = THERMAL_TYPE_NI; | ||
2163 | } else if ((controller->ucType == | ||
2164 | ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || | ||
2165 | (controller->ucType == | ||
2166 | ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || | ||
2167 | (controller->ucType == | ||
2168 | ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { | ||
2169 | DRM_INFO("Special thermal controller config\n"); | ||
2031 | } else { | 2170 | } else { |
2032 | int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo); | 2171 | DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", |
2033 | uint8_t fw_frev, fw_crev; | 2172 | pp_lib_thermal_controller_names[controller->ucType], |
2034 | uint16_t fw_data_offset, vddc = 0; | 2173 | controller->ucI2cAddress >> 1, |
2035 | union firmware_info *firmware_info; | 2174 | (controller->ucFanParameters & |
2036 | ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController; | 2175 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); |
2037 | 2176 | i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); | |
2038 | if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL, | 2177 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); |
2039 | &fw_frev, &fw_crev, &fw_data_offset)) { | 2178 | if (rdev->pm.i2c_bus) { |
2040 | firmware_info = | 2179 | struct i2c_board_info info = { }; |
2041 | (union firmware_info *)(mode_info->atom_context->bios + | 2180 | const char *name = pp_lib_thermal_controller_names[controller->ucType]; |
2042 | fw_data_offset); | 2181 | info.addr = controller->ucI2cAddress >> 1; |
2043 | vddc = firmware_info->info_14.usBootUpVDDCVoltage; | 2182 | strlcpy(info.type, name, sizeof(info.type)); |
2183 | i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); | ||
2044 | } | 2184 | } |
2185 | } | ||
2186 | } | ||
2187 | } | ||
2045 | 2188 | ||
2046 | /* add the i2c bus for thermal/fan chip */ | 2189 | static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev) |
2047 | if (controller->ucType > 0) { | 2190 | { |
2048 | if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { | 2191 | struct radeon_mode_info *mode_info = &rdev->mode_info; |
2049 | DRM_INFO("Internal thermal controller %s fan control\n", | 2192 | int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); |
2050 | (controller->ucFanParameters & | 2193 | u8 frev, crev; |
2051 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | 2194 | u16 data_offset; |
2052 | rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; | 2195 | union firmware_info *firmware_info; |
2053 | } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { | 2196 | u16 vddc = 0; |
2054 | DRM_INFO("Internal thermal controller %s fan control\n", | ||
2055 | (controller->ucFanParameters & | ||
2056 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2057 | rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; | ||
2058 | } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { | ||
2059 | DRM_INFO("Internal thermal controller %s fan control\n", | ||
2060 | (controller->ucFanParameters & | ||
2061 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2062 | rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; | ||
2063 | } else if ((controller->ucType == | ||
2064 | ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || | ||
2065 | (controller->ucType == | ||
2066 | ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL)) { | ||
2067 | DRM_INFO("Special thermal controller config\n"); | ||
2068 | } else { | ||
2069 | DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", | ||
2070 | pp_lib_thermal_controller_names[controller->ucType], | ||
2071 | controller->ucI2cAddress >> 1, | ||
2072 | (controller->ucFanParameters & | ||
2073 | ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); | ||
2074 | i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); | ||
2075 | rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); | ||
2076 | if (rdev->pm.i2c_bus) { | ||
2077 | struct i2c_board_info info = { }; | ||
2078 | const char *name = pp_lib_thermal_controller_names[controller->ucType]; | ||
2079 | info.addr = controller->ucI2cAddress >> 1; | ||
2080 | strlcpy(info.type, name, sizeof(info.type)); | ||
2081 | i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); | ||
2082 | } | ||
2083 | 2197 | ||
2084 | } | 2198 | if (atom_parse_data_header(mode_info->atom_context, index, NULL, |
2085 | } | 2199 | &frev, &crev, &data_offset)) { |
2086 | /* first mode is usually default, followed by low to high */ | 2200 | firmware_info = |
2087 | for (i = 0; i < power_info->info_4.ucNumStates; i++) { | 2201 | (union firmware_info *)(mode_info->atom_context->bios + |
2088 | mode_index = 0; | 2202 | data_offset); |
2089 | power_state = (struct _ATOM_PPLIB_STATE *) | 2203 | vddc = firmware_info->info_14.usBootUpVDDCVoltage; |
2090 | (mode_info->atom_context->bios + | 2204 | } |
2091 | data_offset + | 2205 | |
2092 | le16_to_cpu(power_info->info_4.usStateArrayOffset) + | 2206 | return vddc; |
2093 | i * power_info->info_4.ucStateEntrySize); | 2207 | } |
2094 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) | 2208 | |
2095 | (mode_info->atom_context->bios + | 2209 | static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, |
2096 | data_offset + | 2210 | int state_index, int mode_index, |
2097 | le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) + | 2211 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info) |
2098 | (power_state->ucNonClockStateIndex * | 2212 | { |
2099 | power_info->info_4.ucNonClockSize)); | 2213 | int j; |
2100 | for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) { | 2214 | u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); |
2101 | if (rdev->flags & RADEON_IS_IGP) { | 2215 | u32 misc2 = le16_to_cpu(non_clock_info->usClassification); |
2102 | struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info = | 2216 | u16 vddc = radeon_atombios_get_default_vddc(rdev); |
2103 | (struct _ATOM_PPLIB_RS780_CLOCK_INFO *) | 2217 | |
2104 | (mode_info->atom_context->bios + | 2218 | rdev->pm.power_state[state_index].misc = misc; |
2105 | data_offset + | 2219 | rdev->pm.power_state[state_index].misc2 = misc2; |
2106 | le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + | 2220 | rdev->pm.power_state[state_index].pcie_lanes = |
2107 | (power_state->ucClockStateIndices[j] * | 2221 | ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> |
2108 | power_info->info_4.ucClockInfoSize)); | 2222 | ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; |
2109 | sclk = le16_to_cpu(clock_info->usLowEngineClockLow); | 2223 | switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { |
2110 | sclk |= clock_info->ucLowEngineClockHigh << 16; | 2224 | case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: |
2111 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; | 2225 | rdev->pm.power_state[state_index].type = |
2112 | /* skip invalid modes */ | 2226 | POWER_STATE_TYPE_BATTERY; |
2113 | if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) | 2227 | break; |
2114 | continue; | 2228 | case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: |
2115 | /* voltage works differently on IGPs */ | 2229 | rdev->pm.power_state[state_index].type = |
2116 | mode_index++; | 2230 | POWER_STATE_TYPE_BALANCED; |
2117 | } else if (ASIC_IS_DCE4(rdev)) { | 2231 | break; |
2118 | struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info = | 2232 | case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: |
2119 | (struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *) | 2233 | rdev->pm.power_state[state_index].type = |
2120 | (mode_info->atom_context->bios + | 2234 | POWER_STATE_TYPE_PERFORMANCE; |
2121 | data_offset + | 2235 | break; |
2122 | le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + | 2236 | case ATOM_PPLIB_CLASSIFICATION_UI_NONE: |
2123 | (power_state->ucClockStateIndices[j] * | 2237 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) |
2124 | power_info->info_4.ucClockInfoSize)); | 2238 | rdev->pm.power_state[state_index].type = |
2125 | sclk = le16_to_cpu(clock_info->usEngineClockLow); | 2239 | POWER_STATE_TYPE_PERFORMANCE; |
2126 | sclk |= clock_info->ucEngineClockHigh << 16; | 2240 | break; |
2127 | mclk = le16_to_cpu(clock_info->usMemoryClockLow); | 2241 | } |
2128 | mclk |= clock_info->ucMemoryClockHigh << 16; | 2242 | rdev->pm.power_state[state_index].flags = 0; |
2129 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; | 2243 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) |
2130 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; | 2244 | rdev->pm.power_state[state_index].flags |= |
2131 | /* skip invalid modes */ | 2245 | RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
2132 | if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || | 2246 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { |
2133 | (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) | 2247 | rdev->pm.power_state[state_index].type = |
2134 | continue; | 2248 | POWER_STATE_TYPE_DEFAULT; |
2135 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = | 2249 | rdev->pm.default_power_state_index = state_index; |
2136 | VOLTAGE_SW; | 2250 | rdev->pm.power_state[state_index].default_clock_mode = |
2137 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = | 2251 | &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; |
2138 | clock_info->usVDDC; | 2252 | if (ASIC_IS_DCE5(rdev)) { |
2139 | /* XXX usVDDCI */ | 2253 | /* NI chips post without MC ucode, so default clocks are strobe mode only */ |
2140 | mode_index++; | 2254 | rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; |
2141 | } else { | 2255 | rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; |
2142 | struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info = | 2256 | rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; |
2143 | (struct _ATOM_PPLIB_R600_CLOCK_INFO *) | 2257 | } else { |
2144 | (mode_info->atom_context->bios + | 2258 | /* patch the table values with the default slck/mclk from firmware info */ |
2145 | data_offset + | 2259 | for (j = 0; j < mode_index; j++) { |
2146 | le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + | 2260 | rdev->pm.power_state[state_index].clock_info[j].mclk = |
2147 | (power_state->ucClockStateIndices[j] * | 2261 | rdev->clock.default_mclk; |
2148 | power_info->info_4.ucClockInfoSize)); | 2262 | rdev->pm.power_state[state_index].clock_info[j].sclk = |
2149 | sclk = le16_to_cpu(clock_info->usEngineClockLow); | 2263 | rdev->clock.default_sclk; |
2150 | sclk |= clock_info->ucEngineClockHigh << 16; | 2264 | if (vddc) |
2151 | mclk = le16_to_cpu(clock_info->usMemoryClockLow); | 2265 | rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = |
2152 | mclk |= clock_info->ucMemoryClockHigh << 16; | 2266 | vddc; |
2153 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; | ||
2154 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; | ||
2155 | /* skip invalid modes */ | ||
2156 | if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || | ||
2157 | (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) | ||
2158 | continue; | ||
2159 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = | ||
2160 | VOLTAGE_SW; | ||
2161 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = | ||
2162 | clock_info->usVDDC; | ||
2163 | mode_index++; | ||
2164 | } | ||
2165 | } | ||
2166 | rdev->pm.power_state[state_index].num_clock_modes = mode_index; | ||
2167 | if (mode_index) { | ||
2168 | misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); | ||
2169 | misc2 = le16_to_cpu(non_clock_info->usClassification); | ||
2170 | rdev->pm.power_state[state_index].misc = misc; | ||
2171 | rdev->pm.power_state[state_index].misc2 = misc2; | ||
2172 | rdev->pm.power_state[state_index].pcie_lanes = | ||
2173 | ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> | ||
2174 | ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; | ||
2175 | switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { | ||
2176 | case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: | ||
2177 | rdev->pm.power_state[state_index].type = | ||
2178 | POWER_STATE_TYPE_BATTERY; | ||
2179 | break; | ||
2180 | case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: | ||
2181 | rdev->pm.power_state[state_index].type = | ||
2182 | POWER_STATE_TYPE_BALANCED; | ||
2183 | break; | ||
2184 | case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: | ||
2185 | rdev->pm.power_state[state_index].type = | ||
2186 | POWER_STATE_TYPE_PERFORMANCE; | ||
2187 | break; | ||
2188 | case ATOM_PPLIB_CLASSIFICATION_UI_NONE: | ||
2189 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) | ||
2190 | rdev->pm.power_state[state_index].type = | ||
2191 | POWER_STATE_TYPE_PERFORMANCE; | ||
2192 | break; | ||
2193 | } | ||
2194 | rdev->pm.power_state[state_index].flags = 0; | ||
2195 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) | ||
2196 | rdev->pm.power_state[state_index].flags |= | ||
2197 | RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; | ||
2198 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { | ||
2199 | rdev->pm.power_state[state_index].type = | ||
2200 | POWER_STATE_TYPE_DEFAULT; | ||
2201 | rdev->pm.default_power_state_index = state_index; | ||
2202 | rdev->pm.power_state[state_index].default_clock_mode = | ||
2203 | &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; | ||
2204 | /* patch the table values with the default slck/mclk from firmware info */ | ||
2205 | for (j = 0; j < mode_index; j++) { | ||
2206 | rdev->pm.power_state[state_index].clock_info[j].mclk = | ||
2207 | rdev->clock.default_mclk; | ||
2208 | rdev->pm.power_state[state_index].clock_info[j].sclk = | ||
2209 | rdev->clock.default_sclk; | ||
2210 | if (vddc) | ||
2211 | rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = | ||
2212 | vddc; | ||
2213 | } | ||
2214 | } | ||
2215 | state_index++; | ||
2216 | } | ||
2217 | } | ||
2218 | /* if multiple clock modes, mark the lowest as no display */ | ||
2219 | for (i = 0; i < state_index; i++) { | ||
2220 | if (rdev->pm.power_state[i].num_clock_modes > 1) | ||
2221 | rdev->pm.power_state[i].clock_info[0].flags |= | ||
2222 | RADEON_PM_MODE_NO_DISPLAY; | ||
2223 | } | ||
2224 | /* first mode is usually default */ | ||
2225 | if (rdev->pm.default_power_state_index == -1) { | ||
2226 | rdev->pm.power_state[0].type = | ||
2227 | POWER_STATE_TYPE_DEFAULT; | ||
2228 | rdev->pm.default_power_state_index = 0; | ||
2229 | rdev->pm.power_state[0].default_clock_mode = | ||
2230 | &rdev->pm.power_state[0].clock_info[0]; | ||
2231 | } | 2267 | } |
2232 | } | 2268 | } |
2269 | } | ||
2270 | } | ||
2271 | |||
2272 | static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, | ||
2273 | int state_index, int mode_index, | ||
2274 | union pplib_clock_info *clock_info) | ||
2275 | { | ||
2276 | u32 sclk, mclk; | ||
2277 | |||
2278 | if (rdev->flags & RADEON_IS_IGP) { | ||
2279 | if (rdev->family >= CHIP_PALM) { | ||
2280 | sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); | ||
2281 | sclk |= clock_info->sumo.ucEngineClockHigh << 16; | ||
2282 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; | ||
2283 | } else { | ||
2284 | sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); | ||
2285 | sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; | ||
2286 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; | ||
2287 | } | ||
2288 | } else if (ASIC_IS_DCE4(rdev)) { | ||
2289 | sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); | ||
2290 | sclk |= clock_info->evergreen.ucEngineClockHigh << 16; | ||
2291 | mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow); | ||
2292 | mclk |= clock_info->evergreen.ucMemoryClockHigh << 16; | ||
2293 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; | ||
2294 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; | ||
2295 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = | ||
2296 | VOLTAGE_SW; | ||
2297 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = | ||
2298 | clock_info->evergreen.usVDDC; | ||
2299 | } else { | ||
2300 | sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); | ||
2301 | sclk |= clock_info->r600.ucEngineClockHigh << 16; | ||
2302 | mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow); | ||
2303 | mclk |= clock_info->r600.ucMemoryClockHigh << 16; | ||
2304 | rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; | ||
2305 | rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; | ||
2306 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = | ||
2307 | VOLTAGE_SW; | ||
2308 | rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = | ||
2309 | clock_info->r600.usVDDC; | ||
2310 | } | ||
2311 | |||
2312 | if (rdev->flags & RADEON_IS_IGP) { | ||
2313 | /* skip invalid modes */ | ||
2314 | if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) | ||
2315 | return false; | ||
2316 | } else { | ||
2317 | /* skip invalid modes */ | ||
2318 | if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || | ||
2319 | (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) | ||
2320 | return false; | ||
2321 | } | ||
2322 | return true; | ||
2323 | } | ||
2324 | |||
2325 | static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) | ||
2326 | { | ||
2327 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
2328 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; | ||
2329 | union pplib_power_state *power_state; | ||
2330 | int i, j; | ||
2331 | int state_index = 0, mode_index = 0; | ||
2332 | union pplib_clock_info *clock_info; | ||
2333 | bool valid; | ||
2334 | union power_info *power_info; | ||
2335 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | ||
2336 | u16 data_offset; | ||
2337 | u8 frev, crev; | ||
2338 | |||
2339 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, | ||
2340 | &frev, &crev, &data_offset)) | ||
2341 | return state_index; | ||
2342 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); | ||
2343 | |||
2344 | radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); | ||
2345 | /* first mode is usually default, followed by low to high */ | ||
2346 | for (i = 0; i < power_info->pplib.ucNumStates; i++) { | ||
2347 | mode_index = 0; | ||
2348 | power_state = (union pplib_power_state *) | ||
2349 | (mode_info->atom_context->bios + data_offset + | ||
2350 | le16_to_cpu(power_info->pplib.usStateArrayOffset) + | ||
2351 | i * power_info->pplib.ucStateEntrySize); | ||
2352 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) | ||
2353 | (mode_info->atom_context->bios + data_offset + | ||
2354 | le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + | ||
2355 | (power_state->v1.ucNonClockStateIndex * | ||
2356 | power_info->pplib.ucNonClockSize)); | ||
2357 | for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { | ||
2358 | clock_info = (union pplib_clock_info *) | ||
2359 | (mode_info->atom_context->bios + data_offset + | ||
2360 | le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + | ||
2361 | (power_state->v1.ucClockStateIndices[j] * | ||
2362 | power_info->pplib.ucClockInfoSize)); | ||
2363 | valid = radeon_atombios_parse_pplib_clock_info(rdev, | ||
2364 | state_index, mode_index, | ||
2365 | clock_info); | ||
2366 | if (valid) | ||
2367 | mode_index++; | ||
2368 | } | ||
2369 | rdev->pm.power_state[state_index].num_clock_modes = mode_index; | ||
2370 | if (mode_index) { | ||
2371 | radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, | ||
2372 | non_clock_info); | ||
2373 | state_index++; | ||
2374 | } | ||
2375 | } | ||
2376 | /* if multiple clock modes, mark the lowest as no display */ | ||
2377 | for (i = 0; i < state_index; i++) { | ||
2378 | if (rdev->pm.power_state[i].num_clock_modes > 1) | ||
2379 | rdev->pm.power_state[i].clock_info[0].flags |= | ||
2380 | RADEON_PM_MODE_NO_DISPLAY; | ||
2381 | } | ||
2382 | /* first mode is usually default */ | ||
2383 | if (rdev->pm.default_power_state_index == -1) { | ||
2384 | rdev->pm.power_state[0].type = | ||
2385 | POWER_STATE_TYPE_DEFAULT; | ||
2386 | rdev->pm.default_power_state_index = 0; | ||
2387 | rdev->pm.power_state[0].default_clock_mode = | ||
2388 | &rdev->pm.power_state[0].clock_info[0]; | ||
2389 | } | ||
2390 | return state_index; | ||
2391 | } | ||
2392 | |||
2393 | static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) | ||
2394 | { | ||
2395 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
2396 | struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; | ||
2397 | union pplib_power_state *power_state; | ||
2398 | int i, j, non_clock_array_index, clock_array_index; | ||
2399 | int state_index = 0, mode_index = 0; | ||
2400 | union pplib_clock_info *clock_info; | ||
2401 | struct StateArray *state_array; | ||
2402 | struct ClockInfoArray *clock_info_array; | ||
2403 | struct NonClockInfoArray *non_clock_info_array; | ||
2404 | bool valid; | ||
2405 | union power_info *power_info; | ||
2406 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | ||
2407 | u16 data_offset; | ||
2408 | u8 frev, crev; | ||
2409 | |||
2410 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, | ||
2411 | &frev, &crev, &data_offset)) | ||
2412 | return state_index; | ||
2413 | power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); | ||
2414 | |||
2415 | radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); | ||
2416 | state_array = (struct StateArray *) | ||
2417 | (mode_info->atom_context->bios + data_offset + | ||
2418 | power_info->pplib.usStateArrayOffset); | ||
2419 | clock_info_array = (struct ClockInfoArray *) | ||
2420 | (mode_info->atom_context->bios + data_offset + | ||
2421 | power_info->pplib.usClockInfoArrayOffset); | ||
2422 | non_clock_info_array = (struct NonClockInfoArray *) | ||
2423 | (mode_info->atom_context->bios + data_offset + | ||
2424 | power_info->pplib.usNonClockInfoArrayOffset); | ||
2425 | for (i = 0; i < state_array->ucNumEntries; i++) { | ||
2426 | mode_index = 0; | ||
2427 | power_state = (union pplib_power_state *)&state_array->states[i]; | ||
2428 | /* XXX this might be an inagua bug... */ | ||
2429 | non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ | ||
2430 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) | ||
2431 | &non_clock_info_array->nonClockInfo[non_clock_array_index]; | ||
2432 | for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { | ||
2433 | clock_array_index = power_state->v2.clockInfoIndex[j]; | ||
2434 | /* XXX this might be an inagua bug... */ | ||
2435 | if (clock_array_index >= clock_info_array->ucNumEntries) | ||
2436 | continue; | ||
2437 | clock_info = (union pplib_clock_info *) | ||
2438 | &clock_info_array->clockInfo[clock_array_index]; | ||
2439 | valid = radeon_atombios_parse_pplib_clock_info(rdev, | ||
2440 | state_index, mode_index, | ||
2441 | clock_info); | ||
2442 | if (valid) | ||
2443 | mode_index++; | ||
2444 | } | ||
2445 | rdev->pm.power_state[state_index].num_clock_modes = mode_index; | ||
2446 | if (mode_index) { | ||
2447 | radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, | ||
2448 | non_clock_info); | ||
2449 | state_index++; | ||
2450 | } | ||
2451 | } | ||
2452 | /* if multiple clock modes, mark the lowest as no display */ | ||
2453 | for (i = 0; i < state_index; i++) { | ||
2454 | if (rdev->pm.power_state[i].num_clock_modes > 1) | ||
2455 | rdev->pm.power_state[i].clock_info[0].flags |= | ||
2456 | RADEON_PM_MODE_NO_DISPLAY; | ||
2457 | } | ||
2458 | /* first mode is usually default */ | ||
2459 | if (rdev->pm.default_power_state_index == -1) { | ||
2460 | rdev->pm.power_state[0].type = | ||
2461 | POWER_STATE_TYPE_DEFAULT; | ||
2462 | rdev->pm.default_power_state_index = 0; | ||
2463 | rdev->pm.power_state[0].default_clock_mode = | ||
2464 | &rdev->pm.power_state[0].clock_info[0]; | ||
2465 | } | ||
2466 | return state_index; | ||
2467 | } | ||
2468 | |||
2469 | void radeon_atombios_get_power_modes(struct radeon_device *rdev) | ||
2470 | { | ||
2471 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
2472 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | ||
2473 | u16 data_offset; | ||
2474 | u8 frev, crev; | ||
2475 | int state_index = 0; | ||
2476 | |||
2477 | rdev->pm.default_power_state_index = -1; | ||
2478 | |||
2479 | if (atom_parse_data_header(mode_info->atom_context, index, NULL, | ||
2480 | &frev, &crev, &data_offset)) { | ||
2481 | switch (frev) { | ||
2482 | case 1: | ||
2483 | case 2: | ||
2484 | case 3: | ||
2485 | state_index = radeon_atombios_parse_power_table_1_3(rdev); | ||
2486 | break; | ||
2487 | case 4: | ||
2488 | case 5: | ||
2489 | state_index = radeon_atombios_parse_power_table_4_5(rdev); | ||
2490 | break; | ||
2491 | case 6: | ||
2492 | state_index = radeon_atombios_parse_power_table_6(rdev); | ||
2493 | break; | ||
2494 | default: | ||
2495 | break; | ||
2496 | } | ||
2233 | } else { | 2497 | } else { |
2234 | /* add the default mode */ | 2498 | /* add the default mode */ |
2235 | rdev->pm.power_state[state_index].type = | 2499 | rdev->pm.power_state[state_index].type = |