Skip to content

Commit

Permalink
drm/i915: introduce struct intel_crtc_config
Browse files Browse the repository at this point in the history
Currently only containing the requested and the adjusted mode. And
only crtc callbacks are converted somewhat to it, encoders will be
done on a as-needed basis (simply too much churn in one patch
otherwise).

Future patches will add tons more useful stuff to this struct,
starting with the very simple.

v2: Store the pipe_config in the intel_crtc, so that the ->mode-set,
->enable and also ->disable have easy access to it.

v3: Store the pipe config in the right crtc ...

v4: Rebased.

v5: Fixup an OOPS when trying to kfree an ERR_PTR.

v6: Used drm_moode_copy and some other small cleanups as suggested
by Ville Syrjälä.

v7: drm_mode_copy preserves the mode id of the destination, so no need
to clear it again (Ville).

v8: Break a long line spotted by Paulo.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Daniel Vetter committed Mar 27, 2013
1 parent 7c23396 commit b8cecdf
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 36 deletions.
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ struct drm_i915_error_state {
struct intel_display_error_state *display;
};

struct intel_crtc_config;

struct drm_i915_display_funcs {
bool (*fbc_enabled)(struct drm_device *dev);
void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
Expand All @@ -297,8 +299,6 @@ struct drm_i915_display_funcs {
struct drm_display_mode *mode);
void (*modeset_global_resources)(struct drm_device *dev);
int (*crtc_mode_set)(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *old_fb);
void (*crtc_enable)(struct drm_crtc *crtc);
Expand Down
82 changes: 48 additions & 34 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -3971,15 +3971,16 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
return encoder->get_hw_state(encoder, &pipe);
}

static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
static bool intel_crtc_compute_config(struct drm_crtc *crtc,
struct intel_crtc_config *pipe_config)
{
struct drm_device *dev = crtc->dev;
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;

if (HAS_PCH_SPLIT(dev)) {
/* FDI link clock is fixed at 2.7G */
if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4)
if (pipe_config->requested_mode.clock * 3
> IRONLAKE_FDI_FREQ * 4)
return false;
}

Expand Down Expand Up @@ -4665,14 +4666,15 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
}

static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *fb)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_display_mode *adjusted_mode =
&intel_crtc->config.adjusted_mode;
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
int refclk, num_connectors = 0;
Expand Down Expand Up @@ -5637,14 +5639,15 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
}

static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *fb)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_display_mode *adjusted_mode =
&intel_crtc->config.adjusted_mode;
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
int num_connectors = 0;
Expand Down Expand Up @@ -5803,14 +5806,15 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
}

static int haswell_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *fb)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_display_mode *adjusted_mode =
&intel_crtc->config.adjusted_mode;
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
int num_connectors = 0;
Expand Down Expand Up @@ -5887,8 +5891,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
}

static int intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y,
struct drm_framebuffer *fb)
{
Expand All @@ -5897,6 +5899,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_encoder_helper_funcs *encoder_funcs;
struct intel_encoder *encoder;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_display_mode *adjusted_mode =
&intel_crtc->config.adjusted_mode;
struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
int pipe = intel_crtc->pipe;
int ret;

Expand All @@ -5907,8 +5912,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,

drm_vblank_pre_modeset(dev, pipe);

ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
x, y, fb);
ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb);

drm_vblank_post_modeset(dev, pipe);

if (ret != 0)
Expand Down Expand Up @@ -7530,19 +7535,22 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
}
}

