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

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
...@@ -10741,45 +10741,60 @@ static void update_scanline_offset(struct intel_crtc *crtc) ...@@ -10741,45 +10741,60 @@ static void update_scanline_offset(struct intel_crtc *crtc)
crtc->scanline_offset = 1; crtc->scanline_offset = 1;
} }
static struct intel_crtc_config *
intel_modeset_compute_config(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_framebuffer *fb,
unsigned *modeset_pipes,
unsigned *prepare_pipes,
unsigned *disable_pipes)
{
struct intel_crtc_config *pipe_config = NULL;
intel_modeset_affected_pipes(crtc, modeset_pipes,
prepare_pipes, disable_pipes);
if ((*modeset_pipes) == 0)
goto out;
/*
* 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)) {
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, static int __intel_set_mode(struct drm_crtc *crtc,
struct drm_display_mode *mode, 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)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *saved_mode; struct drm_display_mode *saved_mode;
struct intel_crtc_config *pipe_config = NULL;
struct intel_crtc *intel_crtc; struct intel_crtc *intel_crtc;
unsigned disable_pipes, prepare_pipes, modeset_pipes;
int ret = 0; int ret = 0;
saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL); saved_mode = kmalloc(sizeof(*saved_mode), GFP_KERNEL);
if (!saved_mode) if (!saved_mode)
return -ENOMEM; return -ENOMEM;
intel_modeset_affected_pipes(crtc, &modeset_pipes,
&prepare_pipes, &disable_pipes);
*saved_mode = crtc->mode; *saved_mode = crtc->mode;
/* 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) {
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;
}
/* /*
* See if the config requires any additional preparation, e.g. * See if the config requires any additional preparation, e.g.
* to adjust global state with pipes off. We need to do this * 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, ...@@ -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 /* 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. * 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) { if (modeset_pipes) {
crtc->mode = *mode; crtc->mode = *mode;
...@@ -10881,19 +10900,23 @@ static int __intel_set_mode(struct drm_crtc *crtc, ...@@ -10881,19 +10900,23 @@ static int __intel_set_mode(struct drm_crtc *crtc,
if (ret && crtc->enabled) if (ret && crtc->enabled)
crtc->mode = *saved_mode; crtc->mode = *saved_mode;
out:
kfree(pipe_config); kfree(pipe_config);
kfree(saved_mode); kfree(saved_mode);
return ret; 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, 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; 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) if (ret == 0)
intel_modeset_check_state(crtc->dev); intel_modeset_check_state(crtc->dev);
...@@ -10901,6 +10924,26 @@ static int intel_set_mode(struct drm_crtc *crtc, ...@@ -10901,6 +10924,26 @@ static int intel_set_mode(struct drm_crtc *crtc,
return ret; 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) void intel_crtc_restore_mode(struct drm_crtc *crtc)
{ {
intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb); intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
...@@ -13249,8 +13292,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, ...@@ -13249,8 +13292,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
struct drm_crtc *crtc = struct drm_crtc *crtc =
dev_priv->pipe_to_crtc_mapping[pipe]; 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); crtc->primary->fb);
} }
} else { } else {
intel_modeset_update_staged_output_state(dev); intel_modeset_update_staged_output_state(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment