summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_snps_phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_snps_phy.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.c146
1 files changed, 66 insertions, 80 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
index bc61e736f9b3..2b53ac9f4935 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -5,11 +5,15 @@
#include <linux/math.h>
+#include <drm/drm_print.h>
+
#include "i915_reg.h"
+#include "i915_utils.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
#include "intel_display_types.h"
+#include "intel_snps_hdmi_pll.h"
#include "intel_snps_phy.h"
#include "intel_snps_phy_regs.h"
@@ -25,12 +29,12 @@
* since it is not handled by the shared DPLL framework as on other platforms.
*/
-void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915)
+void intel_snps_phy_wait_for_calibration(struct intel_display *display)
{
enum phy phy;
for_each_phy_masked(phy, ~0) {
- if (!intel_phy_is_snps(i915, phy))
+ if (!intel_phy_is_snps(display, phy))
continue;
/*
@@ -38,36 +42,38 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915)
* which phy was affected and skip setup of the corresponding
* output later.
*/
- if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy),
+ if (intel_de_wait_for_clear(display, DG2_PHY_MISC(phy),
DG2_PHY_DP_TX_ACK_MASK, 25))
- i915->display.snps.phy_failed_calibration |= BIT(phy);
+ display->snps.phy_failed_calibration |= BIT(phy);
}
}
-void intel_snps_phy_update_psr_power_state(struct drm_i915_private *i915,
- enum phy phy, bool enable)
+void intel_snps_phy_update_psr_power_state(struct intel_encoder *encoder,
+ bool enable)
{
+ struct intel_display *display = to_intel_display(encoder);
+ enum phy phy = intel_encoder_to_phy(encoder);
u32 val;
- if (!intel_phy_is_snps(i915, phy))
+ if (!intel_encoder_is_snps(encoder))
return;
val = REG_FIELD_PREP(SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR,
enable ? 2 : 3);
- intel_de_rmw(i915, SNPS_PHY_TX_REQ(phy),
+ intel_de_rmw(display, SNPS_PHY_TX_REQ(phy),
SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val);
}
void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
const struct intel_ddi_buf_trans *trans;
- enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ enum phy phy = intel_encoder_to_phy(encoder);
int n_entries, ln;
trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
- if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
+ if (drm_WARN_ON_ONCE(display->drm, !trans))
return;
for (ln = 0; ln < 4; ln++) {
@@ -78,7 +84,7 @@ void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder,
val |= REG_FIELD_PREP(SNPS_PHY_TX_EQ_PRE, trans->entries[level].snps.pre_cursor);
val |= REG_FIELD_PREP(SNPS_PHY_TX_EQ_POST, trans->entries[level].snps.post_cursor);
- intel_de_write(dev_priv, SNPS_PHY_TX_EQ(ln, phy), val);
+ intel_de_write(display, SNPS_PHY_TX_EQ(ln, phy), val);
}
}
@@ -518,7 +524,7 @@ static const struct intel_mpllb_state dg2_hdmi_148_5 = {
REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
};
-/* values in the below table are calculted using the algo */
+/* values in the below table are calculated using the algo */
static const struct intel_mpllb_state dg2_hdmi_25200 = {
.clock = 25200,
.ref_control =
@@ -1785,44 +1791,37 @@ intel_mpllb_tables_get(struct intel_crtc_state *crtc_state,
int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state,
struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
const struct intel_mpllb_state * const *tables;
int i;
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
- if (intel_snps_phy_check_hdmi_link_rate(crtc_state->port_clock)
- != MODE_OK) {
- /*
- * FIXME: Can only support fixed HDMI frequencies
- * until we have a proper algorithm under a valid
- * license.
- */
- drm_dbg_kms(&i915->drm, "Can't support HDMI link rate %d\n",
- crtc_state->port_clock);
- return -EINVAL;
- }
- }
-
tables = intel_mpllb_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
for (i = 0; tables[i]; i++) {
if (crtc_state->port_clock == tables[i]->clock) {
- crtc_state->mpllb_state = *tables[i];
+ crtc_state->dpll_hw_state.mpllb = *tables[i];
return 0;
}
}
+ /* For HDMI PLLs try SNPS PHY algorithm, if there are no precomputed tables */
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+ intel_snps_hdmi_pll_compute_mpllb(&crtc_state->dpll_hw_state.mpllb,
+ crtc_state->port_clock);
+
+ return 0;
+ }
+
return -EINVAL;
}
void intel_mpllb_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- const struct intel_mpllb_state *pll_state = &crtc_state->mpllb_state;
- enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ struct intel_display *display = to_intel_display(encoder);
+ const struct intel_mpllb_state *pll_state = &crtc_state->dpll_hw_state.mpllb;
+ enum phy phy = intel_encoder_to_phy(encoder);
i915_reg_t enable_reg = (phy <= PHY_D ?
DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0));
@@ -1830,13 +1829,13 @@ void intel_mpllb_enable(struct intel_encoder *encoder,
* 3. Software programs the following PLL registers for the desired
* frequency.
*/
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_CP(phy), pll_state->mpllb_cp);
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV(phy), pll_state->mpllb_div);
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV2(phy), pll_state->mpllb_div2);
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_SSCEN(phy), pll_state->mpllb_sscen);
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_SSCSTEP(phy), pll_state->mpllb_sscstep);
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_FRACN1(phy), pll_state->mpllb_fracn1);
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_FRACN2(phy), pll_state->mpllb_fracn2);
+ intel_de_write(display, SNPS_PHY_MPLLB_CP(phy), pll_state->mpllb_cp);
+ intel_de_write(display, SNPS_PHY_MPLLB_DIV(phy), pll_state->mpllb_div);
+ intel_de_write(display, SNPS_PHY_MPLLB_DIV2(phy), pll_state->mpllb_div2);
+ intel_de_write(display, SNPS_PHY_MPLLB_SSCEN(phy), pll_state->mpllb_sscen);
+ intel_de_write(display, SNPS_PHY_MPLLB_SSCSTEP(phy), pll_state->mpllb_sscstep);
+ intel_de_write(display, SNPS_PHY_MPLLB_FRACN1(phy), pll_state->mpllb_fracn1);
+ intel_de_write(display, SNPS_PHY_MPLLB_FRACN2(phy), pll_state->mpllb_fracn2);
/*
* 4. If the frequency will result in a change to the voltage
@@ -1847,7 +1846,7 @@ void intel_mpllb_enable(struct intel_encoder *encoder,
*/
/* 5. Software sets DPLL_ENABLE [PLL Enable] to "1". */
- intel_de_rmw(dev_priv, enable_reg, 0, PLL_ENABLE);
+ intel_de_rmw(display, enable_reg, 0, PLL_ENABLE);
/*
* 9. Software sets SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "1". This
@@ -1856,7 +1855,7 @@ void intel_mpllb_enable(struct intel_encoder *encoder,
* PLL because that will start the PLL before it has sampled the
* divider values.
*/
- intel_de_write(dev_priv, SNPS_PHY_MPLLB_DIV(phy),
+ intel_de_write(display, SNPS_PHY_MPLLB_DIV(phy),
pll_state->mpllb_div | SNPS_PHY_MPLLB_FORCE_EN);
/*
@@ -1864,8 +1863,8 @@ void intel_mpllb_enable(struct intel_encoder *encoder,
* is locked at new settings. This register bit is sampling PHY
* dp_mpllb_state interface signal.
*/
- if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_LOCK, 5))
- drm_dbg_kms(&dev_priv->drm, "Port %c PLL not locked\n", phy_name(phy));
+ if (intel_de_wait_for_set(display, enable_reg, PLL_LOCK, 5))
+ drm_dbg_kms(display->drm, "Port %c PLL not locked\n", phy_name(phy));
/*
* 11. If the frequency will result in a change to the voltage
@@ -1878,8 +1877,8 @@ void intel_mpllb_enable(struct intel_encoder *encoder,
void intel_mpllb_disable(struct intel_encoder *encoder)
{
- struct drm_i915_private *i915 = to_i915(encoder->base.dev);
- enum phy phy = intel_port_to_phy(i915, encoder->port);
+ struct intel_display *display = to_intel_display(encoder);
+ enum phy phy = intel_encoder_to_phy(encoder);
i915_reg_t enable_reg = (phy <= PHY_D ?
DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0));
@@ -1892,20 +1891,20 @@ void intel_mpllb_disable(struct intel_encoder *encoder)
*/
/* 2. Software programs DPLL_ENABLE [PLL Enable] to "0" */
- intel_de_rmw(i915, enable_reg, PLL_ENABLE, 0);
+ intel_de_rmw(display, enable_reg, PLL_ENABLE, 0);
/*
* 4. Software programs SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "0".
* This will allow the PLL to stop running.
*/
- intel_de_rmw(i915, SNPS_PHY_MPLLB_DIV(phy), SNPS_PHY_MPLLB_FORCE_EN, 0);
+ intel_de_rmw(display, SNPS_PHY_MPLLB_DIV(phy), SNPS_PHY_MPLLB_FORCE_EN, 0);
/*
* 5. Software polls DPLL_ENABLE [PLL Lock] for PHY acknowledgment
* (dp_txX_ack) that the new transmitter setting request is completed.
*/
- if (intel_de_wait_for_clear(i915, enable_reg, PLL_LOCK, 5))
- drm_err(&i915->drm, "Port %c PLL not locked\n", phy_name(phy));
+ if (intel_de_wait_for_clear(display, enable_reg, PLL_LOCK, 5))
+ drm_err(display->drm, "Port %c PLL not locked\n", phy_name(phy));
/*
* 6. If the frequency will result in a change to the voltage
@@ -1950,16 +1949,16 @@ int intel_mpllb_calc_port_clock(struct intel_encoder *encoder,
void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
struct intel_mpllb_state *pll_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+ struct intel_display *display = to_intel_display(encoder);
+ enum phy phy = intel_encoder_to_phy(encoder);
- pll_state->mpllb_cp = intel_de_read(dev_priv, SNPS_PHY_MPLLB_CP(phy));
- pll_state->mpllb_div = intel_de_read(dev_priv, SNPS_PHY_MPLLB_DIV(phy));
- pll_state->mpllb_div2 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_DIV2(phy));
- pll_state->mpllb_sscen = intel_de_read(dev_priv, SNPS_PHY_MPLLB_SSCEN(phy));
- pll_state->mpllb_sscstep = intel_de_read(dev_priv, SNPS_PHY_MPLLB_SSCSTEP(phy));
- pll_state->mpllb_fracn1 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_FRACN1(phy));
- pll_state->mpllb_fracn2 = intel_de_read(dev_priv, SNPS_PHY_MPLLB_FRACN2(phy));
+ pll_state->mpllb_cp = intel_de_read(display, SNPS_PHY_MPLLB_CP(phy));
+ pll_state->mpllb_div = intel_de_read(display, SNPS_PHY_MPLLB_DIV(phy));
+ pll_state->mpllb_div2 = intel_de_read(display, SNPS_PHY_MPLLB_DIV2(phy));
+ pll_state->mpllb_sscen = intel_de_read(display, SNPS_PHY_MPLLB_SSCEN(phy));
+ pll_state->mpllb_sscstep = intel_de_read(display, SNPS_PHY_MPLLB_SSCSTEP(phy));
+ pll_state->mpllb_fracn1 = intel_de_read(display, SNPS_PHY_MPLLB_FRACN1(phy));
+ pll_state->mpllb_fracn2 = intel_de_read(display, SNPS_PHY_MPLLB_FRACN2(phy));
/*
* REF_CONTROL is under firmware control and never programmed by the
@@ -1967,7 +1966,7 @@ void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
* only tells us the expected value for one field in this register,
* so we'll only read out those specific bits here.
*/
- pll_state->ref_control = intel_de_read(dev_priv, SNPS_PHY_REF_CONTROL(phy)) &
+ pll_state->ref_control = intel_de_read(display, SNPS_PHY_REF_CONTROL(phy)) &
SNPS_PHY_REF_CONTROL_REF_RANGE;
/*
@@ -1979,30 +1978,17 @@ void intel_mpllb_readout_hw_state(struct intel_encoder *encoder,
pll_state->mpllb_div &= ~SNPS_PHY_MPLLB_FORCE_EN;
}
-int intel_snps_phy_check_hdmi_link_rate(int clock)
-{
- const struct intel_mpllb_state * const *tables = dg2_hdmi_tables;
- int i;
-
- for (i = 0; tables[i]; i++) {
- if (clock == tables[i]->clock)
- return MODE_OK;
- }
-
- return MODE_CLOCK_RANGE;
-}
-
void intel_mpllb_state_verify(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
- struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_display *display = to_intel_display(state);
const struct intel_crtc_state *new_crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
struct intel_mpllb_state mpllb_hw_state = {};
- const struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state;
+ const struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->dpll_hw_state.mpllb;
struct intel_encoder *encoder;
- if (!IS_DG2(i915))
+ if (!display->platform.dg2)
return;
if (!new_crtc_state->hw.active)
@@ -2017,11 +2003,11 @@ void intel_mpllb_state_verify(struct intel_atomic_state *state,
intel_mpllb_readout_hw_state(encoder, &mpllb_hw_state);
#define MPLLB_CHECK(__name) \
- I915_STATE_WARN(i915, mpllb_sw_state->__name != mpllb_hw_state.__name, \
- "[CRTC:%d:%s] mismatch in MPLLB: %s (expected 0x%08x, found 0x%08x)", \
- crtc->base.base.id, crtc->base.name, \
- __stringify(__name), \
- mpllb_sw_state->__name, mpllb_hw_state.__name)
+ INTEL_DISPLAY_STATE_WARN(display, mpllb_sw_state->__name != mpllb_hw_state.__name, \
+ "[CRTC:%d:%s] mismatch in MPLLB: %s (expected 0x%08x, found 0x%08x)", \
+ crtc->base.base.id, crtc->base.name, \
+ __stringify(__name), \
+ mpllb_sw_state->__name, mpllb_hw_state.__name)
MPLLB_CHECK(mpllb_cp);
MPLLB_CHECK(mpllb_div);