struct radeon_dpm_thermal thermal;
        /* forced levels */
        enum radeon_dpm_forced_level forced_level;
+       /* track UVD streams */
+       unsigned sd;
+       unsigned hd;
 };
 
 void radeon_dpm_enable_power_state(struct radeon_device *rdev,
                                    enum radeon_pm_state_type dpm_state);
-
+void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable);
 
 struct radeon_pm {
        struct mutex            mutex;
 
                DRM_ERROR("Invalid command stream !\n");
                return r;
        }
+
+       if (parser->ring == R600_RING_TYPE_UVD_INDEX)
+               radeon_uvd_note_usage(rdev);
+
        radeon_cs_sync_rings(parser);
        r = radeon_ib_schedule(rdev, &parser->ib, NULL);
        if (r) {
                return r;
        }
 
+       if (parser->ring == R600_RING_TYPE_UVD_INDEX)
+               radeon_uvd_note_usage(rdev);
+
        mutex_lock(&rdev->vm_manager.lock);
        mutex_lock(&vm->mutex);
        r = radeon_vm_alloc_pt(rdev, vm);
                return r;
        }
 
-       /* XXX pick SD/HD/MVC */
-       if (parser.ring == R600_RING_TYPE_UVD_INDEX)
-               radeon_uvd_note_usage(rdev);
-
        r = radeon_cs_ib_chunk(rdev, &parser);
        if (r) {
                goto out;
 
        /* use a fallback state if we didn't match */
        switch (dpm_state) {
        case POWER_STATE_TYPE_INTERNAL_UVD_SD:
+               dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD;
+               goto restart_search;
        case POWER_STATE_TYPE_INTERNAL_UVD_HD:
        case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
        case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
        radeon_pm_compute_clocks(rdev);
 }
 
+void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
+{
+       enum radeon_pm_state_type dpm_state;
+
+       if (enable) {
+               mutex_lock(&rdev->pm.mutex);
+               rdev->pm.dpm.uvd_active = true;
+               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))
+                       dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD;
+               else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 1))
+                       dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD;
+               else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2))
+                       dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2;
+               else
+                       dpm_state = POWER_STATE_TYPE_INTERNAL_UVD;
+               rdev->pm.dpm.state = dpm_state;
+               mutex_unlock(&rdev->pm.mutex);
+       } else {
+               mutex_lock(&rdev->pm.mutex);
+               rdev->pm.dpm.uvd_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);
 
 
        if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) {
                if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
-                       mutex_lock(&rdev->pm.mutex);
-                       rdev->pm.dpm.uvd_active = false;
-                       mutex_unlock(&rdev->pm.mutex);
-                       radeon_pm_compute_clocks(rdev);
+                       radeon_dpm_enable_uvd(rdev, false);
                } else {
                        radeon_set_uvd_clocks(rdev, 0, 0);
                }
 
 void radeon_uvd_note_usage(struct radeon_device *rdev)
 {
+       bool streams_changed = false;
        bool set_clocks = !cancel_delayed_work_sync(&rdev->uvd.idle_work);
        set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work,
                                            msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
-       if (set_clocks) {
+
+       if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+               unsigned hd = 0, sd = 0;
+               radeon_uvd_count_handles(rdev, &sd, &hd);
+               if ((rdev->pm.dpm.sd != sd) ||
+                   (rdev->pm.dpm.hd != hd)) {
+                       rdev->pm.dpm.sd = sd;
+                       rdev->pm.dpm.hd = hd;
+                       streams_changed = true;
+               }
+       }
+
+       if (set_clocks || streams_changed) {
                if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
-                       /* XXX pick SD/HD/MVC */
-                       radeon_dpm_enable_power_state(rdev, POWER_STATE_TYPE_INTERNAL_UVD);
+                       radeon_dpm_enable_uvd(rdev, true);
                } else {
                        radeon_set_uvd_clocks(rdev, 53300, 40000);
                }