static struct drm_display_mode *
intel_modeset_adjusted_mode(struct drm_crtc *crtc,
struct drm_display_mode *mode)
static struct intel_crtc_config *
intel_modeset_pipe_config(struct drm_crtc *crtc,
struct drm_display_mode *mode)
{
struct drm_device *dev = crtc->dev;
struct drm_display_mode *adjusted_mode;
struct drm_encoder_helper_funcs *encoder_funcs;
struct intel_encoder *encoder;
struct intel_crtc_config *pipe_config;

adjusted_mode = drm_mode_duplicate(dev, mode);
if (!adjusted_mode)
pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
if (!pipe_config)
return ERR_PTR(-ENOMEM);

drm_mode_copy(&pipe_config->adjusted_mode, mode);
drm_mode_copy(&pipe_config->requested_mode, mode);

/* Pass our mode to the connectors and the CRTC to give them a chance to
* adjust it according to limitations or connector properties, and also
* a chance to reject the mode entirely.
Expand All @@ -7553,22 +7561,23 @@ intel_modeset_adjusted_mode(struct drm_crtc *crtc,
if (&encoder->new_crtc->base != crtc)
continue;
encoder_funcs = encoder->base.helper_private;
if (!(encoder_funcs->mode_fixup(&encoder->base, mode,
adjusted_mode))) {
if (!(encoder_funcs->mode_fixup(&encoder->base,
&pipe_config->requested_mode,
&pipe_config->adjusted_mode))) {
DRM_DEBUG_KMS("Encoder fixup failed\n");
goto fail;
}
}

if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
if (!(intel_crtc_compute_config(crtc, pipe_config))) {
DRM_DEBUG_KMS("CRTC fixup failed\n");
goto fail;
}
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);

return adjusted_mode;
return pipe_config;
fail:
drm_mode_destroy(dev, adjusted_mode);
kfree(pipe_config);
return ERR_PTR(-EINVAL);
}

Expand Down Expand Up @@ -7834,7 +7843,8 @@ int intel_set_mode(struct drm_crtc *crtc,
{
struct drm_device *dev = crtc->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode;
struct drm_display_mode *saved_mode, *saved_hwmode;
struct intel_crtc_config *pipe_config = NULL;
struct intel_crtc *intel_crtc;
unsigned disable_pipes, prepare_pipes, modeset_pipes;
int ret = 0;
Expand All @@ -7861,11 +7871,12 @@ int intel_set_mode(struct drm_crtc *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. */
adjusted_mode = NULL;
if (modeset_pipes) {
adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
if (IS_ERR(adjusted_mode)) {
ret = PTR_ERR(adjusted_mode);
pipe_config = intel_modeset_pipe_config(crtc, mode);
if (IS_ERR(pipe_config)) {
ret = PTR_ERR(pipe_config);
pipe_config = NULL;

goto out;
}
}
Expand All @@ -7878,8 +7889,12 @@ 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.
*/
if (modeset_pipes)
if (modeset_pipes) {
crtc->mode = *mode;
/* mode_set/enable/disable functions rely on a correct pipe
* config. */
to_intel_crtc(crtc)->config = *pipe_config;
}

/* Only after disabling all output pipelines that will be changed can we
* update the the output configuration. */
Expand All @@ -7893,7 +7908,6 @@ int intel_set_mode(struct drm_crtc *crtc,
*/
for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
ret = intel_crtc_mode_set(&intel_crtc->base,
mode, adjusted_mode,
x, y, fb);
if (ret)
goto done;
Expand All @@ -7905,7 +7919,7 @@ int intel_set_mode(struct drm_crtc *crtc,

if (modeset_pipes) {
/* Store real post-adjustment hardware mode. */
crtc->hwmode = *adjusted_mode;
crtc->hwmode = pipe_config->adjusted_mode;

/* Calculate and store various constants which
* are later needed by vblank and swap-completion
Expand All @@ -7916,7 +7930,6 @@ int intel_set_mode(struct drm_crtc *crtc,

/* FIXME: add subpixel order */
done:
drm_mode_destroy(dev, adjusted_mode);
if (ret && crtc->enabled) {
crtc->hwmode = *saved_hwmode;
crtc->mode = *saved_mode;
Expand All @@ -7925,6 +7938,7 @@ int intel_set_mode(struct drm_crtc *crtc,
}

out:
kfree(pipe_config);
kfree(saved_mode);
return ret;
}
Expand Down
7 changes: 7 additions & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ struct intel_connector {
struct edid *edid;
};

struct intel_crtc_config {
struct drm_display_mode requested_mode;
struct drm_display_mode adjusted_mode;
};

struct intel_crtc {
struct drm_crtc base;
enum pipe pipe;
Expand Down Expand Up @@ -233,6 +238,8 @@ struct intel_crtc {
bool cursor_visible;
unsigned int bpp;

struct intel_crtc_config config;

/* We can share PLLs across outputs if the timings match */
struct intel_pch_pll *pch_pll;
uint32_t ddi_pll_sel;
Expand Down

0 comments on commit b8cecdf

Please sign in to comment.