drm/vc4: crtc: Keep the previously assigned HVS FIFO
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / vc4 / vc4_kms.c
index 96aadcb..77745ad 100644 (file)
@@ -585,7 +585,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
        unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
        struct vc4_dev *vc4 = to_vc4_dev(state->dev);
-       struct drm_crtc_state *crtc_state;
+       struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_crtc *crtc;
        int i, ret;
 
@@ -598,6 +598,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
         * modified.
         */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               struct drm_crtc_state *crtc_state;
                if (!crtc->state->enable)
                        continue;
 
@@ -606,15 +607,23 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
                        return PTR_ERR(crtc_state);
        }
 
-       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-               struct vc4_crtc_state *vc4_crtc_state =
-                       to_vc4_crtc_state(crtc_state);
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               struct vc4_crtc_state *new_vc4_crtc_state =
+                       to_vc4_crtc_state(new_crtc_state);
                struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
                bool is_assigned = false;
                unsigned int channel;
 
-               if (!crtc_state->enable || vc4->firmware_kms)
+               if (old_crtc_state->enable && !new_crtc_state->enable)
+                       new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED;
+
+               if (!new_crtc_state->enable)
+                       continue;
+
+               if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) {
+                       unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel);
                        continue;
+               }
 
                /*
                 * The problem we have to solve here is that we have
@@ -646,7 +655,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
                        if (!(BIT(channel) & vc4_crtc->data->hvs_available_channels))
                                continue;
 
-                       vc4_crtc_state->assigned_channel = channel;
+                       new_vc4_crtc_state->assigned_channel = channel;
                        unassigned_channels &= ~BIT(channel);
                        is_assigned = true;
                        break;