Merge tag 'v3.14' into drm-intel-next-queued
[deliverable/linux.git] / drivers / gpu / drm / radeon / radeon_pm.c
index 984097b907ef5ee67c8e59faf4198ccf8add5f1b..ee738a524639e41e75c7af5279c583e4b3c7ee10 100644 (file)
@@ -260,7 +260,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
                if (!ring->ready) {
                        continue;
                }
-               r = radeon_fence_wait_empty_locked(rdev, i);
+               r = radeon_fence_wait_empty(rdev, i);
                if (r) {
                        /* needs a GPU reset dont reset here */
                        mutex_unlock(&rdev->ring_lock);
@@ -826,6 +826,9 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 
        /* no need to reprogram if nothing changed unless we are on BTC+ */
        if (rdev->pm.dpm.current_ps == rdev->pm.dpm.requested_ps) {
+               /* vce just modifies an existing state so force a change */
+               if (ps->vce_active != rdev->pm.dpm.vce_active)
+                       goto force;
                if ((rdev->family < CHIP_BARTS) || (rdev->flags & RADEON_IS_IGP)) {
                        /* for pre-BTC and APUs if the num crtcs changed but state is the same,
                         * all we need to do is update the display configuration.
@@ -862,16 +865,21 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
                }
        }
 
+force:
        if (radeon_dpm == 1) {
                printk("switching from power state:\n");
                radeon_dpm_print_power_state(rdev, rdev->pm.dpm.current_ps);
                printk("switching to power state:\n");
                radeon_dpm_print_power_state(rdev, rdev->pm.dpm.requested_ps);
        }
+
        mutex_lock(&rdev->ddev->struct_mutex);
        down_write(&rdev->pm.mclk_lock);
        mutex_lock(&rdev->ring_lock);
 
+       /* update whether vce is active */
+       ps->vce_active = rdev->pm.dpm.vce_active;
+
        ret = radeon_dpm_pre_set_power_state(rdev);
        if (ret)
                goto done;
@@ -888,7 +896,7 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
        for (i = 0; i < RADEON_NUM_RINGS; i++) {
                struct radeon_ring *ring = &rdev->ring[i];
                if (ring->ready)
-                       radeon_fence_wait_empty_locked(rdev, i);
+                       radeon_fence_wait_empty(rdev, i);
        }
 
        /* program the new power state */
@@ -924,6 +932,10 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
 
        if (rdev->asic->dpm.powergate_uvd) {
                mutex_lock(&rdev->pm.mutex);
+               /* don't powergate anything if we
+                  have active but pause streams */
+               enable |= rdev->pm.dpm.sd > 0;
+               enable |= rdev->pm.dpm.hd > 0;
                /* enable/disable UVD */
                radeon_dpm_powergate_uvd(rdev, !enable);
                mutex_unlock(&rdev->pm.mutex);
@@ -931,8 +943,6 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
                if (enable) {
                        mutex_lock(&rdev->pm.mutex);
                        rdev->pm.dpm.uvd_active = true;
-                       /* disable this for now */
-#if 0
                        if ((rdev->pm.dpm.sd == 1) && (rdev->pm.dpm.hd == 0))
                                dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_SD;
                        else if ((rdev->pm.dpm.sd == 2) && (rdev->pm.dpm.hd == 0))
@@ -942,7 +952,6 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
                        else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2))
                                dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2;
                        else
-#endif
                                dpm_state = POWER_STATE_TYPE_INTERNAL_UVD;
                        rdev->pm.dpm.state = dpm_state;
                        mutex_unlock(&rdev->pm.mutex);
@@ -956,6 +965,23 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
        }
 }
 
+void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable)
+{
+       if (enable) {
+               mutex_lock(&rdev->pm.mutex);
+               rdev->pm.dpm.vce_active = true;
+               /* XXX select vce level based on ring/task */
+               rdev->pm.dpm.vce_level = RADEON_VCE_LEVEL_AC_ALL;
+               mutex_unlock(&rdev->pm.mutex);
+       } else {
+               mutex_lock(&rdev->pm.mutex);
+               rdev->pm.dpm.vce_active = false;
+               mutex_unlock(&rdev->pm.mutex);
+       }
+
+       radeon_pm_compute_clocks(rdev);
+}
+
 static void radeon_pm_suspend_old(struct radeon_device *rdev)
 {
        mutex_lock(&rdev->pm.mutex);
@@ -1010,8 +1036,10 @@ static void radeon_pm_resume_old(struct radeon_device *rdev)
        rdev->pm.current_clock_mode_index = 0;
        rdev->pm.current_sclk = rdev->pm.default_sclk;
        rdev->pm.current_mclk = rdev->pm.default_mclk;
-       rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
-       rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+       if (rdev->pm.power_state) {
+               rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+               rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
+       }
        if (rdev->pm.pm_method == PM_METHOD_DYNPM
            && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
                rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
@@ -1032,25 +1060,27 @@ static void radeon_pm_resume_dpm(struct radeon_device *rdev)
        radeon_dpm_setup_asic(rdev);
        ret = radeon_dpm_enable(rdev);
        mutex_unlock(&rdev->pm.mutex);
-       if (ret) {
-               DRM_ERROR("radeon: dpm resume failed\n");
-               if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_CAYMAN) &&
-                   rdev->mc_fw) {
-                       if (rdev->pm.default_vddc)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDC);
-                       if (rdev->pm.default_vddci)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDCI);
-                       if (rdev->pm.default_sclk)
-                               radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
-                       if (rdev->pm.default_mclk)
-                               radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
-               }
-       } else {
-               rdev->pm.dpm_enabled = true;
-               radeon_pm_compute_clocks(rdev);
+       if (ret)
+               goto dpm_resume_fail;
+       rdev->pm.dpm_enabled = true;
+       radeon_pm_compute_clocks(rdev);
+       return;
+
+dpm_resume_fail:
+       DRM_ERROR("radeon: dpm resume failed\n");
+       if ((rdev->family >= CHIP_BARTS) &&
+           (rdev->family <= CHIP_CAYMAN) &&
+           rdev->mc_fw) {
+               if (rdev->pm.default_vddc)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDC);
+               if (rdev->pm.default_vddci)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDCI);
+               if (rdev->pm.default_sclk)
+                       radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+               if (rdev->pm.default_mclk)
+                       radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
        }
 }
 
