diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_pm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 94 |
1 files changed, 52 insertions, 42 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 8c9b2ef32c68..3b1b2bf9cdd5 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
@@ -167,13 +167,13 @@ static void radeon_set_power_state(struct radeon_device *rdev) | |||
167 | if (radeon_gui_idle(rdev)) { | 167 | if (radeon_gui_idle(rdev)) { |
168 | sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. | 168 | sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. |
169 | clock_info[rdev->pm.requested_clock_mode_index].sclk; | 169 | clock_info[rdev->pm.requested_clock_mode_index].sclk; |
170 | if (sclk > rdev->clock.default_sclk) | 170 | if (sclk > rdev->pm.default_sclk) |
171 | sclk = rdev->clock.default_sclk; | 171 | sclk = rdev->pm.default_sclk; |
172 | 172 | ||
173 | mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. | 173 | mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. |
174 | clock_info[rdev->pm.requested_clock_mode_index].mclk; | 174 | clock_info[rdev->pm.requested_clock_mode_index].mclk; |
175 | if (mclk > rdev->clock.default_mclk) | 175 | if (mclk > rdev->pm.default_mclk) |
176 | mclk = rdev->clock.default_mclk; | 176 | mclk = rdev->pm.default_mclk; |
177 | 177 | ||
178 | /* upvolt before raising clocks, downvolt after lowering clocks */ | 178 | /* upvolt before raising clocks, downvolt after lowering clocks */ |
179 | if (sclk < rdev->pm.current_sclk) | 179 | if (sclk < rdev->pm.current_sclk) |
@@ -405,20 +405,13 @@ static ssize_t radeon_set_pm_method(struct device *dev, | |||
405 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; | 405 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; |
406 | mutex_unlock(&rdev->pm.mutex); | 406 | mutex_unlock(&rdev->pm.mutex); |
407 | } else if (strncmp("profile", buf, strlen("profile")) == 0) { | 407 | } else if (strncmp("profile", buf, strlen("profile")) == 0) { |
408 | bool flush_wq = false; | ||
409 | |||
410 | mutex_lock(&rdev->pm.mutex); | 408 | mutex_lock(&rdev->pm.mutex); |
411 | if (rdev->pm.pm_method == PM_METHOD_DYNPM) { | ||
412 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | ||
413 | flush_wq = true; | ||
414 | } | ||
415 | /* disable dynpm */ | 409 | /* disable dynpm */ |
416 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; | 410 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; |
417 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; | 411 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; |
418 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 412 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
419 | mutex_unlock(&rdev->pm.mutex); | 413 | mutex_unlock(&rdev->pm.mutex); |
420 | if (flush_wq) | 414 | cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); |
421 | flush_workqueue(rdev->wq); | ||
422 | } else { | 415 | } else { |
423 | DRM_ERROR("invalid power method!\n"); | 416 | DRM_ERROR("invalid power method!\n"); |
424 | goto fail; | 417 | goto fail; |
@@ -447,8 +440,12 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, | |||
447 | temp = rv770_get_temp(rdev); | 440 | temp = rv770_get_temp(rdev); |
448 | break; | 441 | break; |
449 | case THERMAL_TYPE_EVERGREEN: | 442 | case THERMAL_TYPE_EVERGREEN: |
443 | case THERMAL_TYPE_NI: | ||
450 | temp = evergreen_get_temp(rdev); | 444 | temp = evergreen_get_temp(rdev); |
451 | break; | 445 | break; |
446 | case THERMAL_TYPE_SUMO: | ||
447 | temp = sumo_get_temp(rdev); | ||
448 | break; | ||
452 | default: | 449 | default: |
453 | temp = 0; | 450 | temp = 0; |
454 | break; | 451 | break; |
@@ -487,6 +484,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev) | |||
487 | case THERMAL_TYPE_RV6XX: | 484 | case THERMAL_TYPE_RV6XX: |
488 | case THERMAL_TYPE_RV770: | 485 | case THERMAL_TYPE_RV770: |
489 | case THERMAL_TYPE_EVERGREEN: | 486 | case THERMAL_TYPE_EVERGREEN: |
487 | case THERMAL_TYPE_SUMO: | ||
490 | rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); | 488 | rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); |
491 | if (IS_ERR(rdev->pm.int_hwmon_dev)) { | 489 | if (IS_ERR(rdev->pm.int_hwmon_dev)) { |
492 | err = PTR_ERR(rdev->pm.int_hwmon_dev); | 490 | err = PTR_ERR(rdev->pm.int_hwmon_dev); |
@@ -520,34 +518,39 @@ static void radeon_hwmon_fini(struct radeon_device *rdev) | |||
520 | 518 | ||
521 | void radeon_pm_suspend(struct radeon_device *rdev) | 519 | void radeon_pm_suspend(struct radeon_device *rdev) |
522 | { | 520 | { |
523 | bool flush_wq = false; | ||
524 | |||
525 | mutex_lock(&rdev->pm.mutex); | 521 | mutex_lock(&rdev->pm.mutex); |
526 | if (rdev->pm.pm_method == PM_METHOD_DYNPM) { | 522 | if (rdev->pm.pm_method == PM_METHOD_DYNPM) { |
527 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | ||
528 | if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) | 523 | if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) |
529 | rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED; | 524 | rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED; |
530 | flush_wq = true; | ||
531 | } | 525 | } |
532 | mutex_unlock(&rdev->pm.mutex); | 526 | mutex_unlock(&rdev->pm.mutex); |
533 | if (flush_wq) | 527 | |
534 | flush_workqueue(rdev->wq); | 528 | cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); |
535 | } | 529 | } |
536 | 530 | ||
537 | void radeon_pm_resume(struct radeon_device *rdev) | 531 | void radeon_pm_resume(struct radeon_device *rdev) |
538 | { | 532 | { |
533 | /* set up the default clocks if the MC ucode is loaded */ | ||
534 | if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { | ||
535 | if (rdev->pm.default_vddc) | ||
536 | radeon_atom_set_voltage(rdev, rdev->pm.default_vddc); | ||
537 | if (rdev->pm.default_sclk) | ||
538 | radeon_set_engine_clock(rdev, rdev->pm.default_sclk); | ||
539 | if (rdev->pm.default_mclk) | ||
540 | radeon_set_memory_clock(rdev, rdev->pm.default_mclk); | ||
541 | } | ||
539 | /* asic init will reset the default power state */ | 542 | /* asic init will reset the default power state */ |
540 | mutex_lock(&rdev->pm.mutex); | 543 | mutex_lock(&rdev->pm.mutex); |
541 | rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; | 544 | rdev->pm.current_power_state_index = rdev->pm.default_power_state_index; |
542 | rdev->pm.current_clock_mode_index = 0; | 545 | rdev->pm.current_clock_mode_index = 0; |
543 | rdev->pm.current_sclk = rdev->clock.default_sclk; | 546 | rdev->pm.current_sclk = rdev->pm.default_sclk; |
544 | rdev->pm.current_mclk = rdev->clock.default_mclk; | 547 | rdev->pm.current_mclk = rdev->pm.default_mclk; |
545 | rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; | 548 | rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; |
546 | if (rdev->pm.pm_method == PM_METHOD_DYNPM | 549 | if (rdev->pm.pm_method == PM_METHOD_DYNPM |
547 | && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { | 550 | && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { |
548 | rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; | 551 | rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; |
549 | queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, | 552 | schedule_delayed_work(&rdev->pm.dynpm_idle_work, |
550 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | 553 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); |
551 | } | 554 | } |
552 | mutex_unlock(&rdev->pm.mutex); | 555 | mutex_unlock(&rdev->pm.mutex); |
553 | radeon_pm_compute_clocks(rdev); | 556 | radeon_pm_compute_clocks(rdev); |
@@ -564,6 +567,8 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
564 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; | 567 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; |
565 | rdev->pm.dynpm_can_upclock = true; | 568 | rdev->pm.dynpm_can_upclock = true; |
566 | rdev->pm.dynpm_can_downclock = true; | 569 | rdev->pm.dynpm_can_downclock = true; |
570 | rdev->pm.default_sclk = rdev->clock.default_sclk; | ||
571 | rdev->pm.default_mclk = rdev->clock.default_mclk; | ||
567 | rdev->pm.current_sclk = rdev->clock.default_sclk; | 572 | rdev->pm.current_sclk = rdev->clock.default_sclk; |
568 | rdev->pm.current_mclk = rdev->clock.default_mclk; | 573 | rdev->pm.current_mclk = rdev->clock.default_mclk; |
569 | rdev->pm.int_thermal_type = THERMAL_TYPE_NONE; | 574 | rdev->pm.int_thermal_type = THERMAL_TYPE_NONE; |
@@ -575,12 +580,24 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
575 | radeon_combios_get_power_modes(rdev); | 580 | radeon_combios_get_power_modes(rdev); |
576 | radeon_pm_print_states(rdev); | 581 | radeon_pm_print_states(rdev); |
577 | radeon_pm_init_profile(rdev); | 582 | radeon_pm_init_profile(rdev); |
583 | /* set up the default clocks if the MC ucode is loaded */ | ||
584 | if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { | ||
585 | if (rdev->pm.default_vddc) | ||
586 | radeon_atom_set_voltage(rdev, rdev->pm.default_vddc); | ||
587 | if (rdev->pm.default_sclk) | ||
588 | radeon_set_engine_clock(rdev, rdev->pm.default_sclk); | ||
589 | if (rdev->pm.default_mclk) | ||
590 | radeon_set_memory_clock(rdev, rdev->pm.default_mclk); | ||
591 | } | ||
578 | } | 592 | } |
579 | 593 | ||
580 | /* set up the internal thermal sensor if applicable */ | 594 | /* set up the internal thermal sensor if applicable */ |
581 | ret = radeon_hwmon_init(rdev); | 595 | ret = radeon_hwmon_init(rdev); |
582 | if (ret) | 596 | if (ret) |
583 | return ret; | 597 | return ret; |
598 | |||
599 | INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler); | ||
600 | |||
584 | if (rdev->pm.num_power_states > 1) { | 601 | if (rdev->pm.num_power_states > 1) { |
585 | /* where's the best place to put these? */ | 602 | /* where's the best place to put these? */ |
586 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); | 603 | ret = device_create_file(rdev->dev, &dev_attr_power_profile); |
@@ -594,8 +611,6 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
594 | rdev->acpi_nb.notifier_call = radeon_acpi_event; | 611 | rdev->acpi_nb.notifier_call = radeon_acpi_event; |
595 | register_acpi_notifier(&rdev->acpi_nb); | 612 | register_acpi_notifier(&rdev->acpi_nb); |
596 | #endif | 613 | #endif |
597 | INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler); | ||
598 | |||
599 | if (radeon_debugfs_pm_init(rdev)) { | 614 | if (radeon_debugfs_pm_init(rdev)) { |
600 | DRM_ERROR("Failed to register debugfs file for PM!\n"); | 615 | DRM_ERROR("Failed to register debugfs file for PM!\n"); |
601 | } | 616 | } |
@@ -609,25 +624,20 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
609 | void radeon_pm_fini(struct radeon_device *rdev) | 624 | void radeon_pm_fini(struct radeon_device *rdev) |
610 | { | 625 | { |
611 | if (rdev->pm.num_power_states > 1) { | 626 | if (rdev->pm.num_power_states > 1) { |
612 | bool flush_wq = false; | ||
613 | |||
614 | mutex_lock(&rdev->pm.mutex); | 627 | mutex_lock(&rdev->pm.mutex); |
615 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { | 628 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { |
616 | rdev->pm.profile = PM_PROFILE_DEFAULT; | 629 | rdev->pm.profile = PM_PROFILE_DEFAULT; |
617 | radeon_pm_update_profile(rdev); | 630 | radeon_pm_update_profile(rdev); |
618 | radeon_pm_set_clocks(rdev); | 631 | radeon_pm_set_clocks(rdev); |
619 | } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) { | 632 | } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) { |
620 | /* cancel work */ | ||
621 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | ||
622 | flush_wq = true; | ||
623 | /* reset default clocks */ | 633 | /* reset default clocks */ |
624 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; | 634 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; |
625 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; | 635 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; |
626 | radeon_pm_set_clocks(rdev); | 636 | radeon_pm_set_clocks(rdev); |
627 | } | 637 | } |
628 | mutex_unlock(&rdev->pm.mutex); | 638 | mutex_unlock(&rdev->pm.mutex); |
629 | if (flush_wq) | 639 | |
630 | flush_workqueue(rdev->wq); | 640 | cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); |
631 | 641 | ||
632 | device_remove_file(rdev->dev, &dev_attr_power_profile); | 642 | device_remove_file(rdev->dev, &dev_attr_power_profile); |
633 | device_remove_file(rdev->dev, &dev_attr_power_method); | 643 | device_remove_file(rdev->dev, &dev_attr_power_method); |
@@ -686,12 +696,12 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) | |||
686 | radeon_pm_get_dynpm_state(rdev); | 696 | radeon_pm_get_dynpm_state(rdev); |
687 | radeon_pm_set_clocks(rdev); | 697 | radeon_pm_set_clocks(rdev); |
688 | 698 | ||
689 | queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, | 699 | schedule_delayed_work(&rdev->pm.dynpm_idle_work, |
690 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | 700 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); |
691 | } else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) { | 701 | } else if (rdev->pm.dynpm_state == DYNPM_STATE_PAUSED) { |
692 | rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; | 702 | rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; |
693 | queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, | 703 | schedule_delayed_work(&rdev->pm.dynpm_idle_work, |
694 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | 704 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); |
695 | DRM_DEBUG_DRIVER("radeon: dynamic power management activated\n"); | 705 | DRM_DEBUG_DRIVER("radeon: dynamic power management activated\n"); |
696 | } | 706 | } |
697 | } else { /* count == 0 */ | 707 | } else { /* count == 0 */ |
@@ -720,9 +730,9 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev) | |||
720 | */ | 730 | */ |
721 | for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { | 731 | for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { |
722 | if (rdev->pm.active_crtcs & (1 << crtc)) { | 732 | if (rdev->pm.active_crtcs & (1 << crtc)) { |
723 | vbl_status = radeon_get_crtc_scanoutpos(rdev, crtc, &vpos, &hpos); | 733 | vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos); |
724 | if ((vbl_status & RADEON_SCANOUTPOS_VALID) && | 734 | if ((vbl_status & DRM_SCANOUTPOS_VALID) && |
725 | !(vbl_status & RADEON_SCANOUTPOS_INVBL)) | 735 | !(vbl_status & DRM_SCANOUTPOS_INVBL)) |
726 | in_vbl = false; | 736 | in_vbl = false; |
727 | } | 737 | } |
728 | } | 738 | } |
@@ -796,8 +806,8 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work) | |||
796 | radeon_pm_set_clocks(rdev); | 806 | radeon_pm_set_clocks(rdev); |
797 | } | 807 | } |
798 | 808 | ||
799 | queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, | 809 | schedule_delayed_work(&rdev->pm.dynpm_idle_work, |
800 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | 810 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); |
801 | } | 811 | } |
802 | mutex_unlock(&rdev->pm.mutex); | 812 | mutex_unlock(&rdev->pm.mutex); |
803 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | 813 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); |
@@ -814,9 +824,9 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) | |||
814 | struct drm_device *dev = node->minor->dev; | 824 | struct drm_device *dev = node->minor->dev; |
815 | struct radeon_device *rdev = dev->dev_private; | 825 | struct radeon_device *rdev = dev->dev_private; |
816 | 826 | ||
817 | seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk); | 827 | seq_printf(m, "default engine clock: %u0 kHz\n", rdev->pm.default_sclk); |
818 | seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); | 828 | seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); |
819 | seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk); | 829 | seq_printf(m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk); |
820 | if (rdev->asic->get_memory_clock) | 830 | if (rdev->asic->get_memory_clock) |
821 | seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); | 831 | seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); |
822 | if (rdev->pm.current_vddc) | 832 | if (rdev->pm.current_vddc) |