Commit 045ac3b5 authored by Jesse Barnes's avatar Jesse Barnes Committed by Daniel Vetter

drm/i915: add encoder get_config function v5

We can use this for fetching encoder specific pipe_config state, like
mode flags, adjusted clock, etc.

Just used for mode flags atm, so we can check the pipe config state at
mode set time.

v2: get_config when checking hw state too
v3: fix DVO and LVDS mode flags (Ville)
    get SDVO DTD for flag fetch (Ville)
v4: use input timings (Ville)
    correct command used (Ville)
    remove gen4 check (Ville)
v5: get DDI flag config too
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> (v4)
Tested-by: Paulo Zanoni <przanoni@gmail.com> (the new hsw ddi stuff)
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent e1b73cba
...@@ -84,6 +84,28 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, ...@@ -84,6 +84,28 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
static void intel_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crt *crt = intel_encoder_to_crt(encoder);
u32 tmp, flags = 0;
tmp = I915_READ(crt->adpa_reg);
if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (tmp & ADPA_VSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
}
/* Note: The caller is required to filter out dpms modes not supported by the /* Note: The caller is required to filter out dpms modes not supported by the
* platform. */ * platform. */
static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
...@@ -778,6 +800,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -778,6 +800,7 @@ void intel_crt_init(struct drm_device *dev)
crt->base.compute_config = intel_crt_compute_config; 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;
crt->base.get_config = intel_crt_get_config;
if (I915_HAS_HOTPLUG(dev)) if (I915_HAS_HOTPLUG(dev))
crt->base.hpd_pin = HPD_CRT; crt->base.hpd_pin = HPD_CRT;
if (HAS_DDI(dev)) if (HAS_DDI(dev))
......
...@@ -1259,6 +1259,28 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) ...@@ -1259,6 +1259,28 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
intel_dp_check_link_status(intel_dp); intel_dp_check_link_status(intel_dp);
} }
static void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
u32 temp, flags = 0;
temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
if (temp & TRANS_DDI_PHSYNC)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (temp & TRANS_DDI_PVSYNC)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
pipe_config->pixel_multiplier = 1;
}
static void intel_ddi_destroy(struct drm_encoder *encoder) static void intel_ddi_destroy(struct drm_encoder *encoder)
{ {
/* HDMI has nothing special to destroy, so we can go with this. */ /* HDMI has nothing special to destroy, so we can go with this. */
...@@ -1318,6 +1340,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) ...@@ -1318,6 +1340,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_encoder->disable = intel_disable_ddi; intel_encoder->disable = intel_disable_ddi;
intel_encoder->post_disable = intel_ddi_post_disable; intel_encoder->post_disable = intel_ddi_post_disable;
intel_encoder->get_hw_state = intel_ddi_get_hw_state; intel_encoder->get_hw_state = intel_ddi_get_hw_state;
intel_encoder->get_config = intel_ddi_get_config;
intel_dig_port->port = port; intel_dig_port->port = port;
intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) & intel_dig_port->port_reversal = I915_READ(DDI_BUF_CTL(port)) &
......
...@@ -8067,6 +8067,15 @@ intel_pipe_config_compare(struct drm_device *dev, ...@@ -8067,6 +8067,15 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
DRM_MODE_FLAG_INTERLACE); DRM_MODE_FLAG_INTERLACE);
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
DRM_MODE_FLAG_PHSYNC);
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
DRM_MODE_FLAG_NHSYNC);
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
DRM_MODE_FLAG_PVSYNC);
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
DRM_MODE_FLAG_NVSYNC);
PIPE_CONF_CHECK_I(requested_mode.hdisplay); PIPE_CONF_CHECK_I(requested_mode.hdisplay);
PIPE_CONF_CHECK_I(requested_mode.vdisplay); PIPE_CONF_CHECK_I(requested_mode.vdisplay);
...@@ -8159,6 +8168,8 @@ intel_modeset_check_state(struct drm_device *dev) ...@@ -8159,6 +8168,8 @@ intel_modeset_check_state(struct drm_device *dev)
bool enabled = false; bool enabled = false;
bool active = false; bool active = false;
memset(&pipe_config, 0, sizeof(pipe_config));
DRM_DEBUG_KMS("[CRTC:%d]\n", DRM_DEBUG_KMS("[CRTC:%d]\n",
crtc->base.base.id); crtc->base.base.id);
...@@ -8172,6 +8183,8 @@ intel_modeset_check_state(struct drm_device *dev) ...@@ -8172,6 +8183,8 @@ intel_modeset_check_state(struct drm_device *dev)
enabled = true; enabled = true;
if (encoder->connectors_active) if (encoder->connectors_active)
active = true; active = true;
if (encoder->get_config)
encoder->get_config(encoder, &pipe_config);
} }
WARN(active != crtc->active, WARN(active != crtc->active,
"crtc's computed active state doesn't match tracked active state " "crtc's computed active state doesn't match tracked active state "
...@@ -8180,7 +8193,6 @@ intel_modeset_check_state(struct drm_device *dev) ...@@ -8180,7 +8193,6 @@ intel_modeset_check_state(struct drm_device *dev)
"crtc's computed enabled state doesn't match tracked enabled state " "crtc's computed enabled state doesn't match tracked enabled state "
"(expected %i, found %i)\n", enabled, crtc->base.enabled); "(expected %i, found %i)\n", enabled, crtc->base.enabled);
memset(&pipe_config, 0, sizeof(pipe_config));
pipe_config.cpu_transcoder = crtc->config.cpu_transcoder; pipe_config.cpu_transcoder = crtc->config.cpu_transcoder;
active = dev_priv->display.get_pipe_config(crtc, active = dev_priv->display.get_pipe_config(crtc,
&pipe_config); &pipe_config);
...@@ -9589,8 +9601,10 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, ...@@ -9589,8 +9601,10 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
pipe = 0; pipe = 0;
if (encoder->get_hw_state(encoder, &pipe)) { if (encoder->get_hw_state(encoder, &pipe)) {
encoder->base.crtc = crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
dev_priv->pipe_to_crtc_mapping[pipe]; encoder->base.crtc = &crtc->base;
if (encoder->get_config)
encoder->get_config(encoder, &crtc->config);
} else { } else {
encoder->base.crtc = NULL; encoder->base.crtc = NULL;
} }
......
...@@ -1346,6 +1346,28 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, ...@@ -1346,6 +1346,28 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
static void intel_dp_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
u32 tmp, flags = 0;
tmp = I915_READ(intel_dp->output_reg);
if (tmp & DP_SYNC_HS_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (tmp & DP_SYNC_VS_HIGH)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
}
static void intel_disable_dp(struct intel_encoder *encoder) static void intel_disable_dp(struct intel_encoder *encoder)
{ {
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
...@@ -3184,6 +3206,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) ...@@ -3184,6 +3206,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->disable = intel_disable_dp; intel_encoder->disable = intel_disable_dp;
intel_encoder->post_disable = intel_post_disable_dp; intel_encoder->post_disable = intel_post_disable_dp;
intel_encoder->get_hw_state = intel_dp_get_hw_state; intel_encoder->get_hw_state = intel_dp_get_hw_state;
intel_encoder->get_config = intel_dp_get_config;
if (IS_VALLEYVIEW(dev)) if (IS_VALLEYVIEW(dev))
intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable; intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable;
......
...@@ -139,6 +139,10 @@ struct intel_encoder { ...@@ -139,6 +139,10 @@ struct intel_encoder {
* the encoder is active. If the encoder is enabled it also set the pipe * the encoder is active. If the encoder is enabled it also set the pipe
* it is connected to in the pipe parameter. */ * it is connected to in the pipe parameter. */
bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe); bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
/* Reconstructs the equivalent mode flags for the current hardware
* state. */
void (*get_config)(struct intel_encoder *,
struct intel_crtc_config *pipe_config);
int crtc_mask; int crtc_mask;
enum hpd_pin hpd_pin; enum hpd_pin hpd_pin;
}; };
......
...@@ -136,6 +136,26 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder, ...@@ -136,6 +136,26 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
static void intel_dvo_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
u32 tmp, flags = 0;
tmp = I915_READ(intel_dvo->dev.dvo_reg);
if (tmp & DVO_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (tmp & DVO_VSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
}
static void intel_disable_dvo(struct intel_encoder *encoder) static void intel_disable_dvo(struct intel_encoder *encoder)
{ {
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
...@@ -447,6 +467,7 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -447,6 +467,7 @@ void intel_dvo_init(struct drm_device *dev)
intel_encoder->disable = intel_disable_dvo; intel_encoder->disable = intel_disable_dvo;
intel_encoder->enable = intel_enable_dvo; intel_encoder->enable = intel_enable_dvo;
intel_encoder->get_hw_state = intel_dvo_get_hw_state; intel_encoder->get_hw_state = intel_dvo_get_hw_state;
intel_encoder->get_config = intel_dvo_get_config;
intel_connector->get_hw_state = intel_dvo_connector_get_hw_state; intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
/* Now, try to find a controller */ /* Now, try to find a controller */
......
...@@ -658,6 +658,28 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, ...@@ -658,6 +658,28 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
static void intel_hdmi_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
u32 tmp, flags = 0;
tmp = I915_READ(intel_hdmi->hdmi_reg);
if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (tmp & SDVO_VSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
}
static void intel_enable_hdmi(struct intel_encoder *encoder) static void intel_enable_hdmi(struct intel_encoder *encoder)
{ {
struct drm_device *dev = encoder->base.dev; struct drm_device *dev = encoder->base.dev;
...@@ -1216,6 +1238,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) ...@@ -1216,6 +1238,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
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;
intel_encoder->get_config = intel_hdmi_get_config;
if (IS_VALLEYVIEW(dev)) { if (IS_VALLEYVIEW(dev)) {
intel_encoder->pre_enable = intel_hdmi_pre_enable; intel_encoder->pre_enable = intel_hdmi_pre_enable;
intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable; intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable;
......
...@@ -86,6 +86,31 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, ...@@ -86,6 +86,31 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
static void intel_lvds_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 lvds_reg, tmp, flags = 0;
if (HAS_PCH_SPLIT(dev))
lvds_reg = PCH_LVDS;
else
lvds_reg = LVDS;
tmp = I915_READ(lvds_reg);
if (tmp & LVDS_HSYNC_POLARITY)
flags |= DRM_MODE_FLAG_NHSYNC;
else
flags |= DRM_MODE_FLAG_PHSYNC;
if (tmp & LVDS_VSYNC_POLARITY)
flags |= DRM_MODE_FLAG_NVSYNC;
else
flags |= DRM_MODE_FLAG_PVSYNC;
pipe_config->adjusted_mode.flags |= flags;
}
/* The LVDS pin pair needs to be on before the DPLLs are enabled. /* The LVDS pin pair needs to be on before the DPLLs are enabled.
* This is an exception to the general rule that mode_set doesn't turn * This is an exception to the general rule that mode_set doesn't turn
* things on. * things on.
...@@ -921,6 +946,7 @@ bool intel_lvds_init(struct drm_device *dev) ...@@ -921,6 +946,7 @@ bool intel_lvds_init(struct drm_device *dev)
intel_encoder->compute_config = intel_lvds_compute_config; intel_encoder->compute_config = intel_lvds_compute_config;
intel_encoder->disable = intel_disable_lvds; intel_encoder->disable = intel_disable_lvds;
intel_encoder->get_hw_state = intel_lvds_get_hw_state; intel_encoder->get_hw_state = intel_lvds_get_hw_state;
intel_encoder->get_config = intel_lvds_get_config;
intel_connector->get_hw_state = intel_connector_get_hw_state; intel_connector->get_hw_state = intel_connector_get_hw_state;
intel_connector_attach_encoder(intel_connector, intel_encoder); intel_connector_attach_encoder(intel_connector, intel_encoder);
......
...@@ -712,6 +712,13 @@ static bool intel_sdvo_set_timing(struct intel_sdvo *intel_sdvo, u8 cmd, ...@@ -712,6 +712,13 @@ static bool intel_sdvo_set_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
intel_sdvo_set_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2)); intel_sdvo_set_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
} }
static bool intel_sdvo_get_timing(struct intel_sdvo *intel_sdvo, u8 cmd,
struct intel_sdvo_dtd *dtd)
{
return intel_sdvo_get_value(intel_sdvo, cmd, &dtd->part1, sizeof(dtd->part1)) &&
intel_sdvo_get_value(intel_sdvo, cmd + 1, &dtd->part2, sizeof(dtd->part2));
}
static bool intel_sdvo_set_input_timing(struct intel_sdvo *intel_sdvo, static bool intel_sdvo_set_input_timing(struct intel_sdvo *intel_sdvo,
struct intel_sdvo_dtd *dtd) struct intel_sdvo_dtd *dtd)
{ {
...@@ -726,6 +733,13 @@ static bool intel_sdvo_set_output_timing(struct intel_sdvo *intel_sdvo, ...@@ -726,6 +733,13 @@ static bool intel_sdvo_set_output_timing(struct intel_sdvo *intel_sdvo,
SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
} }
static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo,
struct intel_sdvo_dtd *dtd)
{
return intel_sdvo_get_timing(intel_sdvo,
SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
}
static bool static bool
intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
uint16_t clock, uint16_t clock,
...@@ -1295,6 +1309,33 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder, ...@@ -1295,6 +1309,33 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
return true; return true;
} }
static void intel_sdvo_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
struct intel_sdvo_dtd dtd;
u32 flags = 0;
bool ret;
ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd);
if (!ret) {
DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n");
return;
}
if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
}
static void intel_disable_sdvo(struct intel_encoder *encoder) static void intel_disable_sdvo(struct intel_encoder *encoder)
{ {
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
...@@ -2827,6 +2868,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) ...@@ -2827,6 +2868,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
intel_encoder->mode_set = intel_sdvo_mode_set; intel_encoder->mode_set = intel_sdvo_mode_set;
intel_encoder->enable = intel_enable_sdvo; intel_encoder->enable = intel_enable_sdvo;
intel_encoder->get_hw_state = intel_sdvo_get_hw_state; intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
intel_encoder->get_config = intel_sdvo_get_config;
/* In default case sdvo lvds is false */ /* In default case sdvo lvds is false */
if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
......
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