@@ -1170,51 +1200,50 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
        radeon_dpm_setup_asic(rdev);
        ret = radeon_dpm_enable(rdev);
        mutex_unlock(&rdev->pm.mutex);
-       if (ret) {
-               rdev->pm.dpm_enabled = false;
-               if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_CAYMAN) &&
-                   rdev->mc_fw) {
-                       if (rdev->pm.default_vddc)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDC);
-                       if (rdev->pm.default_vddci)
-                               radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
-                                                       SET_VOLTAGE_TYPE_ASIC_VDDCI);
-                       if (rdev->pm.default_sclk)
-                               radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
-                       if (rdev->pm.default_mclk)
-                               radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
-               }
-               DRM_ERROR("radeon: dpm initialization failed\n");
-               return ret;
-       }
+       if (ret)
+               goto dpm_failed;
        rdev->pm.dpm_enabled = true;
-       radeon_pm_compute_clocks(rdev);
-
-       if (rdev->pm.num_power_states > 1) {
-               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
-               if (ret)
-                       DRM_ERROR("failed to create device file for dpm state\n");
-               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
-               if (ret)
-                       DRM_ERROR("failed to create device file for dpm state\n");
-               /* XXX: these are noops for dpm but are here for backwards compat */
-               ret = device_create_file(rdev->dev, &dev_attr_power_profile);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power profile\n");
-               ret = device_create_file(rdev->dev, &dev_attr_power_method);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power method\n");
 
-               if (radeon_debugfs_pm_init(rdev)) {
-                       DRM_ERROR("Failed to register debugfs file for dpm!\n");
-               }
+       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
+       if (ret)
+               DRM_ERROR("failed to create device file for dpm state\n");
+       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
+       if (ret)
+               DRM_ERROR("failed to create device file for dpm state\n");
+       /* XXX: these are noops for dpm but are here for backwards compat */
+       ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+       if (ret)
+               DRM_ERROR("failed to create device file for power profile\n");
+       ret = device_create_file(rdev->dev, &dev_attr_power_method);
+       if (ret)
+               DRM_ERROR("failed to create device file for power method\n");
 
-               DRM_INFO("radeon: dpm initialized\n");
+       if (radeon_debugfs_pm_init(rdev)) {
+               DRM_ERROR("Failed to register debugfs file for dpm!\n");
        }
 
+       DRM_INFO("radeon: dpm initialized\n");
+
        return 0;
+
+dpm_failed:
+       rdev->pm.dpm_enabled = false;
+       if ((rdev->family >= CHIP_BARTS) &&
+           (rdev->family <= CHIP_CAYMAN) &&
+           rdev->mc_fw) {
+               if (rdev->pm.default_vddc)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDC);
+               if (rdev->pm.default_vddci)
+                       radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+                                               SET_VOLTAGE_TYPE_ASIC_VDDCI);
+               if (rdev->pm.default_sclk)
+                       radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
+               if (rdev->pm.default_mclk)
+                       radeon_set_memory_clock(rdev, rdev->pm.default_mclk);
+       }
+       DRM_ERROR("radeon: dpm initialization failed\n");
+       return ret;
 }
 
 int radeon_pm_init(struct radeon_device *rdev)
