Commit 083320eb authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-next-fixes-2020-10-02' of...

Merge tag 'drm-misc-next-fixes-2020-10-02' of git://anongit.freedesktop.org/drm/drm-misc

 into drm-next

Three fixes for vc4 that addresses dual-display breakages

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maxime Ripard <maxime@cerno.tech>
Link: https://patchwork.freedesktop.org/patch/msgid/20201002065243.ry7gp4or3ywhluer@gilmour.lan
parents edb89984 8ba0b6d1
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -852,11 +852,19 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc,

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)
		__drm_atomic_helper_crtc_reset(crtc, crtc->state);

	vc4_crtc_state = kzalloc(sizeof(*vc4_crtc_state), GFP_KERNEL);
	if (!vc4_crtc_state) {
		crtc->state = NULL;
		return;
	}

	vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED;
	__drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base);
}

static const struct drm_crtc_funcs vc4_crtc_funcs = {
+2 −0
Original line number Diff line number Diff line
@@ -532,6 +532,8 @@ struct vc4_crtc_state {
	} margins;
};

#define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1)

static inline struct vc4_crtc_state *
to_vc4_crtc_state(struct drm_crtc_state *crtc_state)
{
+16 −6
Original line number Diff line number Diff line
@@ -616,7 +616,7 @@ static int
vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
{
	unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
	struct drm_crtc_state *crtc_state;
	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
	struct drm_crtc *crtc;
	int i, ret;

@@ -629,6 +629,8 @@ 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;

@@ -637,15 +639,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);
		unsigned int matching_channels;

		if (!crtc_state->active)
		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
		 * up to 7 encoders, connected to up to 6 CRTCs.
@@ -674,7 +684,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
		if (matching_channels) {
			unsigned int channel = ffs(matching_channels) - 1;

			vc4_crtc_state->assigned_channel = channel;
			new_vc4_crtc_state->assigned_channel = channel;
			unassigned_channels &= ~BIT(channel);
		} else {
			return -EINVAL;