drm/i915: Track has_audio in the pipe config
Including state readout and cross-checking. This allows us to get rid of crtc->eld_vld on hsw+. It also means that fastboot will be unhappy if the BIOS hasn't set up the audio routing like we want it too. Wrt fastboot and external screens I see a few options: - Don't. - Try to fix up eld, infoframes and audio settings after the fact. But that means some pretty extensive reworking of our code which currently does all this while the pipe/port is still off. I won't bother with converting SDVO over to this because the audio support for SDVO is very lacking: - We don't update the eld. - We don't update the audio state on the sdvo encoder. - We don't check whether the platform can even feed audio to the sdvo encoder. I've converted hdmi, dp & ddi all in one go since ddi needs both hdmi and dp converted and so doing it step-by-step would have required a few intermediate hacks. Reviewed-by: Naresh Kumar Kachhi <naresh.kumar.kachhi@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Родитель
acfa75b02e
Коммит
9ed109a7b4
|
@ -375,7 +375,15 @@ static void intel_ddi_mode_set(struct intel_encoder *encoder)
|
|||
DRM_DEBUG_KMS("Preparing DDI mode on port %c, pipe %c\n",
|
||||
port_name(port), pipe_name(pipe));
|
||||
|
||||
crtc->eld_vld = false;
|
||||
if (crtc->config.has_audio) {
|
||||
DRM_DEBUG_DRIVER("Audio on pipe %c on DDI\n",
|
||||
pipe_name(crtc->pipe));
|
||||
|
||||
/* write eld */
|
||||
DRM_DEBUG_DRIVER("DDI audio: write eld information\n");
|
||||
intel_write_eld(&encoder->base, adjusted_mode);
|
||||
}
|
||||
|
||||
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
|
||||
struct intel_digital_port *intel_dig_port =
|
||||
|
@ -384,31 +392,9 @@ static void intel_ddi_mode_set(struct intel_encoder *encoder)
|
|||
intel_dp->DP = intel_dig_port->saved_port_bits |
|
||||
DDI_BUF_CTL_ENABLE | DDI_BUF_EMP_400MV_0DB_HSW;
|
||||
intel_dp->DP |= DDI_PORT_WIDTH(intel_dp->lane_count);
|
||||
|
||||
if (intel_dp->has_audio) {
|
||||
DRM_DEBUG_DRIVER("DP audio on pipe %c on DDI\n",
|
||||
pipe_name(crtc->pipe));
|
||||
|
||||
/* write eld */
|
||||
DRM_DEBUG_DRIVER("DP audio: write eld information\n");
|
||||
intel_write_eld(&encoder->base, adjusted_mode);
|
||||
}
|
||||
} else if (type == INTEL_OUTPUT_HDMI) {
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
|
||||
|
||||
if (intel_hdmi->has_audio) {
|
||||
/* Proper support for digital audio needs a new logic
|
||||
* and a new set of registers, so we leave it for future
|
||||
* patch bombing.
|
||||
*/
|
||||
DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
|
||||
pipe_name(crtc->pipe));
|
||||
|
||||
/* write eld */
|
||||
DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
|
||||
intel_write_eld(&encoder->base, adjusted_mode);
|
||||
}
|
||||
|
||||
intel_hdmi->set_infoframes(&encoder->base,
|
||||
crtc->config.has_hdmi_sink,
|
||||
adjusted_mode);
|
||||
|
@ -1385,7 +1371,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
|
|||
intel_edp_psr_enable(intel_dp);
|
||||
}
|
||||
|
||||
if (intel_crtc->eld_vld && type != INTEL_OUTPUT_EDP) {
|
||||
if (intel_crtc->config.has_audio) {
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4));
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
|
@ -1591,6 +1577,10 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
|||
break;
|
||||
}
|
||||
|
||||
temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
if (temp & (AUDIO_OUTPUT_ENABLE_A << (intel_crtc->pipe * 4)))
|
||||
pipe_config->has_audio = true;
|
||||
|
||||
if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp &&
|
||||
pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
|
||||
/*
|
||||
|
|
|
@ -4690,13 +4690,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
|
|||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_connector *connector;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
/* crtc should still be enabled when we disable it. */
|
||||
WARN_ON(!crtc->enabled);
|
||||
|
||||
dev_priv->display.crtc_disable(crtc);
|
||||
intel_crtc->eld_vld = false;
|
||||
intel_crtc_update_sarea(crtc, false);
|
||||
dev_priv->display.off(crtc);
|
||||
|
||||
|
@ -7619,7 +7617,6 @@ static void haswell_write_eld(struct drm_connector *connector,
|
|||
{
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
uint8_t *eld = connector->eld;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
uint32_t eldv;
|
||||
uint32_t i;
|
||||
int len;
|
||||
|
@ -7658,7 +7655,6 @@ static void haswell_write_eld(struct drm_connector *connector,
|
|||
DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe));
|
||||
|
||||
eldv = AUDIO_ELD_VALID_A << (pipe * 4);
|
||||
intel_crtc->eld_vld = true;
|
||||
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
|
||||
DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
|
||||
|
@ -9894,6 +9890,8 @@ intel_pipe_config_compare(struct drm_device *dev,
|
|||
IS_VALLEYVIEW(dev))
|
||||
PIPE_CONF_CHECK_I(limited_color_range);
|
||||
|
||||
PIPE_CONF_CHECK_I(has_audio);
|
||||
|
||||
PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
|
||||
DRM_MODE_FLAG_INTERLACE);
|
||||
|
||||
|
|
|
@ -800,6 +800,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
|||
pipe_config->has_pch_encoder = true;
|
||||
|
||||
pipe_config->has_dp_encoder = true;
|
||||
pipe_config->has_audio = intel_dp->has_audio;
|
||||
|
||||
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
|
||||
intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
|
||||
|
@ -959,7 +960,7 @@ static void intel_dp_mode_set(struct intel_encoder *encoder)
|
|||
intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
|
||||
intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count);
|
||||
|
||||
if (intel_dp->has_audio) {
|
||||
if (crtc->config.has_audio) {
|
||||
DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
|
||||
|
@ -1506,8 +1507,11 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
|
|||
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
|
||||
int dotclock;
|
||||
|
||||
tmp = I915_READ(intel_dp->output_reg);
|
||||
if (tmp & DP_AUDIO_OUTPUT_ENABLE)
|
||||
pipe_config->has_audio = true;
|
||||
|
||||
if ((port == PORT_A) || !HAS_PCH_CPT(dev)) {
|
||||
tmp = I915_READ(intel_dp->output_reg);
|
||||
if (tmp & DP_SYNC_HS_HIGH)
|
||||
flags |= DRM_MODE_FLAG_PHSYNC;
|
||||
else
|
||||
|
|
|
@ -276,6 +276,10 @@ struct intel_crtc_config {
|
|||
/* Whether we should send NULL infoframes. Required for audio. */
|
||||
bool has_hdmi_sink;
|
||||
|
||||
/* Audio enabled on this pipe. Only valid if either has_hdmi_sink or
|
||||
* has_dp_encoder is set. */
|
||||
bool has_audio;
|
||||
|
||||
/*
|
||||
* Enable dithering, used when the selected pipe bpp doesn't match the
|
||||
* plane bpp.
|
||||
|
@ -366,7 +370,6 @@ struct intel_crtc {
|
|||
*/
|
||||
bool active;
|
||||
unsigned long enabled_power_domains;
|
||||
bool eld_vld;
|
||||
bool primary_enabled; /* is the primary plane (partially) visible? */
|
||||
bool lowfreq_avail;
|
||||
struct intel_overlay *overlay;
|
||||
|
|
|
@ -658,7 +658,7 @@ static void intel_hdmi_mode_set(struct intel_encoder *encoder)
|
|||
if (crtc->config.has_hdmi_sink)
|
||||
hdmi_val |= HDMI_MODE_SELECT_HDMI;
|
||||
|
||||
if (intel_hdmi->has_audio) {
|
||||
if (crtc->config.has_audio) {
|
||||
WARN_ON(!crtc->config.has_hdmi_sink);
|
||||
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
|
||||
pipe_name(crtc->pipe));
|
||||
|
@ -726,6 +726,9 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
|||
if (tmp & HDMI_MODE_SELECT_HDMI)
|
||||
pipe_config->has_hdmi_sink = true;
|
||||
|
||||
if (tmp & HDMI_MODE_SELECT_HDMI)
|
||||
pipe_config->has_audio = true;
|
||||
|
||||
pipe_config->adjusted_mode.flags |= flags;
|
||||
|
||||
if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc)
|
||||
|
@ -748,7 +751,7 @@ static void intel_enable_hdmi(struct intel_encoder *encoder)
|
|||
u32 temp;
|
||||
u32 enable_bits = SDVO_ENABLE;
|
||||
|
||||
if (intel_hdmi->has_audio)
|
||||
if (intel_crtc->config.has_audio)
|
||||
enable_bits |= SDVO_AUDIO_ENABLE;
|
||||
|
||||
temp = I915_READ(intel_hdmi->hdmi_reg);
|
||||
|
@ -919,6 +922,9 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
|
|||
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev))
|
||||
pipe_config->has_pch_encoder = true;
|
||||
|
||||
if (pipe_config->has_hdmi_sink && intel_hdmi->has_audio)
|
||||
pipe_config->has_audio = true;
|
||||
|
||||
/*
|
||||
* HDMI is either 12 or 8, so if the display lets 10bpc sneak
|
||||
* through, clamp it down. Note that g4x/vlv don't support 12bpc hdmi
|
||||
|
|
Загрузка…
Ссылка в новой задаче