@@ -1228,11 +1257,10 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_RV670:
        case CHIP_RS780:
        case CHIP_RS880:
+       case CHIP_BARTS:
+       case CHIP_TURKS:
+       case CHIP_CAICOS:
        case CHIP_CAYMAN:
-       case CHIP_BONAIRE:
-       case CHIP_KABINI:
-       case CHIP_KAVERI:
-       case CHIP_HAWAII:
                /* DPM requires the RLC, RV770+ dGPU requires SMC */
                if (!rdev->rlc_fw)
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1257,15 +1285,16 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_PALM:
        case CHIP_SUMO:
        case CHIP_SUMO2:
-       case CHIP_BARTS:
-       case CHIP_TURKS:
-       case CHIP_CAICOS:
        case CHIP_ARUBA:
        case CHIP_TAHITI:
        case CHIP_PITCAIRN:
        case CHIP_VERDE:
        case CHIP_OLAND:
        case CHIP_HAINAN:
+       case CHIP_BONAIRE:
+       case CHIP_KABINI:
+       case CHIP_KAVERI:
+       case CHIP_HAWAII:
                /* DPM requires the RLC, RV770+ dGPU requires SMC */
                if (!rdev->rlc_fw)
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1290,6 +1319,18 @@ int radeon_pm_init(struct radeon_device *rdev)
                return radeon_pm_init_old(rdev);
 }
 
+int radeon_pm_late_init(struct radeon_device *rdev)
+{
+       int ret = 0;
+
+       if (rdev->pm.pm_method == PM_METHOD_DPM) {
+               mutex_lock(&rdev->pm.mutex);
+               ret = radeon_dpm_late_enable(rdev);
+               mutex_unlock(&rdev->pm.mutex);
+       }
+       return ret;
+}
+
 static void radeon_pm_fini_old(struct radeon_device *rdev)
 {
        if (rdev->pm.num_power_states > 1) {
@@ -1420,6 +1461,9 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
        struct drm_crtc *crtc;
        struct radeon_crtc *radeon_crtc;
 
+       if (!rdev->pm.dpm_enabled)
+               return;
+
        mutex_lock(&rdev->pm.mutex);
 
        /* update active crtc counts */
@@ -1464,7 +1508,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
         */
        for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
                if (rdev->pm.active_crtcs & (1 << crtc)) {
-                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos, NULL, NULL);
+                       vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, 0, &vpos, &hpos, NULL, NULL);
                        if ((vbl_status & DRM_SCANOUTPOS_VALID) &&
                            !(vbl_status & DRM_SCANOUTPOS_INVBL))
                                in_vbl = false;
This page took 0.037611 seconds and 5 git commands to generate.