Commit 5bfe2ac0 authored by Daniel Vetter's avatar Daniel Vetter

drm/i915: add pipe_config->has_pch_encoder

This is used way too often in the enable/disable paths. And will
be even more useful in the future.

Note that correct semantics of this change highly depend upon
correct updating of intel_crtc->config: Like with all other
modeset state, we need to call ->disable with the old config,
but ->mode_set and ->enable with the new config.

v2: Do not yet use the flag in the ->disable callbacks - atm we don't
yet have support for the information stored in the pipe_config in the
hw state readout code, so this will be wrong at boot-up/resume.

v3: Rebased on top of the hdmi/dp ddi encoder merging.

v4: Fixup stupid rebase error which lead to a NULL vfunc deref.

v5: On haswell the VGA port is on the PCH!

v6: s/IS_HASWELL/HAS_DDI/, spotted by Paulo Zanoni. Also add a missing
parameter name in a function declaration.

v7: Don't forget to git add ...
Reviewed-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 31fac9dc
...@@ -206,10 +206,14 @@ static int intel_crt_mode_valid(struct drm_connector *connector, ...@@ -206,10 +206,14 @@ static int intel_crt_mode_valid(struct drm_connector *connector,
return MODE_OK; return MODE_OK;
} }
static bool intel_crt_mode_fixup(struct drm_encoder *encoder, static bool intel_crt_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *mode, struct intel_crtc_config *pipe_config)
struct drm_display_mode *adjusted_mode)
{ {
struct drm_device *dev = encoder->base.dev;
if (HAS_PCH_SPLIT(dev))
pipe_config->has_pch_encoder = true;
return true; return true;
} }
...@@ -683,7 +687,6 @@ static void intel_crt_reset(struct drm_connector *connector) ...@@ -683,7 +687,6 @@ static void intel_crt_reset(struct drm_connector *connector)
*/ */
static const struct drm_encoder_helper_funcs crt_encoder_funcs = { static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
.mode_fixup = intel_crt_mode_fixup,
.mode_set = intel_crt_mode_set, .mode_set = intel_crt_mode_set,
}; };
...@@ -774,6 +777,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -774,6 +777,7 @@ void intel_crt_init(struct drm_device *dev)
else else
crt->adpa_reg = ADPA; crt->adpa_reg = ADPA;
crt->base.compute_config = intel_crt_compute_config;
crt->base.disable = intel_disable_crt; crt->base.disable = intel_disable_crt;
crt->base.enable = intel_enable_crt; crt->base.enable = intel_enable_crt;
if (I915_HAS_HOTPLUG(dev)) if (I915_HAS_HOTPLUG(dev))
......
...@@ -1476,19 +1476,17 @@ static void intel_ddi_destroy(struct drm_encoder *encoder) ...@@ -1476,19 +1476,17 @@ static void intel_ddi_destroy(struct drm_encoder *encoder)
intel_dp_encoder_destroy(encoder); intel_dp_encoder_destroy(encoder);
} }
static bool intel_ddi_mode_fixup(struct drm_encoder *encoder, static bool intel_ddi_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *mode, struct intel_crtc_config *pipe_config)
struct drm_display_mode *adjusted_mode)
{ {
struct intel_encoder *intel_encoder = to_intel_encoder(encoder); int type = encoder->type;
int type = intel_encoder->type;
WARN(type == INTEL_OUTPUT_UNKNOWN, "mode_fixup() on unknown output!\n"); WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n");
if (type == INTEL_OUTPUT_HDMI) if (type == INTEL_OUTPUT_HDMI)
return intel_hdmi_mode_fixup(encoder, mode, adjusted_mode); return intel_hdmi_compute_config(encoder, pipe_config);
else else
return intel_dp_mode_fixup(encoder, mode, adjusted_mode); return intel_dp_compute_config(encoder, pipe_config);
} }
static const struct drm_encoder_funcs intel_ddi_funcs = { static const struct drm_encoder_funcs intel_ddi_funcs = {
...@@ -1496,7 +1494,6 @@ static const struct drm_encoder_funcs intel_ddi_funcs = { ...@@ -1496,7 +1494,6 @@ static const struct drm_encoder_funcs intel_ddi_funcs = {
}; };
static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = { static const struct drm_encoder_helper_funcs intel_ddi_helper_funcs = {
.mode_fixup = intel_ddi_mode_fixup,
.mode_set = intel_ddi_mode_set, .mode_set = intel_ddi_mode_set,
}; };
...@@ -1536,6 +1533,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) ...@@ -1536,6 +1533,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
DRM_MODE_ENCODER_TMDS); DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs); drm_encoder_helper_add(encoder, &intel_ddi_helper_funcs);
intel_encoder->compute_config = intel_ddi_compute_config;
intel_encoder->enable = intel_enable_ddi; intel_encoder->enable = intel_enable_ddi;
intel_encoder->pre_enable = intel_ddi_pre_enable; intel_encoder->pre_enable = intel_ddi_pre_enable;
intel_encoder->disable = intel_disable_ddi; intel_encoder->disable = intel_disable_ddi;
......
...@@ -2977,27 +2977,6 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) ...@@ -2977,27 +2977,6 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
static bool ironlake_crtc_driving_pch(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct intel_encoder *intel_encoder;
/*
* If there's a non-PCH eDP on this crtc, it must be DP_A, and that
* must be driven by its own crtc; no sharing is possible.
*/
for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
switch (intel_encoder->type) {
case INTEL_OUTPUT_EDP:
if (!intel_encoder_is_pch_edp(&intel_encoder->base))
return false;
continue;
}
}
return true;
}
static bool haswell_crtc_driving_pch(struct drm_crtc *crtc) static bool haswell_crtc_driving_pch(struct drm_crtc *crtc)
{ {
return intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG); return intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG);
...@@ -3338,7 +3317,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -3338,7 +3317,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
u32 temp; u32 temp;
bool is_pch_port;
WARN_ON(!crtc->enabled); WARN_ON(!crtc->enabled);
...@@ -3354,9 +3332,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -3354,9 +3332,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN); I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
} }
is_pch_port = ironlake_crtc_driving_pch(crtc);
if (is_pch_port) { if (intel_crtc->config.has_pch_encoder) {
/* Note: FDI PLL enabling _must_ be done before we enable the /* Note: FDI PLL enabling _must_ be done before we enable the
* cpu pipes, hence this is separate from all the other fdi/pch * cpu pipes, hence this is separate from all the other fdi/pch
* enabling. */ * enabling. */
...@@ -3393,10 +3370,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) ...@@ -3393,10 +3370,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
*/ */
intel_crtc_load_lut(crtc); intel_crtc_load_lut(crtc);
intel_enable_pipe(dev_priv, pipe, is_pch_port); intel_enable_pipe(dev_priv, pipe,
intel_crtc->config.has_pch_encoder);
intel_enable_plane(dev_priv, plane, pipe); intel_enable_plane(dev_priv, plane, pipe);
if (is_pch_port) if (intel_crtc->config.has_pch_encoder)
ironlake_pch_enable(crtc); ironlake_pch_enable(crtc);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
...@@ -3430,7 +3408,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) ...@@ -3430,7 +3408,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
struct intel_encoder *encoder; struct intel_encoder *encoder;
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane; int plane = intel_crtc->plane;
bool is_pch_port;
WARN_ON(!crtc->enabled); WARN_ON(!crtc->enabled);
...@@ -3440,9 +3417,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) ...@@ -3440,9 +3417,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_crtc->active = true; intel_crtc->active = true;
intel_update_watermarks(dev); intel_update_watermarks(dev);
is_pch_port = haswell_crtc_driving_pch(crtc); if (intel_crtc->config.has_pch_encoder)
if (is_pch_port)
dev_priv->display.fdi_link_train(crtc); dev_priv->display.fdi_link_train(crtc);
for_each_encoder_on_crtc(dev, crtc, encoder) for_each_encoder_on_crtc(dev, crtc, encoder)
...@@ -3473,10 +3448,11 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) ...@@ -3473,10 +3448,11 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_ddi_set_pipe_settings(crtc); intel_ddi_set_pipe_settings(crtc);
intel_ddi_enable_transcoder_func(crtc); intel_ddi_enable_transcoder_func(crtc);
intel_enable_pipe(dev_priv, pipe, is_pch_port); intel_enable_pipe(dev_priv, pipe,
intel_crtc->config.has_pch_encoder);
intel_enable_plane(dev_priv, plane, pipe); intel_enable_plane(dev_priv, plane, pipe);
if (is_pch_port) if (intel_crtc->config.has_pch_encoder)
lpt_pch_enable(crtc); lpt_pch_enable(crtc);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
......
...@@ -689,12 +689,13 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, ...@@ -689,12 +689,13 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
} }
bool bool
intel_dp_mode_fixup(struct drm_encoder *encoder, intel_dp_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *mode, struct intel_crtc_config *pipe_config)
struct drm_display_mode *adjusted_mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->base.dev;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
struct drm_display_mode *mode = &pipe_config->requested_mode;
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
struct intel_connector *intel_connector = intel_dp->attached_connector; struct intel_connector *intel_connector = intel_dp->attached_connector;
int lane_count, clock; int lane_count, clock;
int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd); int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
...@@ -702,6 +703,9 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, ...@@ -702,6 +703,9 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,
int bpp, mode_rate; int bpp, mode_rate;
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && !is_cpu_edp(intel_dp))
pipe_config->has_pch_encoder = true;
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) { if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
intel_fixed_panel_mode(intel_connector->panel.fixed_mode, intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
adjusted_mode); adjusted_mode);
...@@ -2527,7 +2531,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) ...@@ -2527,7 +2531,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
} }
static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
.mode_fixup = intel_dp_mode_fixup,
.mode_set = intel_dp_mode_set, .mode_set = intel_dp_mode_set,
}; };
...@@ -2947,6 +2950,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) ...@@ -2947,6 +2950,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
DRM_MODE_ENCODER_TMDS); DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs); drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
intel_encoder->compute_config = intel_dp_compute_config;
intel_encoder->enable = intel_enable_dp; intel_encoder->enable = intel_enable_dp;
intel_encoder->pre_enable = intel_pre_enable_dp; intel_encoder->pre_enable = intel_pre_enable_dp;
intel_encoder->disable = intel_disable_dp; intel_encoder->disable = intel_disable_dp;
......
...@@ -190,6 +190,9 @@ struct intel_crtc_config { ...@@ -190,6 +190,9 @@ struct intel_crtc_config {
* changes the crtc timings in the mode to prevent the crtc fixup from * changes the crtc timings in the mode to prevent the crtc fixup from
* overwriting them. Currently only lvds needs that. */ * overwriting them. Currently only lvds needs that. */
bool timings_set; bool timings_set;
/* Whether to set up the PCH/FDI. Note that we never allow sharing
* between pch encoders and cpu encoders. */
bool has_pch_encoder;
/* Used by SDVO (and if we ever fix it, HDMI). */ /* Used by SDVO (and if we ever fix it, HDMI). */
unsigned pixel_multiplier; unsigned pixel_multiplier;
}; };
...@@ -449,9 +452,8 @@ extern void intel_hdmi_init(struct drm_device *dev, ...@@ -449,9 +452,8 @@ extern void intel_hdmi_init(struct drm_device *dev,
extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector); struct intel_connector *intel_connector);
extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder); extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
extern bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, extern bool intel_hdmi_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *mode, struct intel_crtc_config *pipe_config);
struct drm_display_mode *adjusted_mode);
extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
bool is_sdvob); bool is_sdvob);
...@@ -475,9 +477,8 @@ extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); ...@@ -475,9 +477,8 @@ extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
extern void intel_dp_check_link_status(struct intel_dp *intel_dp); extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
extern bool intel_dp_mode_fixup(struct drm_encoder *encoder, extern bool intel_dp_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *mode, struct intel_crtc_config *pipe_config);
struct drm_display_mode *adjusted_mode);
extern bool intel_dpd_is_edp(struct drm_device *dev); extern bool intel_dpd_is_edp(struct drm_device *dev);
extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp); extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp); extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
......
...@@ -768,11 +768,12 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector, ...@@ -768,11 +768,12 @@ static int intel_hdmi_mode_valid(struct drm_connector *connector,
return MODE_OK; return MODE_OK;
} }
bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, bool intel_hdmi_compute_config(struct intel_encoder *encoder,
const struct drm_display_mode *mode, struct intel_crtc_config *pipe_config)
struct drm_display_mode *adjusted_mode)
{ {
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
if (intel_hdmi->color_range_auto) { if (intel_hdmi->color_range_auto) {
/* See CEA-861-E - 5.1 Default Encoding Parameters */ /* See CEA-861-E - 5.1 Default Encoding Parameters */
...@@ -786,6 +787,9 @@ bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, ...@@ -786,6 +787,9 @@ bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
if (intel_hdmi->color_range) if (intel_hdmi->color_range)
adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE; adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev))
pipe_config->has_pch_encoder = true;
return true; return true;
} }
...@@ -937,7 +941,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector) ...@@ -937,7 +941,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
} }
static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
.mode_fixup = intel_hdmi_mode_fixup,
.mode_set = intel_hdmi_mode_set, .mode_set = intel_hdmi_mode_set,
}; };
...@@ -1066,6 +1069,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) ...@@ -1066,6 +1069,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
DRM_MODE_ENCODER_TMDS); DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
intel_encoder->compute_config = intel_hdmi_compute_config;
intel_encoder->enable = intel_enable_hdmi; intel_encoder->enable = intel_enable_hdmi;
intel_encoder->disable = intel_disable_hdmi; intel_encoder->disable = intel_disable_hdmi;
intel_encoder->get_hw_state = intel_hdmi_get_hw_state; intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
......
...@@ -331,6 +331,8 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, ...@@ -331,6 +331,8 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
adjusted_mode); adjusted_mode);
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
pipe_config->has_pch_encoder = true;
intel_pch_panel_fitting(dev, intel_pch_panel_fitting(dev,
intel_connector->panel.fitting_mode, intel_connector->panel.fitting_mode,
mode, adjusted_mode); mode, adjusted_mode);
......
...@@ -1047,6 +1047,9 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, ...@@ -1047,6 +1047,9 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
struct drm_display_mode *mode = &pipe_config->requested_mode; struct drm_display_mode *mode = &pipe_config->requested_mode;
if (HAS_PCH_SPLIT(encoder->base.dev))
pipe_config->has_pch_encoder = true;
/* We need to construct preferred input timings based on our /* We need to construct preferred input timings based on our
* output timings. To do that, we have to set the output * output timings. To do that, we have to set the output
* timings, even though this isn't really the right place in * timings, even though this isn't really the right place in
......
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