11bb76ff1Sjsg // SPDX-License-Identifier: MIT
21bb76ff1Sjsg /*
31bb76ff1Sjsg * Copyright © 2021 Intel Corporation
41bb76ff1Sjsg */
51bb76ff1Sjsg
61bb76ff1Sjsg #include "g4x_dp.h"
7*f005ef32Sjsg #include "i915_reg.h"
81bb76ff1Sjsg #include "intel_crt.h"
91bb76ff1Sjsg #include "intel_de.h"
101bb76ff1Sjsg #include "intel_display_types.h"
111bb76ff1Sjsg #include "intel_fdi.h"
12*f005ef32Sjsg #include "intel_fdi_regs.h"
131bb76ff1Sjsg #include "intel_lvds.h"
14*f005ef32Sjsg #include "intel_lvds_regs.h"
151bb76ff1Sjsg #include "intel_pch_display.h"
161bb76ff1Sjsg #include "intel_pch_refclk.h"
171bb76ff1Sjsg #include "intel_pps.h"
181bb76ff1Sjsg #include "intel_sdvo.h"
191bb76ff1Sjsg
intel_has_pch_trancoder(struct drm_i915_private * i915,enum pipe pch_transcoder)201bb76ff1Sjsg bool intel_has_pch_trancoder(struct drm_i915_private *i915,
211bb76ff1Sjsg enum pipe pch_transcoder)
221bb76ff1Sjsg {
231bb76ff1Sjsg return HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915) ||
241bb76ff1Sjsg (HAS_PCH_LPT_H(i915) && pch_transcoder == PIPE_A);
251bb76ff1Sjsg }
261bb76ff1Sjsg
intel_crtc_pch_transcoder(struct intel_crtc * crtc)271bb76ff1Sjsg enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
281bb76ff1Sjsg {
291bb76ff1Sjsg struct drm_i915_private *i915 = to_i915(crtc->base.dev);
301bb76ff1Sjsg
311bb76ff1Sjsg if (HAS_PCH_LPT(i915))
321bb76ff1Sjsg return PIPE_A;
331bb76ff1Sjsg else
341bb76ff1Sjsg return crtc->pipe;
351bb76ff1Sjsg }
361bb76ff1Sjsg
assert_pch_dp_disabled(struct drm_i915_private * dev_priv,enum pipe pipe,enum port port,i915_reg_t dp_reg)371bb76ff1Sjsg static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
381bb76ff1Sjsg enum pipe pipe, enum port port,
391bb76ff1Sjsg i915_reg_t dp_reg)
401bb76ff1Sjsg {
411bb76ff1Sjsg enum pipe port_pipe;
421bb76ff1Sjsg bool state;
431bb76ff1Sjsg
441bb76ff1Sjsg state = g4x_dp_port_enabled(dev_priv, dp_reg, port, &port_pipe);
451bb76ff1Sjsg
46*f005ef32Sjsg I915_STATE_WARN(dev_priv, state && port_pipe == pipe,
471bb76ff1Sjsg "PCH DP %c enabled on transcoder %c, should be disabled\n",
481bb76ff1Sjsg port_name(port), pipe_name(pipe));
491bb76ff1Sjsg
50*f005ef32Sjsg I915_STATE_WARN(dev_priv,
51*f005ef32Sjsg HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
521bb76ff1Sjsg "IBX PCH DP %c still using transcoder B\n",
531bb76ff1Sjsg port_name(port));
541bb76ff1Sjsg }
551bb76ff1Sjsg
assert_pch_hdmi_disabled(struct drm_i915_private * dev_priv,enum pipe pipe,enum port port,i915_reg_t hdmi_reg)561bb76ff1Sjsg static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
571bb76ff1Sjsg enum pipe pipe, enum port port,
581bb76ff1Sjsg i915_reg_t hdmi_reg)
591bb76ff1Sjsg {
601bb76ff1Sjsg enum pipe port_pipe;
611bb76ff1Sjsg bool state;
621bb76ff1Sjsg
631bb76ff1Sjsg state = intel_sdvo_port_enabled(dev_priv, hdmi_reg, &port_pipe);
641bb76ff1Sjsg
65*f005ef32Sjsg I915_STATE_WARN(dev_priv, state && port_pipe == pipe,
661bb76ff1Sjsg "PCH HDMI %c enabled on transcoder %c, should be disabled\n",
671bb76ff1Sjsg port_name(port), pipe_name(pipe));
681bb76ff1Sjsg
69*f005ef32Sjsg I915_STATE_WARN(dev_priv,
70*f005ef32Sjsg HAS_PCH_IBX(dev_priv) && !state && port_pipe == PIPE_B,
711bb76ff1Sjsg "IBX PCH HDMI %c still using transcoder B\n",
721bb76ff1Sjsg port_name(port));
731bb76ff1Sjsg }
741bb76ff1Sjsg
assert_pch_ports_disabled(struct drm_i915_private * dev_priv,enum pipe pipe)751bb76ff1Sjsg static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
761bb76ff1Sjsg enum pipe pipe)
771bb76ff1Sjsg {
781bb76ff1Sjsg enum pipe port_pipe;
791bb76ff1Sjsg
801bb76ff1Sjsg assert_pch_dp_disabled(dev_priv, pipe, PORT_B, PCH_DP_B);
811bb76ff1Sjsg assert_pch_dp_disabled(dev_priv, pipe, PORT_C, PCH_DP_C);
821bb76ff1Sjsg assert_pch_dp_disabled(dev_priv, pipe, PORT_D, PCH_DP_D);
831bb76ff1Sjsg
84*f005ef32Sjsg I915_STATE_WARN(dev_priv,
85*f005ef32Sjsg intel_crt_port_enabled(dev_priv, PCH_ADPA, &port_pipe) && port_pipe == pipe,
861bb76ff1Sjsg "PCH VGA enabled on transcoder %c, should be disabled\n",
871bb76ff1Sjsg pipe_name(pipe));
881bb76ff1Sjsg
89*f005ef32Sjsg I915_STATE_WARN(dev_priv,
90*f005ef32Sjsg intel_lvds_port_enabled(dev_priv, PCH_LVDS, &port_pipe) && port_pipe == pipe,
911bb76ff1Sjsg "PCH LVDS enabled on transcoder %c, should be disabled\n",
921bb76ff1Sjsg pipe_name(pipe));
931bb76ff1Sjsg
941bb76ff1Sjsg /* PCH SDVOB multiplex with HDMIB */
951bb76ff1Sjsg assert_pch_hdmi_disabled(dev_priv, pipe, PORT_B, PCH_HDMIB);
961bb76ff1Sjsg assert_pch_hdmi_disabled(dev_priv, pipe, PORT_C, PCH_HDMIC);
971bb76ff1Sjsg assert_pch_hdmi_disabled(dev_priv, pipe, PORT_D, PCH_HDMID);
981bb76ff1Sjsg }
991bb76ff1Sjsg
assert_pch_transcoder_disabled(struct drm_i915_private * dev_priv,enum pipe pipe)1001bb76ff1Sjsg static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
1011bb76ff1Sjsg enum pipe pipe)
1021bb76ff1Sjsg {
1031bb76ff1Sjsg u32 val;
1041bb76ff1Sjsg bool enabled;
1051bb76ff1Sjsg
1061bb76ff1Sjsg val = intel_de_read(dev_priv, PCH_TRANSCONF(pipe));
1071bb76ff1Sjsg enabled = !!(val & TRANS_ENABLE);
108*f005ef32Sjsg I915_STATE_WARN(dev_priv, enabled,
1091bb76ff1Sjsg "transcoder assertion failed, should be off on pipe %c but is still active\n",
1101bb76ff1Sjsg pipe_name(pipe));
1111bb76ff1Sjsg }
1121bb76ff1Sjsg
ibx_sanitize_pch_hdmi_port(struct drm_i915_private * dev_priv,enum port port,i915_reg_t hdmi_reg)1131bb76ff1Sjsg static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv,
1141bb76ff1Sjsg enum port port, i915_reg_t hdmi_reg)
1151bb76ff1Sjsg {
1161bb76ff1Sjsg u32 val = intel_de_read(dev_priv, hdmi_reg);
1171bb76ff1Sjsg
1181bb76ff1Sjsg if (val & SDVO_ENABLE ||
1191bb76ff1Sjsg (val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A))
1201bb76ff1Sjsg return;
1211bb76ff1Sjsg
1221bb76ff1Sjsg drm_dbg_kms(&dev_priv->drm,
1231bb76ff1Sjsg "Sanitizing transcoder select for HDMI %c\n",
1241bb76ff1Sjsg port_name(port));
1251bb76ff1Sjsg
1261bb76ff1Sjsg val &= ~SDVO_PIPE_SEL_MASK;
1271bb76ff1Sjsg val |= SDVO_PIPE_SEL(PIPE_A);
1281bb76ff1Sjsg
1291bb76ff1Sjsg intel_de_write(dev_priv, hdmi_reg, val);
1301bb76ff1Sjsg }
1311bb76ff1Sjsg
ibx_sanitize_pch_dp_port(struct drm_i915_private * dev_priv,enum port port,i915_reg_t dp_reg)1321bb76ff1Sjsg static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv,
1331bb76ff1Sjsg enum port port, i915_reg_t dp_reg)
1341bb76ff1Sjsg {
1351bb76ff1Sjsg u32 val = intel_de_read(dev_priv, dp_reg);
1361bb76ff1Sjsg
1371bb76ff1Sjsg if (val & DP_PORT_EN ||
1381bb76ff1Sjsg (val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A))
1391bb76ff1Sjsg return;
1401bb76ff1Sjsg
1411bb76ff1Sjsg drm_dbg_kms(&dev_priv->drm,
1421bb76ff1Sjsg "Sanitizing transcoder select for DP %c\n",
1431bb76ff1Sjsg port_name(port));
1441bb76ff1Sjsg
1451bb76ff1Sjsg val &= ~DP_PIPE_SEL_MASK;
1461bb76ff1Sjsg val |= DP_PIPE_SEL(PIPE_A);
1471bb76ff1Sjsg
1481bb76ff1Sjsg intel_de_write(dev_priv, dp_reg, val);
1491bb76ff1Sjsg }
1501bb76ff1Sjsg
ibx_sanitize_pch_ports(struct drm_i915_private * dev_priv)1511bb76ff1Sjsg static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv)
1521bb76ff1Sjsg {
1531bb76ff1Sjsg /*
1541bb76ff1Sjsg * The BIOS may select transcoder B on some of the PCH
1551bb76ff1Sjsg * ports even it doesn't enable the port. This would trip
1561bb76ff1Sjsg * assert_pch_dp_disabled() and assert_pch_hdmi_disabled().
1571bb76ff1Sjsg * Sanitize the transcoder select bits to prevent that. We
1581bb76ff1Sjsg * assume that the BIOS never actually enabled the port,
1591bb76ff1Sjsg * because if it did we'd actually have to toggle the port
1601bb76ff1Sjsg * on and back off to make the transcoder A select stick
1611bb76ff1Sjsg * (see. intel_dp_link_down(), intel_disable_hdmi(),
1621bb76ff1Sjsg * intel_disable_sdvo()).
1631bb76ff1Sjsg */
1641bb76ff1Sjsg ibx_sanitize_pch_dp_port(dev_priv, PORT_B, PCH_DP_B);
1651bb76ff1Sjsg ibx_sanitize_pch_dp_port(dev_priv, PORT_C, PCH_DP_C);
1661bb76ff1Sjsg ibx_sanitize_pch_dp_port(dev_priv, PORT_D, PCH_DP_D);
1671bb76ff1Sjsg
1681bb76ff1Sjsg /* PCH SDVOB multiplex with HDMIB */
1691bb76ff1Sjsg ibx_sanitize_pch_hdmi_port(dev_priv, PORT_B, PCH_HDMIB);
1701bb76ff1Sjsg ibx_sanitize_pch_hdmi_port(dev_priv, PORT_C, PCH_HDMIC);
1711bb76ff1Sjsg ibx_sanitize_pch_hdmi_port(dev_priv, PORT_D, PCH_HDMID);
1721bb76ff1Sjsg }
1731bb76ff1Sjsg
intel_pch_transcoder_set_m1_n1(struct intel_crtc * crtc,const struct intel_link_m_n * m_n)1741bb76ff1Sjsg static void intel_pch_transcoder_set_m1_n1(struct intel_crtc *crtc,
1751bb76ff1Sjsg const struct intel_link_m_n *m_n)
1761bb76ff1Sjsg {
1771bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1781bb76ff1Sjsg enum pipe pipe = crtc->pipe;
1791bb76ff1Sjsg
1801bb76ff1Sjsg intel_set_m_n(dev_priv, m_n,
1811bb76ff1Sjsg PCH_TRANS_DATA_M1(pipe), PCH_TRANS_DATA_N1(pipe),
1821bb76ff1Sjsg PCH_TRANS_LINK_M1(pipe), PCH_TRANS_LINK_N1(pipe));
1831bb76ff1Sjsg }
1841bb76ff1Sjsg
intel_pch_transcoder_set_m2_n2(struct intel_crtc * crtc,const struct intel_link_m_n * m_n)1851bb76ff1Sjsg static void intel_pch_transcoder_set_m2_n2(struct intel_crtc *crtc,
1861bb76ff1Sjsg const struct intel_link_m_n *m_n)
1871bb76ff1Sjsg {
1881bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1891bb76ff1Sjsg enum pipe pipe = crtc->pipe;
1901bb76ff1Sjsg
1911bb76ff1Sjsg intel_set_m_n(dev_priv, m_n,
1921bb76ff1Sjsg PCH_TRANS_DATA_M2(pipe), PCH_TRANS_DATA_N2(pipe),
1931bb76ff1Sjsg PCH_TRANS_LINK_M2(pipe), PCH_TRANS_LINK_N2(pipe));
1941bb76ff1Sjsg }
1951bb76ff1Sjsg
intel_pch_transcoder_get_m1_n1(struct intel_crtc * crtc,struct intel_link_m_n * m_n)1961bb76ff1Sjsg void intel_pch_transcoder_get_m1_n1(struct intel_crtc *crtc,
1971bb76ff1Sjsg struct intel_link_m_n *m_n)
1981bb76ff1Sjsg {
1991bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2001bb76ff1Sjsg enum pipe pipe = crtc->pipe;
2011bb76ff1Sjsg
2021bb76ff1Sjsg intel_get_m_n(dev_priv, m_n,
2031bb76ff1Sjsg PCH_TRANS_DATA_M1(pipe), PCH_TRANS_DATA_N1(pipe),
2041bb76ff1Sjsg PCH_TRANS_LINK_M1(pipe), PCH_TRANS_LINK_N1(pipe));
2051bb76ff1Sjsg }
2061bb76ff1Sjsg
intel_pch_transcoder_get_m2_n2(struct intel_crtc * crtc,struct intel_link_m_n * m_n)2071bb76ff1Sjsg void intel_pch_transcoder_get_m2_n2(struct intel_crtc *crtc,
2081bb76ff1Sjsg struct intel_link_m_n *m_n)
2091bb76ff1Sjsg {
2101bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2111bb76ff1Sjsg enum pipe pipe = crtc->pipe;
2121bb76ff1Sjsg
2131bb76ff1Sjsg intel_get_m_n(dev_priv, m_n,
2141bb76ff1Sjsg PCH_TRANS_DATA_M2(pipe), PCH_TRANS_DATA_N2(pipe),
2151bb76ff1Sjsg PCH_TRANS_LINK_M2(pipe), PCH_TRANS_LINK_N2(pipe));
2161bb76ff1Sjsg }
2171bb76ff1Sjsg
ilk_pch_transcoder_set_timings(const struct intel_crtc_state * crtc_state,enum pipe pch_transcoder)2181bb76ff1Sjsg static void ilk_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state,
2191bb76ff1Sjsg enum pipe pch_transcoder)
2201bb76ff1Sjsg {
2211bb76ff1Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2221bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2231bb76ff1Sjsg enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
2241bb76ff1Sjsg
2251bb76ff1Sjsg intel_de_write(dev_priv, PCH_TRANS_HTOTAL(pch_transcoder),
226*f005ef32Sjsg intel_de_read(dev_priv, TRANS_HTOTAL(cpu_transcoder)));
2271bb76ff1Sjsg intel_de_write(dev_priv, PCH_TRANS_HBLANK(pch_transcoder),
228*f005ef32Sjsg intel_de_read(dev_priv, TRANS_HBLANK(cpu_transcoder)));
2291bb76ff1Sjsg intel_de_write(dev_priv, PCH_TRANS_HSYNC(pch_transcoder),
230*f005ef32Sjsg intel_de_read(dev_priv, TRANS_HSYNC(cpu_transcoder)));
2311bb76ff1Sjsg
2321bb76ff1Sjsg intel_de_write(dev_priv, PCH_TRANS_VTOTAL(pch_transcoder),
233*f005ef32Sjsg intel_de_read(dev_priv, TRANS_VTOTAL(cpu_transcoder)));
2341bb76ff1Sjsg intel_de_write(dev_priv, PCH_TRANS_VBLANK(pch_transcoder),
235*f005ef32Sjsg intel_de_read(dev_priv, TRANS_VBLANK(cpu_transcoder)));
2361bb76ff1Sjsg intel_de_write(dev_priv, PCH_TRANS_VSYNC(pch_transcoder),
237*f005ef32Sjsg intel_de_read(dev_priv, TRANS_VSYNC(cpu_transcoder)));
2381bb76ff1Sjsg intel_de_write(dev_priv, PCH_TRANS_VSYNCSHIFT(pch_transcoder),
239*f005ef32Sjsg intel_de_read(dev_priv, TRANS_VSYNCSHIFT(cpu_transcoder)));
2401bb76ff1Sjsg }
2411bb76ff1Sjsg
ilk_enable_pch_transcoder(const struct intel_crtc_state * crtc_state)2421bb76ff1Sjsg static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
2431bb76ff1Sjsg {
2441bb76ff1Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2451bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2461bb76ff1Sjsg enum pipe pipe = crtc->pipe;
2471bb76ff1Sjsg i915_reg_t reg;
2481bb76ff1Sjsg u32 val, pipeconf_val;
2491bb76ff1Sjsg
2501bb76ff1Sjsg /* Make sure PCH DPLL is enabled */
2511bb76ff1Sjsg assert_shared_dpll_enabled(dev_priv, crtc_state->shared_dpll);
2521bb76ff1Sjsg
2531bb76ff1Sjsg /* FDI must be feeding us bits for PCH ports */
2541bb76ff1Sjsg assert_fdi_tx_enabled(dev_priv, pipe);
2551bb76ff1Sjsg assert_fdi_rx_enabled(dev_priv, pipe);
2561bb76ff1Sjsg
2571bb76ff1Sjsg if (HAS_PCH_CPT(dev_priv)) {
2581bb76ff1Sjsg reg = TRANS_CHICKEN2(pipe);
2591bb76ff1Sjsg val = intel_de_read(dev_priv, reg);
2601bb76ff1Sjsg /*
2611bb76ff1Sjsg * Workaround: Set the timing override bit
2621bb76ff1Sjsg * before enabling the pch transcoder.
2631bb76ff1Sjsg */
2641bb76ff1Sjsg val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
2651bb76ff1Sjsg /* Configure frame start delay to match the CPU */
2661bb76ff1Sjsg val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
2671bb76ff1Sjsg val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
2681bb76ff1Sjsg intel_de_write(dev_priv, reg, val);
2691bb76ff1Sjsg }
2701bb76ff1Sjsg
2711bb76ff1Sjsg reg = PCH_TRANSCONF(pipe);
2721bb76ff1Sjsg val = intel_de_read(dev_priv, reg);
273*f005ef32Sjsg pipeconf_val = intel_de_read(dev_priv, TRANSCONF(pipe));
2741bb76ff1Sjsg
2751bb76ff1Sjsg if (HAS_PCH_IBX(dev_priv)) {
2761bb76ff1Sjsg /* Configure frame start delay to match the CPU */
2771bb76ff1Sjsg val &= ~TRANS_FRAME_START_DELAY_MASK;
2781bb76ff1Sjsg val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
2791bb76ff1Sjsg
2801bb76ff1Sjsg /*
2811bb76ff1Sjsg * Make the BPC in transcoder be consistent with
2821bb76ff1Sjsg * that in pipeconf reg. For HDMI we must use 8bpc
2831bb76ff1Sjsg * here for both 8bpc and 12bpc.
2841bb76ff1Sjsg */
285*f005ef32Sjsg val &= ~TRANSCONF_BPC_MASK;
2861bb76ff1Sjsg if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
287*f005ef32Sjsg val |= TRANSCONF_BPC_8;
2881bb76ff1Sjsg else
289*f005ef32Sjsg val |= pipeconf_val & TRANSCONF_BPC_MASK;
2901bb76ff1Sjsg }
2911bb76ff1Sjsg
2921bb76ff1Sjsg val &= ~TRANS_INTERLACE_MASK;
293*f005ef32Sjsg if ((pipeconf_val & TRANSCONF_INTERLACE_MASK_ILK) == TRANSCONF_INTERLACE_IF_ID_ILK) {
2941bb76ff1Sjsg if (HAS_PCH_IBX(dev_priv) &&
2951bb76ff1Sjsg intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
2961bb76ff1Sjsg val |= TRANS_INTERLACE_LEGACY_VSYNC_IBX;
2971bb76ff1Sjsg else
2981bb76ff1Sjsg val |= TRANS_INTERLACE_INTERLACED;
2991bb76ff1Sjsg } else {
3001bb76ff1Sjsg val |= TRANS_INTERLACE_PROGRESSIVE;
3011bb76ff1Sjsg }
3021bb76ff1Sjsg
3031bb76ff1Sjsg intel_de_write(dev_priv, reg, val | TRANS_ENABLE);
3041bb76ff1Sjsg if (intel_de_wait_for_set(dev_priv, reg, TRANS_STATE_ENABLE, 100))
3051bb76ff1Sjsg drm_err(&dev_priv->drm, "failed to enable transcoder %c\n",
3061bb76ff1Sjsg pipe_name(pipe));
3071bb76ff1Sjsg }
3081bb76ff1Sjsg
ilk_disable_pch_transcoder(struct intel_crtc * crtc)3091bb76ff1Sjsg static void ilk_disable_pch_transcoder(struct intel_crtc *crtc)
3101bb76ff1Sjsg {
3111bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
3121bb76ff1Sjsg enum pipe pipe = crtc->pipe;
3131bb76ff1Sjsg i915_reg_t reg;
3141bb76ff1Sjsg
3151bb76ff1Sjsg /* FDI relies on the transcoder */
3161bb76ff1Sjsg assert_fdi_tx_disabled(dev_priv, pipe);
3171bb76ff1Sjsg assert_fdi_rx_disabled(dev_priv, pipe);
3181bb76ff1Sjsg
3191bb76ff1Sjsg /* Ports must be off as well */
3201bb76ff1Sjsg assert_pch_ports_disabled(dev_priv, pipe);
3211bb76ff1Sjsg
3221bb76ff1Sjsg reg = PCH_TRANSCONF(pipe);
323*f005ef32Sjsg intel_de_rmw(dev_priv, reg, TRANS_ENABLE, 0);
3241bb76ff1Sjsg /* wait for PCH transcoder off, transcoder state */
3251bb76ff1Sjsg if (intel_de_wait_for_clear(dev_priv, reg, TRANS_STATE_ENABLE, 50))
3261bb76ff1Sjsg drm_err(&dev_priv->drm, "failed to disable transcoder %c\n",
3271bb76ff1Sjsg pipe_name(pipe));
3281bb76ff1Sjsg
329*f005ef32Sjsg if (HAS_PCH_CPT(dev_priv))
3301bb76ff1Sjsg /* Workaround: Clear the timing override chicken bit again. */
331*f005ef32Sjsg intel_de_rmw(dev_priv, TRANS_CHICKEN2(pipe),
332*f005ef32Sjsg TRANS_CHICKEN2_TIMING_OVERRIDE, 0);
3331bb76ff1Sjsg }
3341bb76ff1Sjsg
ilk_pch_pre_enable(struct intel_atomic_state * state,struct intel_crtc * crtc)3351bb76ff1Sjsg void ilk_pch_pre_enable(struct intel_atomic_state *state,
3361bb76ff1Sjsg struct intel_crtc *crtc)
3371bb76ff1Sjsg {
3381bb76ff1Sjsg const struct intel_crtc_state *crtc_state =
3391bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc);
3401bb76ff1Sjsg
3411bb76ff1Sjsg /*
3421bb76ff1Sjsg * Note: FDI PLL enabling _must_ be done before we enable the
3431bb76ff1Sjsg * cpu pipes, hence this is separate from all the other fdi/pch
3441bb76ff1Sjsg * enabling.
3451bb76ff1Sjsg */
3461bb76ff1Sjsg ilk_fdi_pll_enable(crtc_state);
3471bb76ff1Sjsg }
3481bb76ff1Sjsg
3491bb76ff1Sjsg /*
3501bb76ff1Sjsg * Enable PCH resources required for PCH ports:
3511bb76ff1Sjsg * - PCH PLLs
3521bb76ff1Sjsg * - FDI training & RX/TX
3531bb76ff1Sjsg * - update transcoder timings
3541bb76ff1Sjsg * - DP transcoding bits
3551bb76ff1Sjsg * - transcoder
3561bb76ff1Sjsg */
ilk_pch_enable(struct intel_atomic_state * state,struct intel_crtc * crtc)3571bb76ff1Sjsg void ilk_pch_enable(struct intel_atomic_state *state,
3581bb76ff1Sjsg struct intel_crtc *crtc)
3591bb76ff1Sjsg {
3601bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
3611bb76ff1Sjsg const struct intel_crtc_state *crtc_state =
3621bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc);
3631bb76ff1Sjsg enum pipe pipe = crtc->pipe;
3641bb76ff1Sjsg u32 temp;
3651bb76ff1Sjsg
3661bb76ff1Sjsg assert_pch_transcoder_disabled(dev_priv, pipe);
3671bb76ff1Sjsg
3681bb76ff1Sjsg /* For PCH output, training FDI link */
3691bb76ff1Sjsg intel_fdi_link_train(crtc, crtc_state);
3701bb76ff1Sjsg
3711bb76ff1Sjsg /*
3721bb76ff1Sjsg * We need to program the right clock selection
3731bb76ff1Sjsg * before writing the pixel multiplier into the DPLL.
3741bb76ff1Sjsg */
3751bb76ff1Sjsg if (HAS_PCH_CPT(dev_priv)) {
3761bb76ff1Sjsg u32 sel;
3771bb76ff1Sjsg
3781bb76ff1Sjsg temp = intel_de_read(dev_priv, PCH_DPLL_SEL);
3791bb76ff1Sjsg temp |= TRANS_DPLL_ENABLE(pipe);
3801bb76ff1Sjsg sel = TRANS_DPLLB_SEL(pipe);
3811bb76ff1Sjsg if (crtc_state->shared_dpll ==
3821bb76ff1Sjsg intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B))
3831bb76ff1Sjsg temp |= sel;
3841bb76ff1Sjsg else
3851bb76ff1Sjsg temp &= ~sel;
3861bb76ff1Sjsg intel_de_write(dev_priv, PCH_DPLL_SEL, temp);
3871bb76ff1Sjsg }
3881bb76ff1Sjsg
3891bb76ff1Sjsg /*
3901bb76ff1Sjsg * XXX: pch pll's can be enabled any time before we enable the PCH
3911bb76ff1Sjsg * transcoder, and we actually should do this to not upset any PCH
3921bb76ff1Sjsg * transcoder that already use the clock when we share it.
3931bb76ff1Sjsg *
3941bb76ff1Sjsg * Note that enable_shared_dpll tries to do the right thing, but
3951bb76ff1Sjsg * get_shared_dpll unconditionally resets the pll - we need that
3961bb76ff1Sjsg * to have the right LVDS enable sequence.
3971bb76ff1Sjsg */
3981bb76ff1Sjsg intel_enable_shared_dpll(crtc_state);
3991bb76ff1Sjsg
4001bb76ff1Sjsg /* set transcoder timing, panel must allow it */
4011bb76ff1Sjsg assert_pps_unlocked(dev_priv, pipe);
4021bb76ff1Sjsg if (intel_crtc_has_dp_encoder(crtc_state)) {
4031bb76ff1Sjsg intel_pch_transcoder_set_m1_n1(crtc, &crtc_state->dp_m_n);
4041bb76ff1Sjsg intel_pch_transcoder_set_m2_n2(crtc, &crtc_state->dp_m2_n2);
4051bb76ff1Sjsg }
4061bb76ff1Sjsg ilk_pch_transcoder_set_timings(crtc_state, pipe);
4071bb76ff1Sjsg
4081bb76ff1Sjsg intel_fdi_normal_train(crtc);
4091bb76ff1Sjsg
4101bb76ff1Sjsg /* For PCH DP, enable TRANS_DP_CTL */
4111bb76ff1Sjsg if (HAS_PCH_CPT(dev_priv) &&
4121bb76ff1Sjsg intel_crtc_has_dp_encoder(crtc_state)) {
4131bb76ff1Sjsg const struct drm_display_mode *adjusted_mode =
4141bb76ff1Sjsg &crtc_state->hw.adjusted_mode;
415*f005ef32Sjsg u32 bpc = (intel_de_read(dev_priv, TRANSCONF(pipe)) & TRANSCONF_BPC_MASK) >> 5;
4161bb76ff1Sjsg i915_reg_t reg = TRANS_DP_CTL(pipe);
4171bb76ff1Sjsg enum port port;
4181bb76ff1Sjsg
4191bb76ff1Sjsg temp = intel_de_read(dev_priv, reg);
4201bb76ff1Sjsg temp &= ~(TRANS_DP_PORT_SEL_MASK |
4211bb76ff1Sjsg TRANS_DP_VSYNC_ACTIVE_HIGH |
4221bb76ff1Sjsg TRANS_DP_HSYNC_ACTIVE_HIGH |
4231bb76ff1Sjsg TRANS_DP_BPC_MASK);
4241bb76ff1Sjsg temp |= TRANS_DP_OUTPUT_ENABLE;
4251bb76ff1Sjsg temp |= bpc << 9; /* same format but at 11:9 */
4261bb76ff1Sjsg
4271bb76ff1Sjsg if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
4281bb76ff1Sjsg temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
4291bb76ff1Sjsg if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
4301bb76ff1Sjsg temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
4311bb76ff1Sjsg
4321bb76ff1Sjsg port = intel_get_crtc_new_encoder(state, crtc_state)->port;
4331bb76ff1Sjsg drm_WARN_ON(&dev_priv->drm, port < PORT_B || port > PORT_D);
4341bb76ff1Sjsg temp |= TRANS_DP_PORT_SEL(port);
4351bb76ff1Sjsg
4361bb76ff1Sjsg intel_de_write(dev_priv, reg, temp);
4371bb76ff1Sjsg }
4381bb76ff1Sjsg
4391bb76ff1Sjsg ilk_enable_pch_transcoder(crtc_state);
4401bb76ff1Sjsg }
4411bb76ff1Sjsg
ilk_pch_disable(struct intel_atomic_state * state,struct intel_crtc * crtc)4421bb76ff1Sjsg void ilk_pch_disable(struct intel_atomic_state *state,
4431bb76ff1Sjsg struct intel_crtc *crtc)
4441bb76ff1Sjsg {
4451bb76ff1Sjsg ilk_fdi_disable(crtc);
4461bb76ff1Sjsg }
4471bb76ff1Sjsg
ilk_pch_post_disable(struct intel_atomic_state * state,struct intel_crtc * crtc)4481bb76ff1Sjsg void ilk_pch_post_disable(struct intel_atomic_state *state,
4491bb76ff1Sjsg struct intel_crtc *crtc)
4501bb76ff1Sjsg {
4511bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
4521bb76ff1Sjsg enum pipe pipe = crtc->pipe;
4531bb76ff1Sjsg
4541bb76ff1Sjsg ilk_disable_pch_transcoder(crtc);
4551bb76ff1Sjsg
4561bb76ff1Sjsg if (HAS_PCH_CPT(dev_priv)) {
4571bb76ff1Sjsg /* disable TRANS_DP_CTL */
458*f005ef32Sjsg intel_de_rmw(dev_priv, TRANS_DP_CTL(pipe),
459*f005ef32Sjsg TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK,
460*f005ef32Sjsg TRANS_DP_PORT_SEL_NONE);
4611bb76ff1Sjsg
4621bb76ff1Sjsg /* disable DPLL_SEL */
463*f005ef32Sjsg intel_de_rmw(dev_priv, PCH_DPLL_SEL,
464*f005ef32Sjsg TRANS_DPLL_ENABLE(pipe) | TRANS_DPLLB_SEL(pipe), 0);
4651bb76ff1Sjsg }
4661bb76ff1Sjsg
4671bb76ff1Sjsg ilk_fdi_pll_disable(crtc);
4681bb76ff1Sjsg }
4691bb76ff1Sjsg
ilk_pch_clock_get(struct intel_crtc_state * crtc_state)4701bb76ff1Sjsg static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state)
4711bb76ff1Sjsg {
4721bb76ff1Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
4731bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
4741bb76ff1Sjsg
4751bb76ff1Sjsg /* read out port_clock from the DPLL */
4761bb76ff1Sjsg i9xx_crtc_clock_get(crtc, crtc_state);
4771bb76ff1Sjsg
4781bb76ff1Sjsg /*
4791bb76ff1Sjsg * In case there is an active pipe without active ports,
4801bb76ff1Sjsg * we may need some idea for the dotclock anyway.
4811bb76ff1Sjsg * Calculate one based on the FDI configuration.
4821bb76ff1Sjsg */
4831bb76ff1Sjsg crtc_state->hw.adjusted_mode.crtc_clock =
4841bb76ff1Sjsg intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, crtc_state),
4851bb76ff1Sjsg &crtc_state->fdi_m_n);
4861bb76ff1Sjsg }
4871bb76ff1Sjsg
ilk_pch_get_config(struct intel_crtc_state * crtc_state)4881bb76ff1Sjsg void ilk_pch_get_config(struct intel_crtc_state *crtc_state)
4891bb76ff1Sjsg {
4901bb76ff1Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
4911bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
4921bb76ff1Sjsg struct intel_shared_dpll *pll;
4931bb76ff1Sjsg enum pipe pipe = crtc->pipe;
4941bb76ff1Sjsg enum intel_dpll_id pll_id;
4951bb76ff1Sjsg bool pll_active;
4961bb76ff1Sjsg u32 tmp;
4971bb76ff1Sjsg
4981bb76ff1Sjsg if ((intel_de_read(dev_priv, PCH_TRANSCONF(pipe)) & TRANS_ENABLE) == 0)
4991bb76ff1Sjsg return;
5001bb76ff1Sjsg
5011bb76ff1Sjsg crtc_state->has_pch_encoder = true;
5021bb76ff1Sjsg
5031bb76ff1Sjsg tmp = intel_de_read(dev_priv, FDI_RX_CTL(pipe));
5041bb76ff1Sjsg crtc_state->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
5051bb76ff1Sjsg FDI_DP_PORT_WIDTH_SHIFT) + 1;
5061bb76ff1Sjsg
5071bb76ff1Sjsg intel_cpu_transcoder_get_m1_n1(crtc, crtc_state->cpu_transcoder,
5081bb76ff1Sjsg &crtc_state->fdi_m_n);
5091bb76ff1Sjsg
5101bb76ff1Sjsg if (HAS_PCH_IBX(dev_priv)) {
5111bb76ff1Sjsg /*
5121bb76ff1Sjsg * The pipe->pch transcoder and pch transcoder->pll
5131bb76ff1Sjsg * mapping is fixed.
5141bb76ff1Sjsg */
5151bb76ff1Sjsg pll_id = (enum intel_dpll_id) pipe;
5161bb76ff1Sjsg } else {
5171bb76ff1Sjsg tmp = intel_de_read(dev_priv, PCH_DPLL_SEL);
5181bb76ff1Sjsg if (tmp & TRANS_DPLLB_SEL(pipe))
5191bb76ff1Sjsg pll_id = DPLL_ID_PCH_PLL_B;
5201bb76ff1Sjsg else
5211bb76ff1Sjsg pll_id = DPLL_ID_PCH_PLL_A;
5221bb76ff1Sjsg }
5231bb76ff1Sjsg
5241bb76ff1Sjsg crtc_state->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
5251bb76ff1Sjsg pll = crtc_state->shared_dpll;
5261bb76ff1Sjsg
5271bb76ff1Sjsg pll_active = intel_dpll_get_hw_state(dev_priv, pll,
5281bb76ff1Sjsg &crtc_state->dpll_hw_state);
5291bb76ff1Sjsg drm_WARN_ON(&dev_priv->drm, !pll_active);
5301bb76ff1Sjsg
5311bb76ff1Sjsg tmp = crtc_state->dpll_hw_state.dpll;
5321bb76ff1Sjsg crtc_state->pixel_multiplier =
5331bb76ff1Sjsg ((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK)
5341bb76ff1Sjsg >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1;
5351bb76ff1Sjsg
5361bb76ff1Sjsg ilk_pch_clock_get(crtc_state);
5371bb76ff1Sjsg }
5381bb76ff1Sjsg
lpt_enable_pch_transcoder(const struct intel_crtc_state * crtc_state)5391bb76ff1Sjsg static void lpt_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
5401bb76ff1Sjsg {
5411bb76ff1Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
5421bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
5431bb76ff1Sjsg enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
5441bb76ff1Sjsg u32 val, pipeconf_val;
5451bb76ff1Sjsg
5461bb76ff1Sjsg /* FDI must be feeding us bits for PCH ports */
5471bb76ff1Sjsg assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
5481bb76ff1Sjsg assert_fdi_rx_enabled(dev_priv, PIPE_A);
5491bb76ff1Sjsg
5501bb76ff1Sjsg val = intel_de_read(dev_priv, TRANS_CHICKEN2(PIPE_A));
5511bb76ff1Sjsg /* Workaround: set timing override bit. */
5521bb76ff1Sjsg val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
5531bb76ff1Sjsg /* Configure frame start delay to match the CPU */
5541bb76ff1Sjsg val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
5551bb76ff1Sjsg val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1);
5561bb76ff1Sjsg intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val);
5571bb76ff1Sjsg
5581bb76ff1Sjsg val = TRANS_ENABLE;
559*f005ef32Sjsg pipeconf_val = intel_de_read(dev_priv, TRANSCONF(cpu_transcoder));
5601bb76ff1Sjsg
561*f005ef32Sjsg if ((pipeconf_val & TRANSCONF_INTERLACE_MASK_HSW) == TRANSCONF_INTERLACE_IF_ID_ILK)
5621bb76ff1Sjsg val |= TRANS_INTERLACE_INTERLACED;
5631bb76ff1Sjsg else
5641bb76ff1Sjsg val |= TRANS_INTERLACE_PROGRESSIVE;
5651bb76ff1Sjsg
5661bb76ff1Sjsg intel_de_write(dev_priv, LPT_TRANSCONF, val);
5671bb76ff1Sjsg if (intel_de_wait_for_set(dev_priv, LPT_TRANSCONF,
5681bb76ff1Sjsg TRANS_STATE_ENABLE, 100))
5691bb76ff1Sjsg drm_err(&dev_priv->drm, "Failed to enable PCH transcoder\n");
5701bb76ff1Sjsg }
5711bb76ff1Sjsg
lpt_disable_pch_transcoder(struct drm_i915_private * dev_priv)5721bb76ff1Sjsg static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
5731bb76ff1Sjsg {
574*f005ef32Sjsg intel_de_rmw(dev_priv, LPT_TRANSCONF, TRANS_ENABLE, 0);
5751bb76ff1Sjsg /* wait for PCH transcoder off, transcoder state */
5761bb76ff1Sjsg if (intel_de_wait_for_clear(dev_priv, LPT_TRANSCONF,
5771bb76ff1Sjsg TRANS_STATE_ENABLE, 50))
5781bb76ff1Sjsg drm_err(&dev_priv->drm, "Failed to disable PCH transcoder\n");
5791bb76ff1Sjsg
5801bb76ff1Sjsg /* Workaround: clear timing override bit. */
581*f005ef32Sjsg intel_de_rmw(dev_priv, TRANS_CHICKEN2(PIPE_A), TRANS_CHICKEN2_TIMING_OVERRIDE, 0);
5821bb76ff1Sjsg }
5831bb76ff1Sjsg
lpt_pch_enable(struct intel_atomic_state * state,struct intel_crtc * crtc)5841bb76ff1Sjsg void lpt_pch_enable(struct intel_atomic_state *state,
5851bb76ff1Sjsg struct intel_crtc *crtc)
5861bb76ff1Sjsg {
5871bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
5881bb76ff1Sjsg const struct intel_crtc_state *crtc_state =
5891bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc);
5901bb76ff1Sjsg
5911bb76ff1Sjsg assert_pch_transcoder_disabled(dev_priv, PIPE_A);
5921bb76ff1Sjsg
5931bb76ff1Sjsg lpt_program_iclkip(crtc_state);
5941bb76ff1Sjsg
5951bb76ff1Sjsg /* Set transcoder timing. */
5961bb76ff1Sjsg ilk_pch_transcoder_set_timings(crtc_state, PIPE_A);
5971bb76ff1Sjsg
5981bb76ff1Sjsg lpt_enable_pch_transcoder(crtc_state);
5991bb76ff1Sjsg }
6001bb76ff1Sjsg
lpt_pch_disable(struct intel_atomic_state * state,struct intel_crtc * crtc)6011bb76ff1Sjsg void lpt_pch_disable(struct intel_atomic_state *state,
6021bb76ff1Sjsg struct intel_crtc *crtc)
6031bb76ff1Sjsg {
6041bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
6051bb76ff1Sjsg
6061bb76ff1Sjsg lpt_disable_pch_transcoder(dev_priv);
6071bb76ff1Sjsg
6081bb76ff1Sjsg lpt_disable_iclkip(dev_priv);
6091bb76ff1Sjsg }
6101bb76ff1Sjsg
lpt_pch_get_config(struct intel_crtc_state * crtc_state)6111bb76ff1Sjsg void lpt_pch_get_config(struct intel_crtc_state *crtc_state)
6121bb76ff1Sjsg {
6131bb76ff1Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
6141bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
6151bb76ff1Sjsg u32 tmp;
6161bb76ff1Sjsg
6171bb76ff1Sjsg if ((intel_de_read(dev_priv, LPT_TRANSCONF) & TRANS_ENABLE) == 0)
6181bb76ff1Sjsg return;
6191bb76ff1Sjsg
6201bb76ff1Sjsg crtc_state->has_pch_encoder = true;
6211bb76ff1Sjsg
6221bb76ff1Sjsg tmp = intel_de_read(dev_priv, FDI_RX_CTL(PIPE_A));
6231bb76ff1Sjsg crtc_state->fdi_lanes = ((FDI_DP_PORT_WIDTH_MASK & tmp) >>
6241bb76ff1Sjsg FDI_DP_PORT_WIDTH_SHIFT) + 1;
6251bb76ff1Sjsg
6261bb76ff1Sjsg intel_cpu_transcoder_get_m1_n1(crtc, crtc_state->cpu_transcoder,
6271bb76ff1Sjsg &crtc_state->fdi_m_n);
6281bb76ff1Sjsg
6291bb76ff1Sjsg crtc_state->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv);
6301bb76ff1Sjsg }
6311bb76ff1Sjsg
intel_pch_sanitize(struct drm_i915_private * i915)6321bb76ff1Sjsg void intel_pch_sanitize(struct drm_i915_private *i915)
6331bb76ff1Sjsg {
6341bb76ff1Sjsg if (HAS_PCH_IBX(i915))
6351bb76ff1Sjsg ibx_sanitize_pch_ports(i915);
6361bb76ff1Sjsg }
637