static void
vc4_crtc_reset(struct drm_crtc *crtc)
{
+ struct vc4_crtc_state *vc4_crtc_state;
+
if (crtc->state)
vc4_crtc_destroy_state(crtc, crtc->state);
- crtc->state = kzalloc(sizeof(struct vc4_crtc_state), GFP_KERNEL);
- if (crtc->state)
- crtc->state->crtc = crtc;
+ vc4_crtc_state = kzalloc(sizeof(*vc4_crtc_state), GFP_KERNEL);
+ if (!vc4_crtc_state)
+ return;
+
+ vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED;
+ crtc->state = &vc4_crtc_state->base;
+ crtc->state->crtc = crtc;
}
static const struct drm_crtc_funcs vc4_crtc_funcs = {
{
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;
* modified.
*/
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ struct drm_crtc_state *crtc_state;
if (!crtc->state->enable)
continue;
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
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;