Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f27126e authored by Jesse Barnes's avatar Jesse Barnes Committed by Daniel Vetter
Browse files

drm/i915: factor out compute_config from __intel_set_mode v3



This allows us to calculate the full pipe config before we do any mode
setting work.

v2:
  - clarify comments about global vs. per-crtc mode set (Ander)
  - clean up unnecessary pipe_config = NULL setting (Ander)
v3:
  - fix pipe_config handling (alloc in compute_config, free in set_mode) (Jesse)
  - fix arg order in set_mode (Jesse)
  - fix failure path of set_config (Ander)

Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: default avatarAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 260d8f98
Loading
Loading
Loading
Loading
+74 −31
Original line number Diff line number Diff line
@@ -10741,45 +10741,60 @@ static void update_scanline_offset(struct intel_crtc *crtc)
		crtc->scanline_offset = 1;
}

static int __intel_set_mode(struct drm_crtc *crtc,
static struct intel_crtc_config *
intel_modeset_compute_config(struct drm_crtc *crtc,
			     struct drm_display_mode *mode,
			    int x, int y, struct drm_framebuffer *fb)
			     struct drm_framebuffer *fb,
			     unsigned *modeset_pipes,
			     unsigned *prepare_pipes,
			     unsigned *disable_pipes)
{
	struct drm_device *dev = crtc->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_display_mode *saved_mode;
	struct intel_crtc_config *pipe_config = NULL;
	struct intel_crtc *intel_crtc;
	unsigned disable_pipes, prepare_pipes, modeset_pipes;
	int ret = 0;

	saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL);
	if (!saved_mode)
		return -ENOMEM;

	intel_modeset_affected_pipes(crtc, &modeset_pipes,
				     &prepare_pipes, &disable_pipes);
	intel_modeset_affected_pipes(crtc, modeset_pipes,
				     prepare_pipes, disable_pipes);

	*saved_mode = crtc->mode;
	if ((*modeset_pipes) == 0)
		goto out;

	/* Hack: Because we don't (yet) support global modeset on multiple
	 * crtcs, we don't keep track of the new mode for more than one crtc.
	 * Hence simply check whether any bit is set in modeset_pipes in all the
	 * pieces of code that are not yet converted to deal with mutliple crtcs
	 * changing their mode at the same time. */
	if (modeset_pipes) {
	/*
	 * Note this needs changes when we start tracking multiple modes
	 * and crtcs.  At that point we'll need to compute the whole config
	 * (i.e. one pipe_config for each crtc) rather than just the one
	 * for this crtc.
	 */
	pipe_config = intel_modeset_pipe_config(crtc, fb, mode);
	if (IS_ERR(pipe_config)) {
			ret = PTR_ERR(pipe_config);
			pipe_config = NULL;

		goto out;
	}
	intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
			       "[modeset]");
	to_intel_crtc(crtc)->new_config = pipe_config;

out:
	return pipe_config;
}

static int __intel_set_mode(struct drm_crtc *crtc,
			    struct drm_display_mode *mode,
			    int x, int y, struct drm_framebuffer *fb,
			    struct intel_crtc_config *pipe_config,
			    unsigned modeset_pipes,
			    unsigned prepare_pipes,
			    unsigned disable_pipes)
{
	struct drm_device *dev = crtc->dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_display_mode *saved_mode;
	struct intel_crtc *intel_crtc;
	int ret = 0;

	saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL);
	if (!saved_mode)
		return -ENOMEM;

	*saved_mode = crtc->mode;

	/*
	 * See if the config requires any additional preparation, e.g.
	 * to adjust global state with pipes off.  We need to do this
@@ -10820,6 +10835,10 @@ static int __intel_set_mode(struct drm_crtc *crtc,

	/* crtc->mode is already used by the ->mode_set callbacks, hence we need
	 * to set it here already despite that we pass it down the callchain.
	 *
	 * Note we'll need to fix this up when we start tracking multiple
	 * pipes; here we assume a single modeset_pipe and only track the
	 * single crtc and mode.
	 */
	if (modeset_pipes) {
		crtc->mode = *mode;
@@ -10881,19 +10900,23 @@ static int __intel_set_mode(struct drm_crtc *crtc,
	if (ret && crtc->enabled)
		crtc->mode = *saved_mode;

out:
	kfree(pipe_config);
	kfree(saved_mode);
	return ret;
}

static int intel_set_mode(struct drm_crtc *crtc,
static int intel_set_mode_pipes(struct drm_crtc *crtc,
				struct drm_display_mode *mode,
			  int x, int y, struct drm_framebuffer *fb)
				int x, int y, struct drm_framebuffer *fb,
				struct intel_crtc_config *pipe_config,
				unsigned modeset_pipes,
				unsigned prepare_pipes,
				unsigned disable_pipes)
{
	int ret;

	ret = __intel_set_mode(crtc, mode, x, y, fb);
	ret = __intel_set_mode(crtc, mode, x, y, fb, pipe_config, modeset_pipes,
			       prepare_pipes, disable_pipes);

	if (ret == 0)
		intel_modeset_check_state(crtc->dev);
@@ -10901,6 +10924,26 @@ static int intel_set_mode(struct drm_crtc *crtc,
	return ret;
}

static int intel_set_mode(struct drm_crtc *crtc,
			  struct drm_display_mode *mode,
			  int x, int y, struct drm_framebuffer *fb)
{
	struct intel_crtc_config *pipe_config;
	unsigned modeset_pipes, prepare_pipes, disable_pipes;

	pipe_config = intel_modeset_compute_config(crtc, mode, fb,
						   &modeset_pipes,
						   &prepare_pipes,
						   &disable_pipes);

	if (IS_ERR(pipe_config))
		return PTR_ERR(pipe_config);

	return intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config,
				    modeset_pipes, prepare_pipes,
				    disable_pipes);
}

void intel_crtc_restore_mode(struct drm_crtc *crtc)
{
	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
@@ -13249,7 +13292,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
			struct drm_crtc *crtc =
				dev_priv->pipe_to_crtc_mapping[pipe];

			__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
			intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
				       crtc->primary->fb);
		}
	} else {