xref: /openbsd-src/sys/dev/pci/drm/i915/display/g4x_hdmi.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
15ca02815Sjsg // SPDX-License-Identifier: MIT
25ca02815Sjsg /*
35ca02815Sjsg  * Copyright © 2020 Intel Corporation
45ca02815Sjsg  *
55ca02815Sjsg  * HDMI support for G4x,ILK,SNB,IVB,VLV,CHV (HSW+ handled by the DDI code).
65ca02815Sjsg  */
75ca02815Sjsg 
85ca02815Sjsg #include "g4x_hdmi.h"
9*f005ef32Sjsg #include "i915_reg.h"
10*f005ef32Sjsg #include "intel_atomic.h"
115ca02815Sjsg #include "intel_audio.h"
125ca02815Sjsg #include "intel_connector.h"
131bb76ff1Sjsg #include "intel_crtc.h"
145ca02815Sjsg #include "intel_de.h"
151bb76ff1Sjsg #include "intel_display_power.h"
165ca02815Sjsg #include "intel_display_types.h"
17*f005ef32Sjsg #include "intel_dp_aux.h"
185ca02815Sjsg #include "intel_dpio_phy.h"
195ca02815Sjsg #include "intel_fifo_underrun.h"
205ca02815Sjsg #include "intel_hdmi.h"
215ca02815Sjsg #include "intel_hotplug.h"
225ca02815Sjsg #include "intel_sdvo.h"
231bb76ff1Sjsg #include "vlv_sideband.h"
245ca02815Sjsg 
intel_hdmi_prepare(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)255ca02815Sjsg static void intel_hdmi_prepare(struct intel_encoder *encoder,
265ca02815Sjsg 			       const struct intel_crtc_state *crtc_state)
275ca02815Sjsg {
285ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
295ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
305ca02815Sjsg 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
315ca02815Sjsg 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
325ca02815Sjsg 	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
335ca02815Sjsg 	u32 hdmi_val;
345ca02815Sjsg 
355ca02815Sjsg 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
365ca02815Sjsg 
375ca02815Sjsg 	hdmi_val = SDVO_ENCODING_HDMI;
385ca02815Sjsg 	if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range)
395ca02815Sjsg 		hdmi_val |= HDMI_COLOR_RANGE_16_235;
405ca02815Sjsg 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
415ca02815Sjsg 		hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
425ca02815Sjsg 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
435ca02815Sjsg 		hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH;
445ca02815Sjsg 
455ca02815Sjsg 	if (crtc_state->pipe_bpp > 24)
465ca02815Sjsg 		hdmi_val |= HDMI_COLOR_FORMAT_12bpc;
475ca02815Sjsg 	else
485ca02815Sjsg 		hdmi_val |= SDVO_COLOR_FORMAT_8bpc;
495ca02815Sjsg 
505ca02815Sjsg 	if (crtc_state->has_hdmi_sink)
515ca02815Sjsg 		hdmi_val |= HDMI_MODE_SELECT_HDMI;
525ca02815Sjsg 
535ca02815Sjsg 	if (HAS_PCH_CPT(dev_priv))
545ca02815Sjsg 		hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
555ca02815Sjsg 	else if (IS_CHERRYVIEW(dev_priv))
565ca02815Sjsg 		hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe);
575ca02815Sjsg 	else
585ca02815Sjsg 		hdmi_val |= SDVO_PIPE_SEL(crtc->pipe);
595ca02815Sjsg 
605ca02815Sjsg 	intel_de_write(dev_priv, intel_hdmi->hdmi_reg, hdmi_val);
615ca02815Sjsg 	intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
625ca02815Sjsg }
635ca02815Sjsg 
intel_hdmi_get_hw_state(struct intel_encoder * encoder,enum pipe * pipe)645ca02815Sjsg static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
655ca02815Sjsg 				    enum pipe *pipe)
665ca02815Sjsg {
675ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
685ca02815Sjsg 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
695ca02815Sjsg 	intel_wakeref_t wakeref;
705ca02815Sjsg 	bool ret;
715ca02815Sjsg 
725ca02815Sjsg 	wakeref = intel_display_power_get_if_enabled(dev_priv,
735ca02815Sjsg 						     encoder->power_domain);
745ca02815Sjsg 	if (!wakeref)
755ca02815Sjsg 		return false;
765ca02815Sjsg 
775ca02815Sjsg 	ret = intel_sdvo_port_enabled(dev_priv, intel_hdmi->hdmi_reg, pipe);
785ca02815Sjsg 
795ca02815Sjsg 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
805ca02815Sjsg 
815ca02815Sjsg 	return ret;
825ca02815Sjsg }
835ca02815Sjsg 
connector_is_hdmi(struct drm_connector * connector)84*f005ef32Sjsg static bool connector_is_hdmi(struct drm_connector *connector)
85*f005ef32Sjsg {
86*f005ef32Sjsg 	struct intel_encoder *encoder =
87*f005ef32Sjsg 		intel_attached_encoder(to_intel_connector(connector));
88*f005ef32Sjsg 
89*f005ef32Sjsg 	return encoder && encoder->type == INTEL_OUTPUT_HDMI;
90*f005ef32Sjsg }
91*f005ef32Sjsg 
g4x_compute_has_hdmi_sink(struct intel_atomic_state * state,struct intel_crtc * this_crtc)92*f005ef32Sjsg static bool g4x_compute_has_hdmi_sink(struct intel_atomic_state *state,
93*f005ef32Sjsg 				      struct intel_crtc *this_crtc)
94*f005ef32Sjsg {
95*f005ef32Sjsg 	const struct drm_connector_state *conn_state;
96*f005ef32Sjsg 	struct drm_connector *connector;
97*f005ef32Sjsg 	int i;
98*f005ef32Sjsg 
99*f005ef32Sjsg 	/*
100*f005ef32Sjsg 	 * On g4x only one HDMI port can transmit infoframes/audio at
101*f005ef32Sjsg 	 * any given time. Select the first suitable port for this duty.
102*f005ef32Sjsg 	 *
103*f005ef32Sjsg 	 * See also g4x_hdmi_connector_atomic_check().
104*f005ef32Sjsg 	 */
105*f005ef32Sjsg 	for_each_new_connector_in_state(&state->base, connector, conn_state, i) {
106*f005ef32Sjsg 		struct intel_encoder *encoder = to_intel_encoder(conn_state->best_encoder);
107*f005ef32Sjsg 		const struct intel_crtc_state *crtc_state;
108*f005ef32Sjsg 		struct intel_crtc *crtc;
109*f005ef32Sjsg 
110*f005ef32Sjsg 		if (!connector_is_hdmi(connector))
111*f005ef32Sjsg 			continue;
112*f005ef32Sjsg 
113*f005ef32Sjsg 		crtc = to_intel_crtc(conn_state->crtc);
114*f005ef32Sjsg 		if (!crtc)
115*f005ef32Sjsg 			continue;
116*f005ef32Sjsg 
117*f005ef32Sjsg 		crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
118*f005ef32Sjsg 
119*f005ef32Sjsg 		if (!intel_hdmi_compute_has_hdmi_sink(encoder, crtc_state, conn_state))
120*f005ef32Sjsg 			continue;
121*f005ef32Sjsg 
122*f005ef32Sjsg 		return crtc == this_crtc;
123*f005ef32Sjsg 	}
124*f005ef32Sjsg 
125*f005ef32Sjsg 	return false;
126*f005ef32Sjsg }
127*f005ef32Sjsg 
g4x_hdmi_compute_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state,struct drm_connector_state * conn_state)128*f005ef32Sjsg static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
129*f005ef32Sjsg 				   struct intel_crtc_state *crtc_state,
130*f005ef32Sjsg 				   struct drm_connector_state *conn_state)
131*f005ef32Sjsg {
132*f005ef32Sjsg 	struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
133*f005ef32Sjsg 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
134*f005ef32Sjsg 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
135*f005ef32Sjsg 
136*f005ef32Sjsg 	if (HAS_PCH_SPLIT(i915))
137*f005ef32Sjsg 		crtc_state->has_pch_encoder = true;
138*f005ef32Sjsg 
139*f005ef32Sjsg 	if (IS_G4X(i915))
140*f005ef32Sjsg 		crtc_state->has_hdmi_sink = g4x_compute_has_hdmi_sink(state, crtc);
141*f005ef32Sjsg 	else
142*f005ef32Sjsg 		crtc_state->has_hdmi_sink =
143*f005ef32Sjsg 			intel_hdmi_compute_has_hdmi_sink(encoder, crtc_state, conn_state);
144*f005ef32Sjsg 
145*f005ef32Sjsg 	return intel_hdmi_compute_config(encoder, crtc_state, conn_state);
146*f005ef32Sjsg }
147*f005ef32Sjsg 
intel_hdmi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config)1485ca02815Sjsg static void intel_hdmi_get_config(struct intel_encoder *encoder,
1495ca02815Sjsg 				  struct intel_crtc_state *pipe_config)
1505ca02815Sjsg {
1515ca02815Sjsg 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
1525ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
1535ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
1545ca02815Sjsg 	u32 tmp, flags = 0;
1555ca02815Sjsg 	int dotclock;
1565ca02815Sjsg 
1575ca02815Sjsg 	pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
1585ca02815Sjsg 
1595ca02815Sjsg 	tmp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
1605ca02815Sjsg 
1615ca02815Sjsg 	if (tmp & SDVO_HSYNC_ACTIVE_HIGH)
1625ca02815Sjsg 		flags |= DRM_MODE_FLAG_PHSYNC;
1635ca02815Sjsg 	else
1645ca02815Sjsg 		flags |= DRM_MODE_FLAG_NHSYNC;
1655ca02815Sjsg 
1665ca02815Sjsg 	if (tmp & SDVO_VSYNC_ACTIVE_HIGH)
1675ca02815Sjsg 		flags |= DRM_MODE_FLAG_PVSYNC;
1685ca02815Sjsg 	else
1695ca02815Sjsg 		flags |= DRM_MODE_FLAG_NVSYNC;
1705ca02815Sjsg 
1715ca02815Sjsg 	if (tmp & HDMI_MODE_SELECT_HDMI)
1725ca02815Sjsg 		pipe_config->has_hdmi_sink = true;
1735ca02815Sjsg 
1745ca02815Sjsg 	pipe_config->infoframes.enable |=
1755ca02815Sjsg 		intel_hdmi_infoframes_enabled(encoder, pipe_config);
1765ca02815Sjsg 
1775ca02815Sjsg 	if (pipe_config->infoframes.enable)
1785ca02815Sjsg 		pipe_config->has_infoframe = true;
1795ca02815Sjsg 
1805ca02815Sjsg 	if (tmp & HDMI_AUDIO_ENABLE)
1815ca02815Sjsg 		pipe_config->has_audio = true;
1825ca02815Sjsg 
1835ca02815Sjsg 	if (!HAS_PCH_SPLIT(dev_priv) &&
1845ca02815Sjsg 	    tmp & HDMI_COLOR_RANGE_16_235)
1855ca02815Sjsg 		pipe_config->limited_color_range = true;
1865ca02815Sjsg 
1875ca02815Sjsg 	pipe_config->hw.adjusted_mode.flags |= flags;
1885ca02815Sjsg 
1895ca02815Sjsg 	if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc)
1901bb76ff1Sjsg 		dotclock = DIV_ROUND_CLOSEST(pipe_config->port_clock * 2, 3);
1915ca02815Sjsg 	else
1925ca02815Sjsg 		dotclock = pipe_config->port_clock;
1935ca02815Sjsg 
1945ca02815Sjsg 	if (pipe_config->pixel_multiplier)
1955ca02815Sjsg 		dotclock /= pipe_config->pixel_multiplier;
1965ca02815Sjsg 
1975ca02815Sjsg 	pipe_config->hw.adjusted_mode.crtc_clock = dotclock;
1985ca02815Sjsg 
1995ca02815Sjsg 	pipe_config->lane_count = 4;
2005ca02815Sjsg 
2015ca02815Sjsg 	intel_hdmi_read_gcp_infoframe(encoder, pipe_config);
2025ca02815Sjsg 
2035ca02815Sjsg 	intel_read_infoframe(encoder, pipe_config,
2045ca02815Sjsg 			     HDMI_INFOFRAME_TYPE_AVI,
2055ca02815Sjsg 			     &pipe_config->infoframes.avi);
2065ca02815Sjsg 	intel_read_infoframe(encoder, pipe_config,
2075ca02815Sjsg 			     HDMI_INFOFRAME_TYPE_SPD,
2085ca02815Sjsg 			     &pipe_config->infoframes.spd);
2095ca02815Sjsg 	intel_read_infoframe(encoder, pipe_config,
2105ca02815Sjsg 			     HDMI_INFOFRAME_TYPE_VENDOR,
2115ca02815Sjsg 			     &pipe_config->infoframes.hdmi);
212*f005ef32Sjsg 
213*f005ef32Sjsg 	intel_audio_codec_get_config(encoder, pipe_config);
2145ca02815Sjsg }
2155ca02815Sjsg 
g4x_hdmi_enable_port(struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config)216*f005ef32Sjsg static void g4x_hdmi_enable_port(struct intel_encoder *encoder,
217*f005ef32Sjsg 				 const struct intel_crtc_state *pipe_config)
2185ca02815Sjsg {
2195ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
2205ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
2215ca02815Sjsg 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
2225ca02815Sjsg 	u32 temp;
2235ca02815Sjsg 
2245ca02815Sjsg 	temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
2255ca02815Sjsg 
2265ca02815Sjsg 	temp |= SDVO_ENABLE;
2275ca02815Sjsg 	if (pipe_config->has_audio)
2285ca02815Sjsg 		temp |= HDMI_AUDIO_ENABLE;
2295ca02815Sjsg 
2305ca02815Sjsg 	intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
2315ca02815Sjsg 	intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
232*f005ef32Sjsg }
233*f005ef32Sjsg 
g4x_enable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)234*f005ef32Sjsg static void g4x_enable_hdmi(struct intel_atomic_state *state,
235*f005ef32Sjsg 			    struct intel_encoder *encoder,
236*f005ef32Sjsg 			    const struct intel_crtc_state *pipe_config,
237*f005ef32Sjsg 			    const struct drm_connector_state *conn_state)
238*f005ef32Sjsg {
239*f005ef32Sjsg 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
240*f005ef32Sjsg 
241*f005ef32Sjsg 	g4x_hdmi_enable_port(encoder, pipe_config);
2425ca02815Sjsg 
2431bb76ff1Sjsg 	drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
2441bb76ff1Sjsg 		    !pipe_config->has_hdmi_sink);
2451bb76ff1Sjsg 	intel_audio_codec_enable(encoder, pipe_config, conn_state);
2465ca02815Sjsg }
2475ca02815Sjsg 
ibx_enable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)2485ca02815Sjsg static void ibx_enable_hdmi(struct intel_atomic_state *state,
2495ca02815Sjsg 			    struct intel_encoder *encoder,
2505ca02815Sjsg 			    const struct intel_crtc_state *pipe_config,
2515ca02815Sjsg 			    const struct drm_connector_state *conn_state)
2525ca02815Sjsg {
2535ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
2545ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
2555ca02815Sjsg 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
2565ca02815Sjsg 	u32 temp;
2575ca02815Sjsg 
2585ca02815Sjsg 	temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
2595ca02815Sjsg 
2605ca02815Sjsg 	temp |= SDVO_ENABLE;
2615ca02815Sjsg 	if (pipe_config->has_audio)
2625ca02815Sjsg 		temp |= HDMI_AUDIO_ENABLE;
2635ca02815Sjsg 
2645ca02815Sjsg 	/*
2655ca02815Sjsg 	 * HW workaround, need to write this twice for issue
2665ca02815Sjsg 	 * that may result in first write getting masked.
2675ca02815Sjsg 	 */
2685ca02815Sjsg 	intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
2695ca02815Sjsg 	intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
2705ca02815Sjsg 	intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
2715ca02815Sjsg 	intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
2725ca02815Sjsg 
2735ca02815Sjsg 	/*
2745ca02815Sjsg 	 * HW workaround, need to toggle enable bit off and on
2755ca02815Sjsg 	 * for 12bpc with pixel repeat.
2765ca02815Sjsg 	 *
2775ca02815Sjsg 	 * FIXME: BSpec says this should be done at the end of
2785ca02815Sjsg 	 * the modeset sequence, so not sure if this isn't too soon.
2795ca02815Sjsg 	 */
2805ca02815Sjsg 	if (pipe_config->pipe_bpp > 24 &&
2815ca02815Sjsg 	    pipe_config->pixel_multiplier > 1) {
2825ca02815Sjsg 		intel_de_write(dev_priv, intel_hdmi->hdmi_reg,
2835ca02815Sjsg 			       temp & ~SDVO_ENABLE);
2845ca02815Sjsg 		intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
2855ca02815Sjsg 
2865ca02815Sjsg 		/*
2875ca02815Sjsg 		 * HW workaround, need to write this twice for issue
2885ca02815Sjsg 		 * that may result in first write getting masked.
2895ca02815Sjsg 		 */
2905ca02815Sjsg 		intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
2915ca02815Sjsg 		intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
2925ca02815Sjsg 		intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
2935ca02815Sjsg 		intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
2945ca02815Sjsg 	}
2955ca02815Sjsg 
2961bb76ff1Sjsg 	drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
2971bb76ff1Sjsg 		    !pipe_config->has_hdmi_sink);
2981bb76ff1Sjsg 	intel_audio_codec_enable(encoder, pipe_config, conn_state);
2995ca02815Sjsg }
3005ca02815Sjsg 
cpt_enable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)3015ca02815Sjsg static void cpt_enable_hdmi(struct intel_atomic_state *state,
3025ca02815Sjsg 			    struct intel_encoder *encoder,
3035ca02815Sjsg 			    const struct intel_crtc_state *pipe_config,
3045ca02815Sjsg 			    const struct drm_connector_state *conn_state)
3055ca02815Sjsg {
3065ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
3075ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
3085ca02815Sjsg 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
3095ca02815Sjsg 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
3105ca02815Sjsg 	enum pipe pipe = crtc->pipe;
3115ca02815Sjsg 	u32 temp;
3125ca02815Sjsg 
3135ca02815Sjsg 	temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
3145ca02815Sjsg 
3155ca02815Sjsg 	temp |= SDVO_ENABLE;
3165ca02815Sjsg 	if (pipe_config->has_audio)
3175ca02815Sjsg 		temp |= HDMI_AUDIO_ENABLE;
3185ca02815Sjsg 
3195ca02815Sjsg 	/*
3205ca02815Sjsg 	 * WaEnableHDMI8bpcBefore12bpc:snb,ivb
3215ca02815Sjsg 	 *
3225ca02815Sjsg 	 * The procedure for 12bpc is as follows:
3235ca02815Sjsg 	 * 1. disable HDMI clock gating
3245ca02815Sjsg 	 * 2. enable HDMI with 8bpc
3255ca02815Sjsg 	 * 3. enable HDMI with 12bpc
3265ca02815Sjsg 	 * 4. enable HDMI clock gating
3275ca02815Sjsg 	 */
3285ca02815Sjsg 
3295ca02815Sjsg 	if (pipe_config->pipe_bpp > 24) {
330*f005ef32Sjsg 		intel_de_rmw(dev_priv, TRANS_CHICKEN1(pipe),
331*f005ef32Sjsg 			     0, TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
3325ca02815Sjsg 
3335ca02815Sjsg 		temp &= ~SDVO_COLOR_FORMAT_MASK;
3345ca02815Sjsg 		temp |= SDVO_COLOR_FORMAT_8bpc;
3355ca02815Sjsg 	}
3365ca02815Sjsg 
3375ca02815Sjsg 	intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
3385ca02815Sjsg 	intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
3395ca02815Sjsg 
3405ca02815Sjsg 	if (pipe_config->pipe_bpp > 24) {
3415ca02815Sjsg 		temp &= ~SDVO_COLOR_FORMAT_MASK;
3425ca02815Sjsg 		temp |= HDMI_COLOR_FORMAT_12bpc;
3435ca02815Sjsg 
3445ca02815Sjsg 		intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
3455ca02815Sjsg 		intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
3465ca02815Sjsg 
347*f005ef32Sjsg 		intel_de_rmw(dev_priv, TRANS_CHICKEN1(pipe),
348*f005ef32Sjsg 			     TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE, 0);
3495ca02815Sjsg 	}
3505ca02815Sjsg 
3511bb76ff1Sjsg 	drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
3521bb76ff1Sjsg 		    !pipe_config->has_hdmi_sink);
3531bb76ff1Sjsg 	intel_audio_codec_enable(encoder, pipe_config, conn_state);
3545ca02815Sjsg }
3555ca02815Sjsg 
vlv_enable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)3565ca02815Sjsg static void vlv_enable_hdmi(struct intel_atomic_state *state,
3575ca02815Sjsg 			    struct intel_encoder *encoder,
3585ca02815Sjsg 			    const struct intel_crtc_state *pipe_config,
3595ca02815Sjsg 			    const struct drm_connector_state *conn_state)
3605ca02815Sjsg {
361*f005ef32Sjsg 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
362*f005ef32Sjsg 
363*f005ef32Sjsg 	drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio &&
364*f005ef32Sjsg 		    !pipe_config->has_hdmi_sink);
365*f005ef32Sjsg 	intel_audio_codec_enable(encoder, pipe_config, conn_state);
3665ca02815Sjsg }
3675ca02815Sjsg 
intel_disable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3685ca02815Sjsg static void intel_disable_hdmi(struct intel_atomic_state *state,
3695ca02815Sjsg 			       struct intel_encoder *encoder,
3705ca02815Sjsg 			       const struct intel_crtc_state *old_crtc_state,
3715ca02815Sjsg 			       const struct drm_connector_state *old_conn_state)
3725ca02815Sjsg {
3735ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
3745ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
3755ca02815Sjsg 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
3765ca02815Sjsg 	struct intel_digital_port *dig_port =
3775ca02815Sjsg 		hdmi_to_dig_port(intel_hdmi);
3785ca02815Sjsg 	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
3795ca02815Sjsg 	u32 temp;
3805ca02815Sjsg 
3815ca02815Sjsg 	temp = intel_de_read(dev_priv, intel_hdmi->hdmi_reg);
3825ca02815Sjsg 
3835ca02815Sjsg 	temp &= ~(SDVO_ENABLE | HDMI_AUDIO_ENABLE);
3845ca02815Sjsg 	intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
3855ca02815Sjsg 	intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
3865ca02815Sjsg 
3875ca02815Sjsg 	/*
3885ca02815Sjsg 	 * HW workaround for IBX, we need to move the port
3895ca02815Sjsg 	 * to transcoder A after disabling it to allow the
3905ca02815Sjsg 	 * matching DP port to be enabled on transcoder A.
3915ca02815Sjsg 	 */
3925ca02815Sjsg 	if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
3935ca02815Sjsg 		/*
3945ca02815Sjsg 		 * We get CPU/PCH FIFO underruns on the other pipe when
3955ca02815Sjsg 		 * doing the workaround. Sweep them under the rug.
3965ca02815Sjsg 		 */
3975ca02815Sjsg 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, false);
3985ca02815Sjsg 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
3995ca02815Sjsg 
4005ca02815Sjsg 		temp &= ~SDVO_PIPE_SEL_MASK;
4015ca02815Sjsg 		temp |= SDVO_ENABLE | SDVO_PIPE_SEL(PIPE_A);
4025ca02815Sjsg 		/*
4035ca02815Sjsg 		 * HW workaround, need to write this twice for issue
4045ca02815Sjsg 		 * that may result in first write getting masked.
4055ca02815Sjsg 		 */
4065ca02815Sjsg 		intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
4075ca02815Sjsg 		intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
4085ca02815Sjsg 		intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
4095ca02815Sjsg 		intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
4105ca02815Sjsg 
4115ca02815Sjsg 		temp &= ~SDVO_ENABLE;
4125ca02815Sjsg 		intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp);
4135ca02815Sjsg 		intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg);
4145ca02815Sjsg 
4155ca02815Sjsg 		intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
4165ca02815Sjsg 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
4175ca02815Sjsg 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
4185ca02815Sjsg 	}
4195ca02815Sjsg 
4205ca02815Sjsg 	dig_port->set_infoframes(encoder,
4215ca02815Sjsg 				       false,
4225ca02815Sjsg 				       old_crtc_state, old_conn_state);
4235ca02815Sjsg 
4245ca02815Sjsg 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
4255ca02815Sjsg }
4265ca02815Sjsg 
g4x_disable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)4275ca02815Sjsg static void g4x_disable_hdmi(struct intel_atomic_state *state,
4285ca02815Sjsg 			     struct intel_encoder *encoder,
4295ca02815Sjsg 			     const struct intel_crtc_state *old_crtc_state,
4305ca02815Sjsg 			     const struct drm_connector_state *old_conn_state)
4315ca02815Sjsg {
4321bb76ff1Sjsg 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
4335ca02815Sjsg 
4345ca02815Sjsg 	intel_disable_hdmi(state, encoder, old_crtc_state, old_conn_state);
4355ca02815Sjsg }
4365ca02815Sjsg 
pch_disable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)4375ca02815Sjsg static void pch_disable_hdmi(struct intel_atomic_state *state,
4385ca02815Sjsg 			     struct intel_encoder *encoder,
4395ca02815Sjsg 			     const struct intel_crtc_state *old_crtc_state,
4405ca02815Sjsg 			     const struct drm_connector_state *old_conn_state)
4415ca02815Sjsg {
4421bb76ff1Sjsg 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
4435ca02815Sjsg }
4445ca02815Sjsg 
pch_post_disable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)4455ca02815Sjsg static void pch_post_disable_hdmi(struct intel_atomic_state *state,
4465ca02815Sjsg 				  struct intel_encoder *encoder,
4475ca02815Sjsg 				  const struct intel_crtc_state *old_crtc_state,
4485ca02815Sjsg 				  const struct drm_connector_state *old_conn_state)
4495ca02815Sjsg {
4505ca02815Sjsg 	intel_disable_hdmi(state, encoder, old_crtc_state, old_conn_state);
4515ca02815Sjsg }
4525ca02815Sjsg 
intel_hdmi_pre_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)4535ca02815Sjsg static void intel_hdmi_pre_enable(struct intel_atomic_state *state,
4545ca02815Sjsg 				  struct intel_encoder *encoder,
4555ca02815Sjsg 				  const struct intel_crtc_state *pipe_config,
4565ca02815Sjsg 				  const struct drm_connector_state *conn_state)
4575ca02815Sjsg {
4585ca02815Sjsg 	struct intel_digital_port *dig_port =
4595ca02815Sjsg 		enc_to_dig_port(encoder);
4605ca02815Sjsg 
4615ca02815Sjsg 	intel_hdmi_prepare(encoder, pipe_config);
4625ca02815Sjsg 
4635ca02815Sjsg 	dig_port->set_infoframes(encoder,
4645ca02815Sjsg 				       pipe_config->has_infoframe,
4655ca02815Sjsg 				       pipe_config, conn_state);
4665ca02815Sjsg }
4675ca02815Sjsg 
vlv_hdmi_pre_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)4685ca02815Sjsg static void vlv_hdmi_pre_enable(struct intel_atomic_state *state,
4695ca02815Sjsg 				struct intel_encoder *encoder,
4705ca02815Sjsg 				const struct intel_crtc_state *pipe_config,
4715ca02815Sjsg 				const struct drm_connector_state *conn_state)
4725ca02815Sjsg {
4735ca02815Sjsg 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
4745ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
4755ca02815Sjsg 
4765ca02815Sjsg 	vlv_phy_pre_encoder_enable(encoder, pipe_config);
4775ca02815Sjsg 
4785ca02815Sjsg 	/* HDMI 1.0V-2dB */
4795ca02815Sjsg 	vlv_set_phy_signal_level(encoder, pipe_config,
4805ca02815Sjsg 				 0x2b245f5f, 0x00002000,
4815ca02815Sjsg 				 0x5578b83a, 0x2b247878);
4825ca02815Sjsg 
4835ca02815Sjsg 	dig_port->set_infoframes(encoder,
4845ca02815Sjsg 			      pipe_config->has_infoframe,
4855ca02815Sjsg 			      pipe_config, conn_state);
4865ca02815Sjsg 
487*f005ef32Sjsg 	g4x_hdmi_enable_port(encoder, pipe_config);
4885ca02815Sjsg 
4895ca02815Sjsg 	vlv_wait_port_ready(dev_priv, dig_port, 0x0);
4905ca02815Sjsg }
4915ca02815Sjsg 
vlv_hdmi_pre_pll_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)4925ca02815Sjsg static void vlv_hdmi_pre_pll_enable(struct intel_atomic_state *state,
4935ca02815Sjsg 				    struct intel_encoder *encoder,
4945ca02815Sjsg 				    const struct intel_crtc_state *pipe_config,
4955ca02815Sjsg 				    const struct drm_connector_state *conn_state)
4965ca02815Sjsg {
4975ca02815Sjsg 	intel_hdmi_prepare(encoder, pipe_config);
4985ca02815Sjsg 
4995ca02815Sjsg 	vlv_phy_pre_pll_enable(encoder, pipe_config);
5005ca02815Sjsg }
5015ca02815Sjsg 
chv_hdmi_pre_pll_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)5025ca02815Sjsg static void chv_hdmi_pre_pll_enable(struct intel_atomic_state *state,
5035ca02815Sjsg 				    struct intel_encoder *encoder,
5045ca02815Sjsg 				    const struct intel_crtc_state *pipe_config,
5055ca02815Sjsg 				    const struct drm_connector_state *conn_state)
5065ca02815Sjsg {
5075ca02815Sjsg 	intel_hdmi_prepare(encoder, pipe_config);
5085ca02815Sjsg 
5095ca02815Sjsg 	chv_phy_pre_pll_enable(encoder, pipe_config);
5105ca02815Sjsg }
5115ca02815Sjsg 
chv_hdmi_post_pll_disable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)5125ca02815Sjsg static void chv_hdmi_post_pll_disable(struct intel_atomic_state *state,
5135ca02815Sjsg 				      struct intel_encoder *encoder,
5145ca02815Sjsg 				      const struct intel_crtc_state *old_crtc_state,
5155ca02815Sjsg 				      const struct drm_connector_state *old_conn_state)
5165ca02815Sjsg {
5175ca02815Sjsg 	chv_phy_post_pll_disable(encoder, old_crtc_state);
5185ca02815Sjsg }
5195ca02815Sjsg 
vlv_hdmi_post_disable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)5205ca02815Sjsg static void vlv_hdmi_post_disable(struct intel_atomic_state *state,
5215ca02815Sjsg 				  struct intel_encoder *encoder,
5225ca02815Sjsg 				  const struct intel_crtc_state *old_crtc_state,
5235ca02815Sjsg 				  const struct drm_connector_state *old_conn_state)
5245ca02815Sjsg {
5255ca02815Sjsg 	/* Reset lanes to avoid HDMI flicker (VLV w/a) */
5265ca02815Sjsg 	vlv_phy_reset_lanes(encoder, old_crtc_state);
5275ca02815Sjsg }
5285ca02815Sjsg 
chv_hdmi_post_disable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)5295ca02815Sjsg static void chv_hdmi_post_disable(struct intel_atomic_state *state,
5305ca02815Sjsg 				  struct intel_encoder *encoder,
5315ca02815Sjsg 				  const struct intel_crtc_state *old_crtc_state,
5325ca02815Sjsg 				  const struct drm_connector_state *old_conn_state)
5335ca02815Sjsg {
5345ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
5355ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
5365ca02815Sjsg 
5375ca02815Sjsg 	vlv_dpio_get(dev_priv);
5385ca02815Sjsg 
5395ca02815Sjsg 	/* Assert data lane reset */
5405ca02815Sjsg 	chv_data_lane_soft_reset(encoder, old_crtc_state, true);
5415ca02815Sjsg 
5425ca02815Sjsg 	vlv_dpio_put(dev_priv);
5435ca02815Sjsg }
5445ca02815Sjsg 
chv_hdmi_pre_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * pipe_config,const struct drm_connector_state * conn_state)5455ca02815Sjsg static void chv_hdmi_pre_enable(struct intel_atomic_state *state,
5465ca02815Sjsg 				struct intel_encoder *encoder,
5475ca02815Sjsg 				const struct intel_crtc_state *pipe_config,
5485ca02815Sjsg 				const struct drm_connector_state *conn_state)
5495ca02815Sjsg {
5505ca02815Sjsg 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
5515ca02815Sjsg 	struct drm_device *dev = encoder->base.dev;
5525ca02815Sjsg 	struct drm_i915_private *dev_priv = to_i915(dev);
5535ca02815Sjsg 
5545ca02815Sjsg 	chv_phy_pre_encoder_enable(encoder, pipe_config);
5555ca02815Sjsg 
5565ca02815Sjsg 	/* FIXME: Program the support xxx V-dB */
5575ca02815Sjsg 	/* Use 800mV-0dB */
5585ca02815Sjsg 	chv_set_phy_signal_level(encoder, pipe_config, 128, 102, false);
5595ca02815Sjsg 
5605ca02815Sjsg 	dig_port->set_infoframes(encoder,
5615ca02815Sjsg 			      pipe_config->has_infoframe,
5625ca02815Sjsg 			      pipe_config, conn_state);
5635ca02815Sjsg 
564*f005ef32Sjsg 	g4x_hdmi_enable_port(encoder, pipe_config);
5655ca02815Sjsg 
5665ca02815Sjsg 	vlv_wait_port_ready(dev_priv, dig_port, 0x0);
5675ca02815Sjsg 
5685ca02815Sjsg 	/* Second common lane will stay alive on its own now */
5695ca02815Sjsg 	chv_phy_release_cl2_override(encoder);
5705ca02815Sjsg }
5715ca02815Sjsg 
5725ca02815Sjsg static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
5735ca02815Sjsg 	.destroy = intel_encoder_destroy,
5745ca02815Sjsg };
5755ca02815Sjsg 
5765ca02815Sjsg static enum intel_hotplug_state
intel_hdmi_hotplug(struct intel_encoder * encoder,struct intel_connector * connector)5775ca02815Sjsg intel_hdmi_hotplug(struct intel_encoder *encoder,
5785ca02815Sjsg 		   struct intel_connector *connector)
5795ca02815Sjsg {
5805ca02815Sjsg 	enum intel_hotplug_state state;
5815ca02815Sjsg 
5825ca02815Sjsg 	state = intel_encoder_hotplug(encoder, connector);
5835ca02815Sjsg 
5845ca02815Sjsg 	/*
5855ca02815Sjsg 	 * On many platforms the HDMI live state signal is known to be
5865ca02815Sjsg 	 * unreliable, so we can't use it to detect if a sink is connected or
5875ca02815Sjsg 	 * not. Instead we detect if it's connected based on whether we can
5885ca02815Sjsg 	 * read the EDID or not. That in turn has a problem during disconnect,
5895ca02815Sjsg 	 * since the HPD interrupt may be raised before the DDC lines get
5905ca02815Sjsg 	 * disconnected (due to how the required length of DDC vs. HPD
5915ca02815Sjsg 	 * connector pins are specified) and so we'll still be able to get a
5925ca02815Sjsg 	 * valid EDID. To solve this schedule another detection cycle if this
5935ca02815Sjsg 	 * time around we didn't detect any change in the sink's connection
5945ca02815Sjsg 	 * status.
5955ca02815Sjsg 	 */
5965ca02815Sjsg 	if (state == INTEL_HOTPLUG_UNCHANGED && !connector->hotplug_retries)
5975ca02815Sjsg 		state = INTEL_HOTPLUG_RETRY;
5985ca02815Sjsg 
5995ca02815Sjsg 	return state;
6005ca02815Sjsg }
6015ca02815Sjsg 
g4x_hdmi_connector_atomic_check(struct drm_connector * connector,struct drm_atomic_state * state)602*f005ef32Sjsg int g4x_hdmi_connector_atomic_check(struct drm_connector *connector,
603*f005ef32Sjsg 				    struct drm_atomic_state *state)
604*f005ef32Sjsg {
605*f005ef32Sjsg 	struct drm_i915_private *i915 = to_i915(state->dev);
606*f005ef32Sjsg 	struct drm_connector_list_iter conn_iter;
607*f005ef32Sjsg 	struct drm_connector *conn;
608*f005ef32Sjsg 	int ret;
609*f005ef32Sjsg 
610*f005ef32Sjsg 	ret = intel_digital_connector_atomic_check(connector, state);
611*f005ef32Sjsg 	if (ret)
612*f005ef32Sjsg 		return ret;
613*f005ef32Sjsg 
614*f005ef32Sjsg 	if (!IS_G4X(i915))
615*f005ef32Sjsg 		return 0;
616*f005ef32Sjsg 
617*f005ef32Sjsg 	if (!intel_connector_needs_modeset(to_intel_atomic_state(state), connector))
618*f005ef32Sjsg 		return 0;
619*f005ef32Sjsg 
620*f005ef32Sjsg 	/*
621*f005ef32Sjsg 	 * On g4x only one HDMI port can transmit infoframes/audio
622*f005ef32Sjsg 	 * at any given time. Make sure all enabled HDMI ports are
623*f005ef32Sjsg 	 * included in the state so that it's possible to select
624*f005ef32Sjsg 	 * one of them for this duty.
625*f005ef32Sjsg 	 *
626*f005ef32Sjsg 	 * See also g4x_compute_has_hdmi_sink().
627*f005ef32Sjsg 	 */
628*f005ef32Sjsg 	drm_connector_list_iter_begin(&i915->drm, &conn_iter);
629*f005ef32Sjsg 	drm_for_each_connector_iter(conn, &conn_iter) {
630*f005ef32Sjsg 		struct drm_connector_state *conn_state;
631*f005ef32Sjsg 		struct drm_crtc_state *crtc_state;
632*f005ef32Sjsg 		struct drm_crtc *crtc;
633*f005ef32Sjsg 
634*f005ef32Sjsg 		if (!connector_is_hdmi(conn))
635*f005ef32Sjsg 			continue;
636*f005ef32Sjsg 
637*f005ef32Sjsg 		drm_dbg_kms(&i915->drm, "Adding [CONNECTOR:%d:%s]\n",
638*f005ef32Sjsg 			    conn->base.id, conn->name);
639*f005ef32Sjsg 
640*f005ef32Sjsg 		conn_state = drm_atomic_get_connector_state(state, conn);
641*f005ef32Sjsg 		if (IS_ERR(conn_state)) {
642*f005ef32Sjsg 			ret = PTR_ERR(conn_state);
643*f005ef32Sjsg 			break;
644*f005ef32Sjsg 		}
645*f005ef32Sjsg 
646*f005ef32Sjsg 		crtc = conn_state->crtc;
647*f005ef32Sjsg 		if (!crtc)
648*f005ef32Sjsg 			continue;
649*f005ef32Sjsg 
650*f005ef32Sjsg 		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
651*f005ef32Sjsg 		crtc_state->mode_changed = true;
652*f005ef32Sjsg 
653*f005ef32Sjsg 		ret = drm_atomic_add_affected_planes(state, crtc);
654*f005ef32Sjsg 		if (ret)
655*f005ef32Sjsg 			break;
656*f005ef32Sjsg 	}
657*f005ef32Sjsg 	drm_connector_list_iter_end(&conn_iter);
658*f005ef32Sjsg 
659*f005ef32Sjsg 	return ret;
660*f005ef32Sjsg }
661*f005ef32Sjsg 
is_hdmi_port_valid(struct drm_i915_private * i915,enum port port)662*f005ef32Sjsg static bool is_hdmi_port_valid(struct drm_i915_private *i915, enum port port)
663*f005ef32Sjsg {
664*f005ef32Sjsg 	if (IS_G4X(i915) || IS_VALLEYVIEW(i915))
665*f005ef32Sjsg 		return port == PORT_B || port == PORT_C;
666*f005ef32Sjsg 	else
667*f005ef32Sjsg 		return port == PORT_B || port == PORT_C || port == PORT_D;
668*f005ef32Sjsg }
669*f005ef32Sjsg 
assert_hdmi_port_valid(struct drm_i915_private * i915,enum port port)670*f005ef32Sjsg static bool assert_hdmi_port_valid(struct drm_i915_private *i915, enum port port)
671*f005ef32Sjsg {
672*f005ef32Sjsg 	return !drm_WARN(&i915->drm, !is_hdmi_port_valid(i915, port),
673*f005ef32Sjsg 			 "Platform does not support HDMI %c\n", port_name(port));
674*f005ef32Sjsg }
675*f005ef32Sjsg 
g4x_hdmi_init(struct drm_i915_private * dev_priv,i915_reg_t hdmi_reg,enum port port)6765ca02815Sjsg void g4x_hdmi_init(struct drm_i915_private *dev_priv,
6775ca02815Sjsg 		   i915_reg_t hdmi_reg, enum port port)
6785ca02815Sjsg {
679*f005ef32Sjsg 	const struct intel_bios_encoder_data *devdata;
6805ca02815Sjsg 	struct intel_digital_port *dig_port;
6815ca02815Sjsg 	struct intel_encoder *intel_encoder;
6825ca02815Sjsg 	struct intel_connector *intel_connector;
6835ca02815Sjsg 
684*f005ef32Sjsg 	if (!assert_port_valid(dev_priv, port))
685*f005ef32Sjsg 		return;
686*f005ef32Sjsg 
687*f005ef32Sjsg 	if (!assert_hdmi_port_valid(dev_priv, port))
688*f005ef32Sjsg 		return;
689*f005ef32Sjsg 
690*f005ef32Sjsg 	devdata = intel_bios_encoder_data_lookup(dev_priv, port);
691*f005ef32Sjsg 
692*f005ef32Sjsg 	/* FIXME bail? */
693*f005ef32Sjsg 	if (!devdata)
694*f005ef32Sjsg 		drm_dbg_kms(&dev_priv->drm, "No VBT child device for HDMI-%c\n",
695*f005ef32Sjsg 			    port_name(port));
696*f005ef32Sjsg 
6975ca02815Sjsg 	dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
6985ca02815Sjsg 	if (!dig_port)
6995ca02815Sjsg 		return;
7005ca02815Sjsg 
701*f005ef32Sjsg 	dig_port->aux_ch = AUX_CH_NONE;
702*f005ef32Sjsg 
7035ca02815Sjsg 	intel_connector = intel_connector_alloc();
7045ca02815Sjsg 	if (!intel_connector) {
7055ca02815Sjsg 		kfree(dig_port);
7065ca02815Sjsg 		return;
7075ca02815Sjsg 	}
7085ca02815Sjsg 
7095ca02815Sjsg 	intel_encoder = &dig_port->base;
7105ca02815Sjsg 
711*f005ef32Sjsg 	intel_encoder->devdata = devdata;
712*f005ef32Sjsg 
7135ca02815Sjsg 	rw_init(&dig_port->hdcp_mutex, "hhdcp");
7145ca02815Sjsg 
7155ca02815Sjsg 	drm_encoder_init(&dev_priv->drm, &intel_encoder->base,
7165ca02815Sjsg 			 &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS,
7175ca02815Sjsg 			 "HDMI %c", port_name(port));
7185ca02815Sjsg 
7195ca02815Sjsg 	intel_encoder->hotplug = intel_hdmi_hotplug;
720*f005ef32Sjsg 	intel_encoder->compute_config = g4x_hdmi_compute_config;
7215ca02815Sjsg 	if (HAS_PCH_SPLIT(dev_priv)) {
7225ca02815Sjsg 		intel_encoder->disable = pch_disable_hdmi;
7235ca02815Sjsg 		intel_encoder->post_disable = pch_post_disable_hdmi;
7245ca02815Sjsg 	} else {
7255ca02815Sjsg 		intel_encoder->disable = g4x_disable_hdmi;
7265ca02815Sjsg 	}
7275ca02815Sjsg 	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
7285ca02815Sjsg 	intel_encoder->get_config = intel_hdmi_get_config;
7295ca02815Sjsg 	if (IS_CHERRYVIEW(dev_priv)) {
7305ca02815Sjsg 		intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable;
7315ca02815Sjsg 		intel_encoder->pre_enable = chv_hdmi_pre_enable;
7325ca02815Sjsg 		intel_encoder->enable = vlv_enable_hdmi;
7335ca02815Sjsg 		intel_encoder->post_disable = chv_hdmi_post_disable;
7345ca02815Sjsg 		intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
7355ca02815Sjsg 	} else if (IS_VALLEYVIEW(dev_priv)) {
7365ca02815Sjsg 		intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
7375ca02815Sjsg 		intel_encoder->pre_enable = vlv_hdmi_pre_enable;
7385ca02815Sjsg 		intel_encoder->enable = vlv_enable_hdmi;
7395ca02815Sjsg 		intel_encoder->post_disable = vlv_hdmi_post_disable;
7405ca02815Sjsg 	} else {
7415ca02815Sjsg 		intel_encoder->pre_enable = intel_hdmi_pre_enable;
7425ca02815Sjsg 		if (HAS_PCH_CPT(dev_priv))
7435ca02815Sjsg 			intel_encoder->enable = cpt_enable_hdmi;
7445ca02815Sjsg 		else if (HAS_PCH_IBX(dev_priv))
7455ca02815Sjsg 			intel_encoder->enable = ibx_enable_hdmi;
7465ca02815Sjsg 		else
7475ca02815Sjsg 			intel_encoder->enable = g4x_enable_hdmi;
7485ca02815Sjsg 	}
7495ca02815Sjsg 	intel_encoder->shutdown = intel_hdmi_encoder_shutdown;
7505ca02815Sjsg 
7515ca02815Sjsg 	intel_encoder->type = INTEL_OUTPUT_HDMI;
7521bb76ff1Sjsg 	intel_encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port);
7535ca02815Sjsg 	intel_encoder->port = port;
7545ca02815Sjsg 	if (IS_CHERRYVIEW(dev_priv)) {
7555ca02815Sjsg 		if (port == PORT_D)
7565ca02815Sjsg 			intel_encoder->pipe_mask = BIT(PIPE_C);
7575ca02815Sjsg 		else
7585ca02815Sjsg 			intel_encoder->pipe_mask = BIT(PIPE_A) | BIT(PIPE_B);
7595ca02815Sjsg 	} else {
7605ca02815Sjsg 		intel_encoder->pipe_mask = ~0;
7615ca02815Sjsg 	}
762*f005ef32Sjsg 	intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG);
7635ca02815Sjsg 	intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
7645ca02815Sjsg 	/*
7655ca02815Sjsg 	 * BSpec is unclear about HDMI+HDMI cloning on g4x, but it seems
7665ca02815Sjsg 	 * to work on real hardware. And since g4x can send infoframes to
7675ca02815Sjsg 	 * only one port anyway, nothing is lost by allowing it.
7685ca02815Sjsg 	 */
7695ca02815Sjsg 	if (IS_G4X(dev_priv))
770*f005ef32Sjsg 		intel_encoder->cloneable |= BIT(INTEL_OUTPUT_HDMI);
7715ca02815Sjsg 
7725ca02815Sjsg 	dig_port->hdmi.hdmi_reg = hdmi_reg;
7735ca02815Sjsg 	dig_port->dp.output_reg = INVALID_MMIO_REG;
7745ca02815Sjsg 	dig_port->max_lanes = 4;
7755ca02815Sjsg 
7765ca02815Sjsg 	intel_infoframe_init(dig_port);
7775ca02815Sjsg 
7785ca02815Sjsg 	intel_hdmi_init_connector(dig_port, intel_connector);
7795ca02815Sjsg }
780