[PATCH 2/2] drm/i915/display: Force full modeset for eDP

2024-02-05 Thread Mika Kahola
Force full modeset for eDP when booting up. GOP programs
PLL parameters and hence, we would be able to use fastset
for eDP. However, with fastset we are not setting PLL values
from the driver and rely that GOP and driver PLL values match.
We have discovered that with some of the panels this is not
true and hence we would need to program PLL values by the
driver. The patch suggests a workaround as enabling full
modeset when booting up. This way we force the driver to
write the PLL values to the hw.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index ab415f41924d..9699ded1eb5f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3319,6 +3319,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder 
*encoder,
 * of crtc_state->dsc, we have no way to ensure reliable fastset.
 * Remove once we have readout for DSC.
 */
+
if (crtc_state->dsc.compression_enable) {
drm_dbg_kms(>drm, "[ENCODER:%d:%s] Forcing full modeset 
due to DSC being enabled\n",
encoder->base.base.id, encoder->base.name);
@@ -3326,6 +3327,18 @@ bool intel_dp_initial_fastset_check(struct intel_encoder 
*encoder,
fastset = false;
}
 
+   /*
+* FIXME hack to force full modeset for eDP as not always BIOS written 
PLL
+* values does not match with the ones defined in the driver code
+*/
+   if (!crtc_state->uapi.mode_changed &&
+   intel_dp_is_edp(intel_dp)) {
+   drm_dbg_kms(>drm, "Forcing full modeset for eDP\n");
+   crtc_state->uapi.mode_changed = true;
+   fastset = false;
+   }
+
+
return fastset;
 }
 
-- 
2.34.1



[PATCH 1/2] Revert "drm/i915/display: Skip C10 state verification in case of fastset"

2024-02-05 Thread Mika Kahola
This reverts commit a1d91c6e989d0e66b89aa911f2cd459d7bdebbe5.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 288a00e083c8..5051e7f5abb1 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3017,9 +3017,6 @@ static void intel_c10pll_state_verify(const struct 
intel_crtc_state *state,
const struct intel_c10pll_state *mpllb_sw_state = 
>cx0pll_state.c10;
int i;
 
-   if (intel_crtc_needs_fastset(state))
-   return;
-
for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
u8 expected = mpllb_sw_state->pll[i];
 
-- 
2.34.1



[PATCH 0/2] drm/i915/display: Force full modeset for eDP

2024-02-05 Thread Mika Kahola
It was discovered that we couldn't skip the fastset on state
verification and hence this workaround is proposed.

First, the patch that skips state verifcation in case of
fastset is reverted. The second patch proposes the following
workaround by forcing full modeset for eDP when booting up.
GOP programs PLL parameters and hence, we would be able to
use fastset for eDP. However, with fastset we are not setting
PLL values from the driver and rely that GOP and driver PLL
values match. We have discovered that with some of the panels
this is not true and hence we would need to program PLL values
by the driver.

Signed-off-by: Mika Kahola 

Mika Kahola (2):
  Revert "drm/i915/display: Skip C10 state verification in case of
fastset"
  drm/i915/display: Force full modeset for eDP

 drivers/gpu/drm/i915/display/intel_cx0_phy.c |  3 ---
 drivers/gpu/drm/i915/display/intel_dp.c  | 13 +
 2 files changed, 13 insertions(+), 3 deletions(-)

-- 
2.34.1



[PATCH] drm/i915/display: Use helper to select C20 MPLLA/B

2024-01-05 Thread Mika Kahola
We used to select between MPLLA/B with the following

state->tx[0] & C20_PHY_USE_MPLLB

Since this is used a few places within C20 PLL setting,
let's introduce a helper function to clean up the code
a bit.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index ce1bddf74a82..e67c25975947 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2096,6 +2096,11 @@ int intel_cx0pll_calc_state(struct intel_crtc_state 
*crtc_state,
return intel_c20pll_calc_state(crtc_state, encoder);
 }
 
+static bool intel_c20phy_use_mpllb(const struct intel_c20pll_state *state)
+{
+   return state->tx[0] & C20_PHY_USE_MPLLB;
+}
+
 static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
const struct intel_c20pll_state 
*pll_state)
 {
@@ -2108,7 +2113,7 @@ static int intel_c20pll_calc_port_clock(struct 
intel_encoder *encoder,
unsigned int tx_rate_mult;
unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
 
-   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   if (intel_c20phy_use_mpllb(pll_state)) {
tx_rate_mult = 1;
frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
frac_quot = pll_state->mpllb[8];
@@ -2174,7 +2179,7 @@ static void intel_c20pll_readout_hw_state(struct 
intel_encoder *encoder,

PHY_C20_A_CMN_CNTX_CFG(i));
}
 
-   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   if (intel_c20phy_use_mpllb(pll_state)) {
/* MPLLB configuration */
for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
if (cntx)
@@ -2212,7 +2217,7 @@ void intel_c20pll_dump_hw_state(struct drm_i915_private 
*i915,
drm_dbg_kms(>drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 
0x%.4x, cmn[3] = 0x%.4x\n",
hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], 
hw_state->cmn[3]);
 
-   if (hw_state->tx[0] & C20_PHY_USE_MPLLB) {
+   if (intel_c20phy_use_mpllb(hw_state)) {
for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
drm_dbg_kms(>drm, "mpllb[%d] = 0x%.4x\n", i, 
hw_state->mpllb[i]);
} else {
@@ -2364,7 +2369,7 @@ static void intel_c20_pll_program(struct drm_i915_private 
*i915,
}
 
/* 3.3 mpllb or mplla configuration */
-   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   if (intel_c20phy_use_mpllb(pll_state)) {
for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
if (cntx)
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
@@ -3063,8 +3068,8 @@ static void intel_c20pll_state_verify(const struct 
intel_crtc_state *state,
 {
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct intel_c20pll_state *mpll_sw_state = 
>cx0pll_state.c20;
-   bool sw_use_mpllb = mpll_sw_state->tx[0] & C20_PHY_USE_MPLLB;
-   bool hw_use_mpllb = mpll_hw_state->tx[0] & C20_PHY_USE_MPLLB;
+   bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state);
+   bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state);
int i;
 
I915_STATE_WARN(i915, mpll_hw_state->clock != mpll_sw_state->clock,
-- 
2.34.1



[PATCH v2 3/3] drm/i915/display: Cleanup mplla/mpllb selection

2024-01-02 Thread Mika Kahola
The function intel_c20_use_mplla() is not really
widely used and can be replaced with the more suitable

pll->tx[0] & C20_PHY_USE_MPLLB

expression. Let's remove the intel_c20_use_mplla()
alltogether and replace mplla/mpllb selection by
checking mpllb bit.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 39 
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index fc7211675b2f..d0b6b4e439e1 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2096,15 +2096,6 @@ int intel_cx0pll_calc_state(struct intel_crtc_state 
*crtc_state,
return intel_c20pll_calc_state(crtc_state, encoder);
 }
 
-static bool intel_c20_use_mplla(u32 clock)
-{
-   /* 10G and 20G rates use MPLLA */
-   if (clock == 100 || clock == 200)
-   return true;
-
-   return false;
-}
-
 static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
const struct intel_c20pll_state 
*pll_state)
 {
@@ -2221,12 +2212,12 @@ void intel_c20pll_dump_hw_state(struct drm_i915_private 
*i915,
drm_dbg_kms(>drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 
0x%.4x, cmn[3] = 0x%.4x\n",
hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], 
hw_state->cmn[3]);
 
-   if (intel_c20_use_mplla(hw_state->clock)) {
-   for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
-   drm_dbg_kms(>drm, "mplla[%d] = 0x%.4x\n", i, 
hw_state->mplla[i]);
-   } else {
+   if (hw_state->tx[0] & C20_PHY_USE_MPLLB) {
for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
drm_dbg_kms(>drm, "mpllb[%d] = 0x%.4x\n", i, 
hw_state->mpllb[i]);
+   } else {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
+   drm_dbg_kms(>drm, "mplla[%d] = 0x%.4x\n", i, 
hw_state->mplla[i]);
}
 }
 
@@ -2373,27 +2364,27 @@ static void intel_c20_pll_program(struct 
drm_i915_private *i915,
}
 
/* 3.3 mpllb or mplla configuration */
-   if (intel_c20_use_mplla(clock)) {
-   for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
+   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
if (cntx)
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_A_MPLLA_CNTX_CFG(i),
-pll_state->mplla[i]);
+
PHY_C20_A_MPLLB_CNTX_CFG(i),
+pll_state->mpllb[i]);
else
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_B_MPLLA_CNTX_CFG(i),
-pll_state->mplla[i]);
+
PHY_C20_B_MPLLB_CNTX_CFG(i),
+pll_state->mpllb[i]);
}
} else {
-   for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
+   for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
if (cntx)
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_A_MPLLB_CNTX_CFG(i),
-pll_state->mpllb[i]);
+
PHY_C20_A_MPLLA_CNTX_CFG(i),
+pll_state->mplla[i]);
else
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_B_MPLLB_CNTX_CFG(i),
-pll_state->mpllb[i]);
+
PHY_C20_B_MPLLA_CNTX_CFG(i),
+pll_state->mplla[i]);
}
}
 
-- 
2.34.1



[PATCH v2 2/3] drm/i915/display: Store hw clock for C20

2024-01-02 Thread Mika Kahola
We can calculate the hw port clock during the hw readout
and store it as pll_state->clock for C20 state verification.
In order to do that we need to move intel_c20pll_calc_port_clock()
function.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 97 +++-
 1 file changed, 52 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 6b25e195232f..fc7211675b2f 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2105,6 +2105,51 @@ static bool intel_c20_use_mplla(u32 clock)
return false;
 }
 
+static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+   const struct intel_c20pll_state 
*pll_state)
+{
+   unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
+   unsigned int multiplier, refclk = 38400;
+   unsigned int tx_clk_div;
+   unsigned int ref_clk_mpllb_div;
+   unsigned int fb_clk_div4_en;
+   unsigned int ref, vco;
+   unsigned int tx_rate_mult;
+   unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
+
+   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   tx_rate_mult = 1;
+   frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
+   frac_quot = pll_state->mpllb[8];
+   frac_rem =  pll_state->mpllb[9];
+   frac_den =  pll_state->mpllb[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, 
pll_state->mpllb[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = 0;
+   } else {
+   tx_rate_mult = 2;
+   frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
+   frac_quot = pll_state->mplla[8];
+   frac_rem =  pll_state->mplla[9];
+   frac_den =  pll_state->mplla[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mplla[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, 
pll_state->mplla[1]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mplla[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mplla[0]);
+   }
+
+   if (frac_en)
+   frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den);
+   else
+   frac = 0;
+
+   ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << 
ref_clk_mpllb_div);
+   vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + 
frac) >> 17, 10);
+
+   return vco << tx_rate_mult >> tx_clk_div >> tx_rate;
+}
+
 static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
  struct intel_c20pll_state *pll_state)
 {
@@ -2160,6 +2205,8 @@ static void intel_c20pll_readout_hw_state(struct 
intel_encoder *encoder,
}
}
 
+   pll_state->clock = intel_c20pll_calc_port_clock(encoder, pll_state);
+
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
@@ -2408,51 +2455,6 @@ static int intel_c10pll_calc_port_clock(struct 
intel_encoder *encoder,
return tmpclk;
 }
 
-static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
-   const struct intel_c20pll_state 
*pll_state)
-{
-   unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
-   unsigned int multiplier, refclk = 38400;
-   unsigned int tx_clk_div;
-   unsigned int ref_clk_mpllb_div;
-   unsigned int fb_clk_div4_en;
-   unsigned int ref, vco;
-   unsigned int tx_rate_mult;
-   unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
-
-   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
-   tx_rate_mult = 1;
-   frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
-   frac_quot = pll_state->mpllb[8];
-   frac_rem =  pll_state->mpllb[9];
-   frac_den =  pll_state->mpllb[7];
-   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
-   tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, 
pll_state->mpllb[0]);
-   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
-   fb_clk_div4_en = 0;
-   } else {
-   tx_rate_mult = 2;
-   frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
-   frac_quot = pll_state->mplla[8];
-   frac_rem =  pll_state->

[PATCH v2 1/3] drm/i915/display: Fix C20 pll selection for state verification

2024-01-02 Thread Mika Kahola
Add pll selection check for C20 as well as
clock state verification0. We have been relying
on sw state to select A or B pll's. This is incorrect
as the hw might see this selection differently. This
patch fixes this shortcoming by reading pll selection
for both sw and hw states and compares if these two
selections match.

Fixes: 59be90248b42 ("drm/i915/mtl: C20 state verification")

v2: reword commit message and include fix to a
original commit (Imre)
Compare pll selection (Jani)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 25 
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 884a1da36089..6b25e195232f 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3067,24 +3067,29 @@ static void intel_c20pll_state_verify(const struct 
intel_crtc_state *state,
 {
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct intel_c20pll_state *mpll_sw_state = 
>cx0pll_state.c20;
-   bool use_mplla;
+   bool sw_use_mpllb = mpll_sw_state->tx[0] & C20_PHY_USE_MPLLB;
+   bool hw_use_mpllb = mpll_hw_state->tx[0] & C20_PHY_USE_MPLLB;
int i;
 
-   use_mplla = intel_c20_use_mplla(mpll_hw_state->clock);
-   if (use_mplla) {
-   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
-   I915_STATE_WARN(i915, mpll_hw_state->mplla[i] != 
mpll_sw_state->mplla[i],
-   "[CRTC:%d:%s] mismatch in C20MPLLA: 
Register[%d] (expected 0x%04x, found 0x%04x)",
-   crtc->base.base.id, crtc->base.name, i,
-   mpll_sw_state->mplla[i], 
mpll_hw_state->mplla[i]);
-   }
-   } else {
+   I915_STATE_WARN(i915, sw_use_mpllb != hw_use_mpllb,
+   "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection 
(expected %d, found %d)",
+   crtc->base.base.id, crtc->base.name,
+   sw_use_mpllb, hw_use_mpllb);
+
+   if (hw_use_mpllb) {
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) {
I915_STATE_WARN(i915, mpll_hw_state->mpllb[i] != 
mpll_sw_state->mpllb[i],
"[CRTC:%d:%s] mismatch in C20MPLLB: 
Register[%d] (expected 0x%04x, found 0x%04x)",
crtc->base.base.id, crtc->base.name, i,
mpll_sw_state->mpllb[i], 
mpll_hw_state->mpllb[i]);
}
+   } else {
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state->mplla[i] != 
mpll_sw_state->mplla[i],
+   "[CRTC:%d:%s] mismatch in C20MPLLA: 
Register[%d] (expected 0x%04x, found 0x%04x)",
+   crtc->base.base.id, crtc->base.name, i,
+   mpll_sw_state->mplla[i], 
mpll_hw_state->mplla[i]);
+   }
}
 
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) {
-- 
2.34.1



[PATCH v2 0/3] drm/i915/display: C20 clock state verification

2024-01-02 Thread Mika Kahola
Add pll selection check for C20 as well as
clock state verification0. We have been relying
on sw state to select A or B pll's. This is incorrect
as the hw might see this selection differently. This
patch fixes this shortcoming by reading pll selection
for both sw and hw states and compares if these two
selections match.

While at it, cleanup mpllb selection by removing intel_c20_use_mplla()
function as redundant.

Fixes: 59be90248b42 ("drm/i915/mtl: C20 state verification")

v2: reword commit message and include fix to a
original commit (Imre)
Compare pll selection (Jani)

Signed-off-by: Mika Kahola 

Mika Kahola (3):
  drm/i915/display: Fix C20 pll selection for state verification
  drm/i915/display: Store hw clock for C20
  drm/i915/display: Cleanup mplla/mpllb selection

 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 153 ++-
 1 file changed, 78 insertions(+), 75 deletions(-)

-- 
2.34.1



[PATCH v2 2/3] drm/i915/display: Store hw clock for C20

2023-12-21 Thread Mika Kahola
We can calculate the hw port clock during the hw readout
and store it as pll_state->clock for C20 state verification.
In order to do that we need to move intel_c20pll_calc_port_clock()
function.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 97 +++-
 1 file changed, 52 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 6b25e195232f..fc7211675b2f 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2105,6 +2105,51 @@ static bool intel_c20_use_mplla(u32 clock)
return false;
 }
 
+static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+   const struct intel_c20pll_state 
*pll_state)
+{
+   unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
+   unsigned int multiplier, refclk = 38400;
+   unsigned int tx_clk_div;
+   unsigned int ref_clk_mpllb_div;
+   unsigned int fb_clk_div4_en;
+   unsigned int ref, vco;
+   unsigned int tx_rate_mult;
+   unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
+
+   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   tx_rate_mult = 1;
+   frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
+   frac_quot = pll_state->mpllb[8];
+   frac_rem =  pll_state->mpllb[9];
+   frac_den =  pll_state->mpllb[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, 
pll_state->mpllb[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = 0;
+   } else {
+   tx_rate_mult = 2;
+   frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
+   frac_quot = pll_state->mplla[8];
+   frac_rem =  pll_state->mplla[9];
+   frac_den =  pll_state->mplla[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mplla[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, 
pll_state->mplla[1]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mplla[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mplla[0]);
+   }
+
+   if (frac_en)
+   frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den);
+   else
+   frac = 0;
+
+   ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << 
ref_clk_mpllb_div);
+   vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + 
frac) >> 17, 10);
+
+   return vco << tx_rate_mult >> tx_clk_div >> tx_rate;
+}
+
 static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
  struct intel_c20pll_state *pll_state)
 {
@@ -2160,6 +2205,8 @@ static void intel_c20pll_readout_hw_state(struct 
intel_encoder *encoder,
}
}
 
+   pll_state->clock = intel_c20pll_calc_port_clock(encoder, pll_state);
+
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
@@ -2408,51 +2455,6 @@ static int intel_c10pll_calc_port_clock(struct 
intel_encoder *encoder,
return tmpclk;
 }
 
-static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
-   const struct intel_c20pll_state 
*pll_state)
-{
-   unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
-   unsigned int multiplier, refclk = 38400;
-   unsigned int tx_clk_div;
-   unsigned int ref_clk_mpllb_div;
-   unsigned int fb_clk_div4_en;
-   unsigned int ref, vco;
-   unsigned int tx_rate_mult;
-   unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
-
-   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
-   tx_rate_mult = 1;
-   frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
-   frac_quot = pll_state->mpllb[8];
-   frac_rem =  pll_state->mpllb[9];
-   frac_den =  pll_state->mpllb[7];
-   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
-   tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, 
pll_state->mpllb[0]);
-   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
-   fb_clk_div4_en = 0;
-   } else {
-   tx_rate_mult = 2;
-   frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
-   frac_quot = pll_state->mplla[8];
-   frac_rem =  pll_state->

[PATCH v2 1/3] drm/i915/display: Fix C20 pll selection for state verification

2023-12-21 Thread Mika Kahola
Add pll selection check for C20 as well as
clock state verification0. We have been relying
on sw state to select A or B pll's. This is incorrect
as the hw might see this selection differently. This
patch fixes this shortcoming by reading pll selection
for both sw and hw states and compares if these two
selections match.

Fixes: 59be90248b42 ("drm/i915/mtl: C20 state verification")

v2: reword commit message and include fix to a
original commit (Imre)
Compare pll selection (Jani)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 25 
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 884a1da36089..6b25e195232f 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3067,24 +3067,29 @@ static void intel_c20pll_state_verify(const struct 
intel_crtc_state *state,
 {
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct intel_c20pll_state *mpll_sw_state = 
>cx0pll_state.c20;
-   bool use_mplla;
+   bool sw_use_mpllb = mpll_sw_state->tx[0] & C20_PHY_USE_MPLLB;
+   bool hw_use_mpllb = mpll_hw_state->tx[0] & C20_PHY_USE_MPLLB;
int i;
 
-   use_mplla = intel_c20_use_mplla(mpll_hw_state->clock);
-   if (use_mplla) {
-   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
-   I915_STATE_WARN(i915, mpll_hw_state->mplla[i] != 
mpll_sw_state->mplla[i],
-   "[CRTC:%d:%s] mismatch in C20MPLLA: 
Register[%d] (expected 0x%04x, found 0x%04x)",
-   crtc->base.base.id, crtc->base.name, i,
-   mpll_sw_state->mplla[i], 
mpll_hw_state->mplla[i]);
-   }
-   } else {
+   I915_STATE_WARN(i915, sw_use_mpllb != hw_use_mpllb,
+   "[CRTC:%d:%s] mismatch in C20: Register MPLLB selection 
(expected %d, found %d)",
+   crtc->base.base.id, crtc->base.name,
+   sw_use_mpllb, hw_use_mpllb);
+
+   if (hw_use_mpllb) {
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) {
I915_STATE_WARN(i915, mpll_hw_state->mpllb[i] != 
mpll_sw_state->mpllb[i],
"[CRTC:%d:%s] mismatch in C20MPLLB: 
Register[%d] (expected 0x%04x, found 0x%04x)",
crtc->base.base.id, crtc->base.name, i,
mpll_sw_state->mpllb[i], 
mpll_hw_state->mpllb[i]);
}
+   } else {
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state->mplla[i] != 
mpll_sw_state->mplla[i],
+   "[CRTC:%d:%s] mismatch in C20MPLLA: 
Register[%d] (expected 0x%04x, found 0x%04x)",
+   crtc->base.base.id, crtc->base.name, i,
+   mpll_sw_state->mplla[i], 
mpll_hw_state->mplla[i]);
+   }
}
 
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) {
-- 
2.34.1



[PATCH v2 3/3] drm/i915/display: Cleanup mplla/mpllb selection

2023-12-21 Thread Mika Kahola
The function intel_c20_use_mplla() is not really
widely used and can be replaced with the more suitable

pll->tx[0] & C20_PHY_USE_MPLLB

expression. Let's remove the intel_c20_use_mplla()
alltogether and replace mplla/mpllb selection by
checking mpllb bit.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 39 
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index fc7211675b2f..d0b6b4e439e1 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2096,15 +2096,6 @@ int intel_cx0pll_calc_state(struct intel_crtc_state 
*crtc_state,
return intel_c20pll_calc_state(crtc_state, encoder);
 }
 
-static bool intel_c20_use_mplla(u32 clock)
-{
-   /* 10G and 20G rates use MPLLA */
-   if (clock == 100 || clock == 200)
-   return true;
-
-   return false;
-}
-
 static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
const struct intel_c20pll_state 
*pll_state)
 {
@@ -2221,12 +2212,12 @@ void intel_c20pll_dump_hw_state(struct drm_i915_private 
*i915,
drm_dbg_kms(>drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 
0x%.4x, cmn[3] = 0x%.4x\n",
hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], 
hw_state->cmn[3]);
 
-   if (intel_c20_use_mplla(hw_state->clock)) {
-   for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
-   drm_dbg_kms(>drm, "mplla[%d] = 0x%.4x\n", i, 
hw_state->mplla[i]);
-   } else {
+   if (hw_state->tx[0] & C20_PHY_USE_MPLLB) {
for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
drm_dbg_kms(>drm, "mpllb[%d] = 0x%.4x\n", i, 
hw_state->mpllb[i]);
+   } else {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
+   drm_dbg_kms(>drm, "mplla[%d] = 0x%.4x\n", i, 
hw_state->mplla[i]);
}
 }
 
@@ -2373,27 +2364,27 @@ static void intel_c20_pll_program(struct 
drm_i915_private *i915,
}
 
/* 3.3 mpllb or mplla configuration */
-   if (intel_c20_use_mplla(clock)) {
-   for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
+   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
if (cntx)
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_A_MPLLA_CNTX_CFG(i),
-pll_state->mplla[i]);
+
PHY_C20_A_MPLLB_CNTX_CFG(i),
+pll_state->mpllb[i]);
else
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_B_MPLLA_CNTX_CFG(i),
-pll_state->mplla[i]);
+
PHY_C20_B_MPLLB_CNTX_CFG(i),
+pll_state->mpllb[i]);
}
} else {
-   for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
+   for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
if (cntx)
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_A_MPLLB_CNTX_CFG(i),
-pll_state->mpllb[i]);
+
PHY_C20_A_MPLLA_CNTX_CFG(i),
+pll_state->mplla[i]);
else
intel_c20_sram_write(i915, encoder->port, 
INTEL_CX0_LANE0,
-
PHY_C20_B_MPLLB_CNTX_CFG(i),
-pll_state->mpllb[i]);
+
PHY_C20_B_MPLLA_CNTX_CFG(i),
+pll_state->mplla[i]);
}
}
 
-- 
2.34.1



[PATCH v2 0/3] drm/i915/display: C20 clock state verification

2023-12-21 Thread Mika Kahola
Add pll selection check for C20 as well as
clock state verification0. We have been relying
on sw state to select A or B pll's. This is incorrect
as the hw might see this selection differently. This
patch fixes this shortcoming by reading pll selection
for both sw and hw states and compares if these two
selections match.

While at it, cleanup mpllb selection by removing intel_c20_use_mplla()
function as redundant.

Fixes: 59be90248b42 ("drm/i915/mtl: C20 state verification")

v2: reword commit message and include fix to a
original commit (Imre)
Compare pll selection (Jani)

Signed-off-by: Mika Kahola 

Mika Kahola (3):
  drm/i915/display: Fix C20 pll selection for state verification
  drm/i915/display: Store hw clock for C20
  drm/i915/display: Cleanup mplla/mpllb selection

 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 153 ++-
 1 file changed, 78 insertions(+), 75 deletions(-)

-- 
2.34.1



[PATCH] drm/i915/display: Skip C10 state verification in case of fastset

2023-12-19 Thread Mika Kahola
PLL's are not programmed in case of fastset so the state
verfication compares bios programmed PLL values against
sw PLL values. To overcome this limitation, we can skip
the state verification for C10 in fastset case as the
driver is not writing PLL values.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 884a1da36089..3ef54eaca9e4 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3016,6 +3016,9 @@ static void intel_c10pll_state_verify(const struct 
intel_crtc_state *state,
const struct intel_c10pll_state *mpllb_sw_state = 
>cx0pll_state.c10;
int i;
 
+   if (intel_crtc_needs_fastset(state))
+   return;
+
for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
u8 expected = mpllb_sw_state->pll[i];
 
-- 
2.34.1



[PATCH] drm/i915/display: C20 clock state verification

2023-12-15 Thread Mika Kahola
Add clock state verification for C20. Since we
are usign either A or B contexts, which are
selected based on clock rate, we first need to
calculate hw clock and use that clock to select
which context we are using.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 775c1c4a8978..6757e9f941e4 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3079,8 +3079,9 @@ static void intel_c20pll_state_verify(const struct 
intel_crtc_state *state,
const struct intel_c20pll_state *mpll_sw_state = 
>cx0pll_state.c20;
bool use_mplla;
int i;
+   int hw_clock = intel_c20pll_calc_port_clock(encoder, mpll_hw_state);
 
-   use_mplla = intel_c20_use_mplla(mpll_hw_state->clock);
+   use_mplla = intel_c20_use_mplla(hw_clock);
if (use_mplla) {
for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
I915_STATE_WARN(i915, mpll_hw_state->mplla[i] != 
mpll_sw_state->mplla[i],
@@ -3110,6 +3111,11 @@ static void intel_c20pll_state_verify(const struct 
intel_crtc_state *state,
crtc->base.base.id, crtc->base.name, i,
mpll_sw_state->cmn[i], mpll_hw_state->cmn[i]);
}
+
+   I915_STATE_WARN(i915, hw_clock != mpll_sw_state->clock,
+   "[CRTC:%d:%s] mismatch in C20: Register CLOCK (expected 
%d, found %d)",
+   crtc->base.base.id, crtc->base.name,
+   mpll_sw_state->clock, hw_clock);
 }
 
 void intel_cx0pll_state_verify(struct intel_atomic_state *state,
-- 
2.34.1



[PATCH v2] drm/i915/display: Wait for PHY readiness not needed for disabling sequence

2023-12-12 Thread Mika Kahola
When going through the disconnection flow we don't need to wait for PHY
readiness and hence we can skip the wait part. For disabling the function
returns false as an indicator that the power is not enabled. After all,
we are not even using the return value when Type-C is disconnecting.

v2: Cleanup for increased readibility (Imre)

BSpec: 65380

For VLK-53734

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 25 -
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index f64d348a969e..dcf05e00e505 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -1030,18 +1030,25 @@ static bool xelpdp_tc_phy_enable_tcss_power(struct 
intel_tc_port *tc, bool enabl
 
__xelpdp_tc_phy_enable_tcss_power(tc, enable);
 
-   if ((!tc_phy_wait_for_ready(tc) ||
-!xelpdp_tc_phy_wait_for_tcss_power(tc, enable)) &&
-   !drm_WARN_ON(>drm, tc->mode == TC_PORT_LEGACY)) {
-   if (enable) {
-   __xelpdp_tc_phy_enable_tcss_power(tc, false);
-   xelpdp_tc_phy_wait_for_tcss_power(tc, false);
-   }
+   if (enable && !tc_phy_wait_for_ready(tc))
+   goto out_disable;
 
-   return false;
-   }
+   if (!xelpdp_tc_phy_wait_for_tcss_power(tc, enable))
+   goto out_disable;
 
return true;
+
+out_disable:
+   if (drm_WARN_ON(>drm, tc->mode == TC_PORT_LEGACY))
+   return false;
+
+   if (!enable)
+   return false;
+
+   __xelpdp_tc_phy_enable_tcss_power(tc, false);
+   xelpdp_tc_phy_wait_for_tcss_power(tc, false);
+
+   return false;
 }
 
 static void xelpdp_tc_phy_take_ownership(struct intel_tc_port *tc, bool take)
-- 
2.34.1



[PATCH] drm/i915/display: Wait for PHY readiness not needed for disabling sequence

2023-12-12 Thread Mika Kahola
When going through the disconnection flow we don't need to wait for PHY
readiness and hence we can skip the wait part. For disabling the function
returns false as an indicator that the power is not enabled. After all,
we are not even using the return value when Type-C is disconnecting.

BSpec: 65380

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index f64d348a969e..79ec17fa3edd 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -1030,6 +1030,9 @@ static bool xelpdp_tc_phy_enable_tcss_power(struct 
intel_tc_port *tc, bool enabl
 
__xelpdp_tc_phy_enable_tcss_power(tc, enable);
 
+   if (!enable)
+   return false;
+
if ((!tc_phy_wait_for_ready(tc) ||
 !xelpdp_tc_phy_wait_for_tcss_power(tc, enable)) &&
!drm_WARN_ON(>drm, tc->mode == TC_PORT_LEGACY)) {
-- 
2.34.1



[Intel-gfx] [PATCH 3/3] drm/i915/display: Print out debug messages for clock rates

2023-12-04 Thread Mika Kahola
Print out clock rate for C10 chip and clock rate and link bitrate
for C20 chip for debugging purposes.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 02efe2786c6a..647e00bac9c3 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -1942,8 +1942,9 @@ void intel_c10pll_dump_hw_state(struct drm_i915_private 
*i915,
unsigned int multiplier, tx_clk_div;
 
fracen = hw_state->pll[0] & C10_PLL0_FRACEN;
-   drm_dbg_kms(>drm, "c10pll_hw_state: fracen: %s, ",
-   str_yes_no(fracen));
+   drm_dbg_kms(>drm, "c10pll_hw_state:\n");
+   drm_dbg_kms(>drm, "clock: %d\n", hw_state->clock);
+   drm_dbg_kms(>drm, "fracen: %s, ", str_yes_no(fracen));
 
if (fracen) {
frac_quot = hw_state->pll[12] << 8 | hw_state->pll[11];
@@ -2131,6 +2132,8 @@ void intel_c20pll_dump_hw_state(struct drm_i915_private 
*i915,
int i;
 
drm_dbg_kms(>drm, "c20pll_hw_state:\n");
+   drm_dbg_kms(>drm, "link bitrate: %d\n", hw_state->link_bit_rate);
+   drm_dbg_kms(>drm, "clock: %d\n", hw_state->clock);
drm_dbg_kms(>drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 
0x%.4x\n",
hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
drm_dbg_kms(>drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 
0x%.4x, cmn[3] = 0x%.4x\n",
-- 
2.34.1



[Intel-gfx] [PATCH 2/3] drm/i915/display: Convert link bitrate to corresponding PLL clock

2023-12-04 Thread Mika Kahola
Compute clock during PLL readout. This prevents warn when only c20 phy
is connected during modprobe. The intel_c20pll_calc_port_clock()
function returns link bitrate which in DP2.0 and HDMI cases does not match
with the clock rate. Hence, conversion function is needed to convert
link bitrate to corresponding PLL clock rate.

while at it, update clock on C10 pll state as well.

Signed-off-by: Clint Taylor 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 38 ++--
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  1 +
 drivers/gpu/drm/i915/display/intel_ddi.c |  2 +-
 3 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 2e6412fc2258..02efe2786c6a 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -1871,6 +1871,7 @@ static int intel_c10pll_calc_state(struct 
intel_crtc_state *crtc_state,
 }
 
 static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state,
  struct intel_c10pll_state *pll_state)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
@@ -1894,6 +1895,7 @@ static void intel_c10pll_readout_hw_state(struct 
intel_encoder *encoder,
 
pll_state->cmn = intel_cx0_read(i915, encoder->port, lane, 
PHY_C10_VDR_CMN(0));
pll_state->tx = intel_cx0_read(i915, encoder->port, lane, 
PHY_C10_VDR_TX(0));
+   pll_state->clock = crtc_state->port_clock;
 
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
@@ -2445,12 +2447,33 @@ static void intel_program_port_clock_ctl(struct 
intel_encoder *encoder,
 XELPDP_SSC_ENABLE_PLLB, val);
 }
 
+static int intel_link_bitrate_to_clock(struct intel_encoder *encoder,
+  struct intel_crtc_state *crtc_state,
+  int link_bit_rate)
+{
+   const struct intel_c20pll_state * const *tables;
+   int i;
+
+   tables = intel_c20_pll_tables_get(crtc_state, encoder);
+   if (!tables)
+   return -EINVAL;
+
+   for (i = 0; tables[i]; i++) {
+   if (link_bit_rate == tables[i]->link_bit_rate)
+   return tables[i]->clock;
+   }
+
+   return -EINVAL;
+}
+
 static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state,
  struct intel_c20pll_state *pll_state)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
bool cntx;
intel_wakeref_t wakeref;
+   int clock;
int i;
 
wakeref = intel_cx0_phy_transaction_begin(encoder);
@@ -2500,6 +2523,13 @@ static void intel_c20pll_readout_hw_state(struct 
intel_encoder *encoder,
}
}
 
+   pll_state->link_bit_rate = intel_c20pll_calc_port_clock(encoder, 
pll_state);
+   clock = intel_link_bitrate_to_clock(encoder, crtc_state,
+   pll_state->link_bit_rate);
+
+   if (clock >= 0)
+   pll_state->clock = clock;
+
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
@@ -3053,15 +3083,16 @@ static void intel_c10pll_state_verify(const struct 
intel_crtc_state *state,
 }
 
 void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
+  struct intel_crtc_state *crtc_state,
   struct intel_cx0pll_state *pll_state)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
 
if (intel_is_c10phy(i915, phy))
-   intel_c10pll_readout_hw_state(encoder, _state->c10);
+   intel_c10pll_readout_hw_state(encoder, crtc_state, 
_state->c10);
else
-   intel_c20pll_readout_hw_state(encoder, _state->c20);
+   intel_c20pll_readout_hw_state(encoder, crtc_state, 
_state->c20);
 }
 
 int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder,
@@ -3145,7 +3176,8 @@ void intel_cx0pll_state_verify(struct intel_atomic_state 
*state,
if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
return;
 
-   intel_cx0pll_readout_hw_state(encoder, _hw_state);
+   intel_cx0pll_readout_hw_state(encoder, (struct 
intel_crtc_state*)new_crtc_state,
+ _hw_state);
 
if (intel_is_c10phy(i915, phy))
intel_c10pll_state_verify(new_crtc_state, crtc, encoder, 
_hw_state.c10);
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index c6682677253a..eac7354e9a4e 100644
--- a/dr

[Intel-gfx] [PATCH 1/3] drm/i915/display: Move C20 HW readout

2023-12-04 Thread Mika Kahola
Moving intel_c20pll_readout_hw_state() for better place
to better suit for upcoming changes.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 116 +--
 1 file changed, 58 insertions(+), 58 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 5fbec5784b83..2e6412fc2258 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2123,64 +2123,6 @@ static bool intel_c20_use_mplla(u32 clock)
return false;
 }
 
-static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
- struct intel_c20pll_state *pll_state)
-{
-   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
-   bool cntx;
-   intel_wakeref_t wakeref;
-   int i;
-
-   wakeref = intel_cx0_phy_transaction_begin(encoder);
-
-   /* 1. Read current context selection */
-   cntx = intel_cx0_read(i915, encoder->port, INTEL_CX0_LANE0, 
PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE;
-
-   /* Read Tx configuration */
-   for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) {
-   if (cntx)
-   pll_state->tx[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
-  
PHY_C20_B_TX_CNTX_CFG(i));
-   else
-   pll_state->tx[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
-  
PHY_C20_A_TX_CNTX_CFG(i));
-   }
-
-   /* Read common configuration */
-   for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) {
-   if (cntx)
-   pll_state->cmn[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
-   
PHY_C20_B_CMN_CNTX_CFG(i));
-   else
-   pll_state->cmn[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
-   
PHY_C20_A_CMN_CNTX_CFG(i));
-   }
-
-   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
-   /* MPLLB configuration */
-   for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) {
-   if (cntx)
-   pll_state->mpllb[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
- 
PHY_C20_B_MPLLB_CNTX_CFG(i));
-   else
-   pll_state->mpllb[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
- 
PHY_C20_A_MPLLB_CNTX_CFG(i));
-   }
-   } else {
-   /* MPLLA configuration */
-   for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) {
-   if (cntx)
-   pll_state->mplla[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
- 
PHY_C20_B_MPLLA_CNTX_CFG(i));
-   else
-   pll_state->mplla[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
- 
PHY_C20_A_MPLLA_CNTX_CFG(i));
-   }
-   }
-
-   intel_cx0_phy_transaction_end(encoder, wakeref);
-}
-
 void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
const struct intel_c20pll_state *hw_state)
 {
@@ -2503,6 +2445,64 @@ static void intel_program_port_clock_ctl(struct 
intel_encoder *encoder,
 XELPDP_SSC_ENABLE_PLLB, val);
 }
 
+static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
+ struct intel_c20pll_state *pll_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   bool cntx;
+   intel_wakeref_t wakeref;
+   int i;
+
+   wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+   /* 1. Read current context selection */
+   cntx = intel_cx0_read(i915, encoder->port, INTEL_CX0_LANE0, 
PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE;
+
+   /* Read Tx configuration */
+   for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) {
+   if (cntx)
+   pll_state->tx[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
+  
PHY_C20_B_TX_CNTX_CFG(i));
+   else
+   pll_state->tx[i] = intel_c20_sram_read(i915, 
encoder->port, INTEL_CX0_LANE0,
+

[Intel-gfx] [PATCH 0/3] drm/i915/display: Convert link bitrate to clock

2023-12-04 Thread Mika Kahola
While reading HW state for C10 and C20 chips, let's update the PLL
clock rates. For C20 the clock rate differs from link bit rate on
DP2.0 cases and hence a conversion from link bitrate to clock is
needed.

Signed-off-by: Mika Kahola 

Mika Kahola (3):
  drm/i915/display: Move C20 HW readout
  drm/i915/display: Convert link bitrate to corresponding PLL clock
  drm/i915/display: Print out debug messages for clock rates

 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 161 +++
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   1 +
 drivers/gpu/drm/i915/display/intel_ddi.c |   2 +-
 3 files changed, 100 insertions(+), 64 deletions(-)

-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/display: Skip state verification with TBT-ALT mode

2023-11-29 Thread Mika Kahola
With TBT-ALT mode we are not programming C20 chip PLL's and
hence we don't need to check state verification. We don't
need to program DP link signal levels i.e.pre-emphasis and
voltage swing either.

This patch fixes dmesg errors like this one

"[drm] ERROR PHY F Write 0c06 failed after 3 retries."

Signed-off-by: Mika Kahola 
Reviewed-by: Gustavo Sousa 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index a8fa76580802..5fbec5784b83 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -415,9 +415,15 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder 
*encoder,
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
const struct intel_ddi_buf_trans *trans;
enum phy phy = intel_port_to_phy(i915, encoder->port);
-   u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
+   u8 owned_lane_mask;
intel_wakeref_t wakeref;
int n_entries, ln;
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+   if (intel_tc_port_in_tbt_alt_mode(dig_port))
+   return;
+
+   owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
 
wakeref = intel_cx0_phy_transaction_begin(encoder);
 
@@ -3136,6 +3142,9 @@ void intel_cx0pll_state_verify(struct intel_atomic_state 
*state,
encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
phy = intel_port_to_phy(i915, encoder->port);
 
+   if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
+   return;
+
intel_cx0pll_readout_hw_state(encoder, _hw_state);
 
if (intel_is_c10phy(i915, phy))
-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/display: Skip state verification with TBT-ALT mode

2023-11-27 Thread Mika Kahola
With TBT-ALT mode we are not programming C20 chip PLL's and
hence we don't need to check state verification. We don't
need to program DP link signal levels i.e.pre-emphasis and
voltage swing either.

This patch fixes dmesg errors like this one

"[drm] ERROR PHY F Write 0c06 failed after 3 retries."

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index a8fa76580802..3a30cffd450c 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -418,6 +418,10 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder 
*encoder,
u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder);
intel_wakeref_t wakeref;
int n_entries, ln;
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+   if (intel_tc_port_in_tbt_alt_mode(dig_port))
+   return;
 
wakeref = intel_cx0_phy_transaction_begin(encoder);
 
@@ -3136,6 +3140,9 @@ void intel_cx0pll_state_verify(struct intel_atomic_state 
*state,
encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
phy = intel_port_to_phy(i915, encoder->port);
 
+   if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
+   return;
+
intel_cx0pll_readout_hw_state(encoder, _hw_state);
 
if (intel_is_c10phy(i915, phy))
-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/display: Use int type for entry_setup_frames

2023-11-16 Thread Mika Kahola
entry_setup_frames variable is defined as u8. However, the
function call intel_psr_entry_setup_frames() can return
negative error code. There is a type mismatch here, so let's
switch to use int here as well.

Fixes: 2b981d57e480 ("drm/i915/display: Support PSR entry VSC packet to be 
transmitted one frame earlier")

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 8d180132a74b..204da50e3f28 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1319,7 +1319,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
const struct drm_display_mode *adjusted_mode = 
_state->hw.adjusted_mode;
-   u8 entry_setup_frames;
+   int entry_setup_frames;
 
/*
 * Current PSR panels don't work reliably with VRR enabled
-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/mtl: Use int for entry setup frames

2023-11-13 Thread Mika Kahola
At least one TGL had regression when using u8 types
for entry setup frames calculation. So, let's switch
to use ints instead.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 3691f882e1c0..a4417e85f92a 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1093,12 +1093,12 @@ static bool _compute_psr2_wake_times(struct intel_dp 
*intel_dp,
return true;
 }
 
-static u8 intel_psr_entry_setup_frames(struct intel_dp *intel_dp,
-  const struct drm_display_mode 
*adjusted_mode)
+static int intel_psr_entry_setup_frames(struct intel_dp *intel_dp,
+   const struct drm_display_mode 
*adjusted_mode)
 {
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
int psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
-   u8 entry_setup_frames = 0;
+   int entry_setup_frames = 0;
 
if (psr_setup_time < 0) {
drm_dbg_kms(>drm,
-- 
2.34.1



[Intel-gfx] [PATCH v2] drm/i915/mtl: C20 state verification

2023-11-09 Thread Mika Kahola
Add state verification for C20 as we have one
for C10.

V2: Use abstractation of HW readout (Gustavo)
Drop MPLLA/B from message for TX and CMN
parameters (Gustavo)

Reviewed-by: Gustavo Sousa  (v1)
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 120 +-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   2 +-
 .../drm/i915/display/intel_modeset_verify.c   |   2 +-
 3 files changed, 88 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index b2ad4c6172f6..a8fa76580802 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3017,55 +3017,33 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder,
return ICL_PORT_DPLL_DEFAULT;
 }
 
-void intel_c10pll_state_verify(struct intel_atomic_state *state,
-  struct intel_crtc *crtc)
+static void intel_c10pll_state_verify(const struct intel_crtc_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder,
+ struct intel_c10pll_state *mpllb_hw_state)
 {
-   struct drm_i915_private *i915 = to_i915(state->base.dev);
-   const struct intel_crtc_state *new_crtc_state =
-   intel_atomic_get_new_crtc_state(state, crtc);
-   struct intel_c10pll_state mpllb_hw_state = {};
-   const struct intel_c10pll_state *mpllb_sw_state = 
_crtc_state->cx0pll_state.c10;
-   struct intel_encoder *encoder;
-   enum phy phy;
+   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+   const struct intel_c10pll_state *mpllb_sw_state = 
>cx0pll_state.c10;
int i;
 
-   if (DISPLAY_VER(i915) < 14)
-   return;
-
-   if (!new_crtc_state->hw.active)
-   return;
-
-   /* intel_get_crtc_new_encoder() only works for modeset/fastset commits 
*/
-   if (!intel_crtc_needs_modeset(new_crtc_state) &&
-   !intel_crtc_needs_fastset(new_crtc_state))
-   return;
-
-   encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
-   phy = intel_port_to_phy(i915, encoder->port);
-
-   if (!intel_is_c10phy(i915, phy))
-   return;
-
-   intel_c10pll_readout_hw_state(encoder, _hw_state);
-
for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
u8 expected = mpllb_sw_state->pll[i];
 
-   I915_STATE_WARN(i915, mpllb_hw_state.pll[i] != expected,
+   I915_STATE_WARN(i915, mpllb_hw_state->pll[i] != expected,
"[CRTC:%d:%s] mismatch in C10MPLLB: 
Register[%d] (expected 0x%02x, found 0x%02x)",
crtc->base.base.id, crtc->base.name, i,
-   expected, mpllb_hw_state.pll[i]);
+   expected, mpllb_hw_state->pll[i]);
}
 
-   I915_STATE_WARN(i915, mpllb_hw_state.tx != mpllb_sw_state->tx,
+   I915_STATE_WARN(i915, mpllb_hw_state->tx != mpllb_sw_state->tx,
"[CRTC:%d:%s] mismatch in C10MPLLB: Register TX0 
(expected 0x%02x, found 0x%02x)",
crtc->base.base.id, crtc->base.name,
-   mpllb_sw_state->tx, mpllb_hw_state.tx);
+   mpllb_sw_state->tx, mpllb_hw_state->tx);
 
-   I915_STATE_WARN(i915, mpllb_hw_state.cmn != mpllb_sw_state->cmn,
+   I915_STATE_WARN(i915, mpllb_hw_state->cmn != mpllb_sw_state->cmn,
"[CRTC:%d:%s] mismatch in C10MPLLB: Register CMN0 
(expected 0x%02x, found 0x%02x)",
crtc->base.base.id, crtc->base.name,
-   mpllb_sw_state->cmn, mpllb_hw_state.cmn);
+   mpllb_sw_state->cmn, mpllb_hw_state->cmn);
 }
 
 void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder,
@@ -3091,3 +3069,77 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder 
*encoder,
 
return intel_c20pll_calc_port_clock(encoder, _state->c20);
 }
+
+static void intel_c20pll_state_verify(const struct intel_crtc_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder,
+ struct intel_c20pll_state *mpll_hw_state)
+{
+   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+   const struct intel_c20pll_state *mpll_sw_state = 
>cx0pll_state.c20;
+   bool use_mplla;
+   int i;
+
+   use_mplla = intel_c20_use_mplla(mpll_hw_state->clock);
+   if (use_mplla) {
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state->mplla

[Intel-gfx] [PATCH v4] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier

2023-11-06 Thread Mika Kahola
Display driver shall read DPCD 00071h[3:1] during configuration
to get PSR setup time. This register provides the setup time
requirement on the VSC SDP entry packet. If setup time cannot be
met with the current timings
(e.g., PSR setup time + other blanking requirements > blanking time),
driver should enable sending VSC SDP one frame earlier before sending
the capture frame.

BSpec: 69895 (PSR Entry Setup Frames 17:16)

v2: Write frames before su entry to correct register (Ville, Jouni)
Move frames before su entry calculation to it's
own function (Ville, Jouni)
Rename PSR Entry Setup Frames register to indicate
Lunarlake specificity (Jouni)
v3: Modify setup entry frames calculation function to
return the actual frames (Ville)
Match comment with actual implementation (Jouni)
v4: Drop "set" from function naming (Jouni, Ville)
Use i915 instead of dev_priv (Jouni)

Signed-off-by: Mika Kahola 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 82 +++
 drivers/gpu/drm/i915/display/intel_psr_regs.h |  2 +
 3 files changed, 71 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 047fe3f8905a..92f06d67fd1e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1708,6 +1708,7 @@ struct intel_psr {
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
+   u8 entry_setup_frames;
 };
 
 struct intel_dp {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 920f77336163..fc242916349b 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -593,6 +593,9 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE;
 
+   if (intel_dp->psr.entry_setup_frames > 0)
+   dpcd_val |= DP_PSR_FRAME_CAPTURE;
+
drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, dpcd_val);
 
drm_dp_dpcd_writeb(_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
@@ -691,6 +694,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 8)
val |= EDP_PSR_CRC_ENABLE;
 
+   if (DISPLAY_VER(dev_priv) >= 20)
+   val |= 
LNL_EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
intel_de_rmw(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder),
 ~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val);
 }
@@ -728,11 +734,27 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static u8 frames_before_su_entry(struct intel_dp *intel_dp)
+{
+   u8 frames_before_su_entry;
+
+   frames_before_su_entry = max_t(u8,
+  intel_dp->psr.sink_sync_latency + 1,
+  2);
+
+   /* Entry setup frames must be at least 1 less than frames before SU 
entry */
+   if (intel_dp->psr.entry_setup_frames >= frames_before_su_entry)
+   frames_before_su_entry = intel_dp->psr.entry_setup_frames + 1;
+
+   return frames_before_su_entry;
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
+   u32 psr_val = 0;
 
val |= EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
 
@@ -742,7 +764,8 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12)
val |= EDP_Y_COORDINATE_ENABLE;
 
-   val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, 
intel_dp->psr.sink_sync_latency + 1, 2));
+   val |= EDP_PSR2_FRAME_BEFORE_SU(frames_before_su_entry(intel_dp));
+
val |= intel_psr2_get_tp_time(intel_dp);
 
if (DISPLAY_VER(dev_priv) >= 12) {
@@ -786,6 +809,9 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
val |= EDP_PSR2_SU_SDP_SCANLINE;
 
+   if (DISPLAY_VER(dev_priv) >= 20)
+   psr_val |= 
LNL_EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
if (intel_dp->psr.psr2_sel_fetch_enabled) {
u32 tmp;
 
@@ -799,7 +825,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is
 * recommending keep this bit unset while PSR2 is enabled.
 */
-   intel_de_write(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), 

[Intel-gfx] [PATCH v2] drm/i915/mtl: C20 state verification

2023-11-06 Thread Mika Kahola
Add state verification for C20 as we have one
for C10.

v2: use register values as u32 instead of u8

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 107 ++
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   2 +-
 .../drm/i915/display/intel_modeset_verify.c   |   2 +-
 3 files changed, 84 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index b2ad4c6172f6..87329bd2272a 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3017,35 +3017,15 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder,
return ICL_PORT_DPLL_DEFAULT;
 }
 
-void intel_c10pll_state_verify(struct intel_atomic_state *state,
-  struct intel_crtc *crtc)
+static void intel_c10pll_state_verify(const struct intel_crtc_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
 {
-   struct drm_i915_private *i915 = to_i915(state->base.dev);
-   const struct intel_crtc_state *new_crtc_state =
-   intel_atomic_get_new_crtc_state(state, crtc);
+   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_c10pll_state mpllb_hw_state = {};
-   const struct intel_c10pll_state *mpllb_sw_state = 
_crtc_state->cx0pll_state.c10;
-   struct intel_encoder *encoder;
-   enum phy phy;
+   const struct intel_c10pll_state *mpllb_sw_state = 
>cx0pll_state.c10;
int i;
 
-   if (DISPLAY_VER(i915) < 14)
-   return;
-
-   if (!new_crtc_state->hw.active)
-   return;
-
-   /* intel_get_crtc_new_encoder() only works for modeset/fastset commits 
*/
-   if (!intel_crtc_needs_modeset(new_crtc_state) &&
-   !intel_crtc_needs_fastset(new_crtc_state))
-   return;
-
-   encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
-   phy = intel_port_to_phy(i915, encoder->port);
-
-   if (!intel_is_c10phy(i915, phy))
-   return;
-
intel_c10pll_readout_hw_state(encoder, _hw_state);
 
for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
@@ -3091,3 +3071,80 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder 
*encoder,
 
return intel_c20pll_calc_port_clock(encoder, _state->c20);
 }
+
+static void intel_c20pll_state_verify(const struct intel_crtc_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+   struct intel_c20pll_state mpll_hw_state = {};
+   const struct intel_c20pll_state *mpll_sw_state = 
>cx0pll_state.c20;
+   bool use_mplla;
+   int i;
+
+   intel_c20pll_readout_hw_state(encoder, _hw_state);
+
+   use_mplla = intel_c20_use_mplla(mpll_hw_state.clock);
+   if (use_mplla) {
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state.mplla[i] != 
mpll_sw_state->mplla[i],
+   "[CRTC:%d:%s] mismatch in C20MPLLA: 
Register[%d] (expected 0x%04x, found 0x%04x)",
+   crtc->base.base.id, crtc->base.name, i,
+   mpll_sw_state->mplla[i], 
mpll_hw_state.mplla[i]);
+   }
+   } else {
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state.mpllb[i] != 
mpll_sw_state->mpllb[i],
+   "[CRTC:%d:%s] mismatch in C20MPLLB: 
Register[%d] (expected 0x%04x, found 0x%04x)",
+   crtc->base.base.id, crtc->base.name, i,
+   mpll_sw_state->mpllb[i], 
mpll_hw_state.mpllb[i]);
+   }
+   }
+
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state.tx[i] != 
mpll_sw_state->tx[i],
+   "[CRTC:%d:%s] mismatch in C20MPLL%s: Register 
TX[%i] (expected 0x%04x, found 0x%04x)",
+   crtc->base.base.id, crtc->base.name,
+   use_mplla ? "A" : "B",
+   i,
+   mpll_sw_state->tx[i], mpll_hw_state.tx[i]);
+   }
+
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->cmn); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state.cmn[i] != 
mpll_sw_state->cmn[i],
+   "[CRTC:%d:%s] mismatch in C20MPLL%s: Register 
CMN[%i] (expected 0x%04x, found 0x%04

[Intel-gfx] [PATCH v3] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier

2023-11-03 Thread Mika Kahola
Display driver shall read DPCD 00071h[3:1] during configuration
to get PSR setup time. This register provides the setup time
requirement on the VSC SDP entry packet. If setup time cannot be
met with the current timings
(e.g., PSR setup time + other blanking requirements > blanking time),
driver should enable sending VSC SDP one frame earlier before sending
the capture frame.

BSpec: 69895 (PSR Entry Setup Frames 17:16)

v2: Write frames before su entry to correct register (Ville, Jouni)
Move frames before su entry calculation to it's
own function (Ville, Jouni)
Rename PSR Entry Setup Frames register to indicate
Lunarlake specificity (Jouni)
v3: Modify setup entry frames calculation function to
return the actual frames (Ville)
Match comment with actual implementation (Jouni)

Signed-off-by: Mika Kahola 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 82 +++
 drivers/gpu/drm/i915/display/intel_psr_regs.h |  2 +
 3 files changed, 71 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 047fe3f8905a..92f06d67fd1e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1708,6 +1708,7 @@ struct intel_psr {
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
+   u8 entry_setup_frames;
 };
 
 struct intel_dp {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index ecd24a0b86cb..497e4c26f4a6 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -592,6 +592,9 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE;
 
+   if (intel_dp->psr.entry_setup_frames > 0)
+   dpcd_val |= DP_PSR_FRAME_CAPTURE;
+
drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, dpcd_val);
 
drm_dp_dpcd_writeb(_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
@@ -690,6 +693,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 8)
val |= EDP_PSR_CRC_ENABLE;
 
+   if (DISPLAY_VER(dev_priv) >= 20)
+   val |= 
LNL_EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
intel_de_rmw(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder),
 ~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val);
 }
@@ -727,11 +733,27 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static u8 get_frames_before_su_entry(struct intel_dp *intel_dp)
+{
+   u8 frames_before_su_entry;
+
+   frames_before_su_entry = max_t(u8,
+  intel_dp->psr.sink_sync_latency + 1,
+  2);
+
+   /* Entry setup frames must be at least 1 less than frames before SU 
entry */
+   if (intel_dp->psr.entry_setup_frames >= frames_before_su_entry)
+   frames_before_su_entry = intel_dp->psr.entry_setup_frames + 1;
+
+   return frames_before_su_entry;
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
+   u32 psr_val = 0;
 
val |= EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
 
@@ -741,7 +763,8 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12)
val |= EDP_Y_COORDINATE_ENABLE;
 
-   val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, 
intel_dp->psr.sink_sync_latency + 1, 2));
+   val |= EDP_PSR2_FRAME_BEFORE_SU(get_frames_before_su_entry(intel_dp));
+
val |= intel_psr2_get_tp_time(intel_dp);
 
if (DISPLAY_VER(dev_priv) >= 12) {
@@ -785,6 +808,9 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
val |= EDP_PSR2_SU_SDP_SCANLINE;
 
+   if (DISPLAY_VER(dev_priv) >= 20)
+   psr_val |= 
LNL_EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
if (intel_dp->psr.psr2_sel_fetch_enabled) {
u32 tmp;
 
@@ -798,7 +824,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is
 * recommending keep this bit unset while PSR2 is enabled.
 */
-   intel_de_write(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), 0);
+   intel_de_write(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), 
psr_

[Intel-gfx] [PATCH] drm/i915/mtl: C20 state verification

2023-11-01 Thread Mika Kahola
Add state verification for C20 as we have one
for C10.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 111 ++
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   2 +-
 .../drm/i915/display/intel_modeset_verify.c   |   2 +-
 3 files changed, 88 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index b2ad4c6172f6..654e91deb7e8 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -3017,35 +3017,15 @@ intel_mtl_port_pll_type(struct intel_encoder *encoder,
return ICL_PORT_DPLL_DEFAULT;
 }
 
-void intel_c10pll_state_verify(struct intel_atomic_state *state,
-  struct intel_crtc *crtc)
+static void intel_c10pll_state_verify(const struct intel_crtc_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
 {
-   struct drm_i915_private *i915 = to_i915(state->base.dev);
-   const struct intel_crtc_state *new_crtc_state =
-   intel_atomic_get_new_crtc_state(state, crtc);
+   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_c10pll_state mpllb_hw_state = {};
-   const struct intel_c10pll_state *mpllb_sw_state = 
_crtc_state->cx0pll_state.c10;
-   struct intel_encoder *encoder;
-   enum phy phy;
+   const struct intel_c10pll_state *mpllb_sw_state = 
>cx0pll_state.c10;
int i;
 
-   if (DISPLAY_VER(i915) < 14)
-   return;
-
-   if (!new_crtc_state->hw.active)
-   return;
-
-   /* intel_get_crtc_new_encoder() only works for modeset/fastset commits 
*/
-   if (!intel_crtc_needs_modeset(new_crtc_state) &&
-   !intel_crtc_needs_fastset(new_crtc_state))
-   return;
-
-   encoder = intel_get_crtc_new_encoder(state, new_crtc_state);
-   phy = intel_port_to_phy(i915, encoder->port);
-
-   if (!intel_is_c10phy(i915, phy))
-   return;
-
intel_c10pll_readout_hw_state(encoder, _hw_state);
 
for (i = 0; i < ARRAY_SIZE(mpllb_sw_state->pll); i++) {
@@ -3091,3 +3071,84 @@ int intel_cx0pll_calc_port_clock(struct intel_encoder 
*encoder,
 
return intel_c20pll_calc_port_clock(encoder, _state->c20);
 }
+
+static void intel_c20pll_state_verify(const struct intel_crtc_state *state,
+ struct intel_crtc *crtc,
+ struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+   struct intel_c20pll_state mpll_hw_state = {};
+   const struct intel_c20pll_state *mpll_sw_state = 
>cx0pll_state.c20;
+   bool use_mplla;
+   int i;
+
+   intel_c20pll_readout_hw_state(encoder, _hw_state);
+
+   use_mplla = intel_c20_use_mplla(mpll_hw_state.clock);
+   if (use_mplla) {
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mplla); i++) {
+   u8 expected = mpll_sw_state->mplla[i];
+
+   I915_STATE_WARN(i915, mpll_hw_state.mplla[i] != 
expected,
+   "[CRTC:%d:%s] mismatch in C20MPLLA: 
Register[%d] (expected 0x%02x, found 0x%02x)",
+   crtc->base.base.id, crtc->base.name, i,
+   expected, mpll_hw_state.mplla[i]);
+   }
+   } else {
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->mpllb); i++) {
+   u8 expected = mpll_sw_state->mpllb[i];
+
+   I915_STATE_WARN(i915, mpll_hw_state.mpllb[i] != 
expected,
+   "[CRTC:%d:%s] mismatch in C20MPLLB: 
Register[%d] (expected 0x%02x, found 0x%02x)",
+   crtc->base.base.id, crtc->base.name, i,
+   expected, mpll_hw_state.mpllb[i]);
+   }
+   }
+
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->tx); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state.tx[i] != 
mpll_sw_state->tx[i],
+   "[CRTC:%d:%s] mismatch in C20MPLL%s: Register 
TX[%i] (expected 0x%02x, found 0x%02x)",
+   crtc->base.base.id, crtc->base.name,
+   use_mplla ? "A" : "B",
+   i,
+   mpll_sw_state->tx[i], mpll_hw_state.tx[i]);
+   }
+
+   for (i = 0; i < ARRAY_SIZE(mpll_sw_state->cmn); i++) {
+   I915_STATE_WARN(i915, mpll_hw_state.cmn[i] != 
mpll_sw_state->cmn[i],
+   "[CRTC:%d:%s] mismatch in C20MPLL%s: Register 
CMN[%i]

[Intel-gfx] [PATCH] drm/i915/mtl: Clear possible sticky bits on PICA message bus

2023-11-01 Thread Mika Kahola
It is possible that sticky bits or error bits are left on
message bus status register. Reading and then writing the
value back to messagebus status register clears all possible
sticky bits and errors.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index b2ad4c6172f6..f439f0c7b400 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -195,6 +195,13 @@ static int __intel_cx0_read_once(struct drm_i915_private 
*i915, enum port port,
return -ETIMEDOUT;
}
 
+   /*
+* write XELPDP_PORT_P2M_MSGBUS_STATUS register after read to clear
+* any error sticky bits set from previous transactions
+*/
+   val = intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane));
+   intel_de_write(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane), val);
+
intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
   XELPDP_PORT_M2P_TRANSACTION_PENDING |
   XELPDP_PORT_M2P_COMMAND_READ |
@@ -262,6 +269,13 @@ static int __intel_cx0_write_once(struct drm_i915_private 
*i915, enum port port,
return -ETIMEDOUT;
}
 
+   /*
+* write XELPDP_PORT_P2M_MSGBUS_STATUS register after read to clear
+* any error sticky bits set from previous transactions
+*/
+   val = intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane));
+   intel_de_write(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane), val);
+
intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane),
   XELPDP_PORT_M2P_TRANSACTION_PENDING |
   (committed ? XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED :
-- 
2.34.1



[Intel-gfx] [PATCH v2] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier

2023-11-01 Thread Mika Kahola
Display driver shall read DPCD 00071h[3:1] during configuration
to get PSR setup time. This register provides the setup time
requirement on the VSC SDP entry packet. If setup time cannot be
met with the current timings
(e.g., PSR setup time + other blanking requirements > blanking time),
driver should enable sending VSC SDP one frame earlier before sending
the capture frame.

BSpec: 69895 (PSR Entry Setup Frames 17:16)

v2: Write frames before su entry to correct register (Ville, Jouni)
Move frames before su entry calculation to it's own function (Ville, Jouni)
Rename PSR Entry Setup Frames register to indicate Lunarlake specificity 
(Jouni)

Signed-off-by: Mika Kahola 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 77 ++-
 drivers/gpu/drm/i915/display/intel_psr_regs.h |  2 +
 3 files changed, 62 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 65ea37fe8cff..a0bcab6f2bec 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1710,6 +1710,7 @@ struct intel_psr {
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
+   u8 entry_setup_frames;
 };
 
 struct intel_dp {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index ecd24a0b86cb..c9e6651fb3b2 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -592,6 +592,9 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE;
 
+   if (intel_dp->psr.entry_setup_frames > 0)
+   dpcd_val |= DP_PSR_FRAME_CAPTURE;
+
drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, dpcd_val);
 
drm_dp_dpcd_writeb(_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
@@ -690,6 +693,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 8)
val |= EDP_PSR_CRC_ENABLE;
 
+   if (DISPLAY_VER(dev_priv) >= 20)
+   val |= 
LNL_EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
intel_de_rmw(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder),
 ~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val);
 }
@@ -727,11 +733,27 @@ static int psr2_block_count(struct intel_dp *intel_dp)
return psr2_block_count_lines(intel_dp) / 4;
 }
 
+static u8 get_frames_before_su_entry(struct intel_dp *intel_dp)
+{
+   u8 frames_before_su_entry;
+
+   frames_before_su_entry = max_t(u8,
+  intel_dp->psr.sink_sync_latency + 1,
+  2);
+
+   /* Entry setup frames must be at least 1 less than frames before SU 
entry */
+   if (intel_dp->psr.entry_setup_frames >= frames_before_su_entry)
+   frames_before_su_entry += 1;
+
+   return frames_before_su_entry;
+}
+
 static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 val = EDP_PSR2_ENABLE;
+   u32 psr_val = 0;
 
val |= EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
 
@@ -741,7 +763,8 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12)
val |= EDP_Y_COORDINATE_ENABLE;
 
-   val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, 
intel_dp->psr.sink_sync_latency + 1, 2));
+   val |= EDP_PSR2_FRAME_BEFORE_SU(get_frames_before_su_entry(intel_dp));
+
val |= intel_psr2_get_tp_time(intel_dp);
 
if (DISPLAY_VER(dev_priv) >= 12) {
@@ -785,6 +808,9 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
val |= EDP_PSR2_SU_SDP_SCANLINE;
 
+   if (DISPLAY_VER(dev_priv) >= 20)
+   psr_val |= 
LNL_EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
if (intel_dp->psr.psr2_sel_fetch_enabled) {
u32 tmp;
 
@@ -798,7 +824,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is
 * recommending keep this bit unset while PSR2 is enabled.
 */
-   intel_de_write(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), 0);
+   intel_de_write(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder), 
psr_val);
 
intel_de_write(dev_priv, EDP_PSR2_CTL(cpu_transcoder), val);
 }
@@ -1066,6 +1092,36 @@ static bool _compute_psr2_wake_times(struct intel_dp 
*intel_dp,
return true;
 }
 

[Intel-gfx] [PATCH] drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier

2023-10-25 Thread Mika Kahola
Display driver shall read DPCD 00071h[3:1] during configuration
to get PSR setup time. This register provides the setup time
requirement on the VSC SDP entry packet. If setup time cannot be
met with the current timings
(e.g., PSR setup time + other blanking requirements > blanking time),
driver should enable sending VSC SDP one frame earlier before sending
the capture frame.

BSpec: 69895 (PSR Entry Setup Frames 17:16)

Signed-off-by: Mika Kahola 
---
 .../drm/i915/display/intel_display_types.h|  1 +
 drivers/gpu/drm/i915/display/intel_psr.c  | 35 ---
 drivers/gpu/drm/i915/display/intel_psr_regs.h |  2 ++
 3 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index 65ea37fe8cff..a0bcab6f2bec 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1710,6 +1710,7 @@ struct intel_psr {
u32 dc3co_exitline;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
+   u8 entry_setup_frames;
 };
 
 struct intel_dp {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 4f1f31fc9529..0acb4edae128 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -592,6 +592,9 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE;
 
+   if (intel_dp->psr.entry_setup_frames > 0)
+   dpcd_val |= DP_PSR_FRAME_CAPTURE;
+
drm_dp_dpcd_writeb(_dp->aux, DP_PSR_EN_CFG, dpcd_val);
 
drm_dp_dpcd_writeb(_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
@@ -690,6 +693,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 8)
val |= EDP_PSR_CRC_ENABLE;
 
+   if (intel_dp->psr.entry_setup_frames > 0)
+   val |= 
EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
intel_de_rmw(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder),
 ~EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK, val);
 }
@@ -731,6 +737,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
+   u8 frames_before_su_entry;
u32 val = EDP_PSR2_ENABLE;
 
val |= EDP_PSR2_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
@@ -741,7 +748,10 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12)
val |= EDP_Y_COORDINATE_ENABLE;
 
-   val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, 
intel_dp->psr.sink_sync_latency + 1, 2));
+   frames_before_su_entry = max_t(u8,
+  intel_dp->psr.sink_sync_latency + 1,
+  2);
+   val |= EDP_PSR2_FRAME_BEFORE_SU(frames_before_su_entry);
val |= intel_psr2_get_tp_time(intel_dp);
 
if (DISPLAY_VER(dev_priv) >= 12) {
@@ -785,6 +795,14 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (intel_dp->psr.req_psr2_sdp_prior_scanline)
val |= EDP_PSR2_SU_SDP_SCANLINE;
 
+   /* Entry setup frames must be at least 1 less than frames before SU 
entry */
+   if (intel_dp->psr.entry_setup_frames > 0) {
+   val |= 
EDP_PSR_ENTRY_SETUP_FRAMES(intel_dp->psr.entry_setup_frames);
+
+   if (intel_dp->psr.entry_setup_frames >= frames_before_su_entry)
+   val |= EDP_PSR2_FRAME_BEFORE_SU(frames_before_su_entry 
+ 1);
+   }
+
if (intel_dp->psr.psr2_sel_fetch_enabled) {
u32 tmp;
 
@@ -1252,10 +1270,17 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
 
if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) {
-   drm_dbg_kms(_priv->drm,
-   "PSR condition failed: PSR setup time (%d us) too 
long\n",
-   psr_setup_time);
-   return;
+   if (DISPLAY_VER(dev_priv) >= 20) {
+   intel_dp->psr.entry_setup_frames = 1;
+   drm_dbg_kms(_priv->drm,
+   "PSR setup entry frames: %d\n",
+   intel_dp->psr.entry_setup_frames);
+   } else {
+   drm_dbg_kms(_priv->drm,
+   "PSR condition failed: PSR setup time (%d 
us) too long\n",
+   psr_setup_time);
+

[Intel-gfx] [PATCH v3] drm/i915/display: Reset message bus after each read/write operation

2023-10-16 Thread Mika Kahola
Every know and then we receive the following error when running
for example IGT test kms_flip.

[drm] *ERROR* PHY G Read 0d80 failed after 3 retries.
[drm] *ERROR* PHY G Write 0d81 failed after 3 retries.

Since the error is sporadic in nature, the patch proposes
to reset the message bus after every successful or unsuccessful
read or write operation.

v2: Add FIXME's to indicate the experimental nature of
this workaround (Rodrigo)
v3: Dropping the additional delay as moving reset to *_read_once()
and *_write_once() functions seem unnecessary delay

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 6e6a1818071e..9e24f820d4cf 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -206,6 +206,13 @@ static int __intel_cx0_read_once(struct drm_i915_private 
*i915, enum port port,
 
intel_clear_response_ready_flag(i915, port, lane);
 
+   /*
+* FIXME: Workaround to let HW to settle
+* down and let the message bus to end up
+* in a known state
+*/
+   intel_cx0_bus_reset(i915, port, lane);
+
return REG_FIELD_GET(XELPDP_PORT_P2M_DATA_MASK, val);
 }
 
@@ -285,6 +292,13 @@ static int __intel_cx0_write_once(struct drm_i915_private 
*i915, enum port port,
 
intel_clear_response_ready_flag(i915, port, lane);
 
+   /*
+* FIXME: Workaround to let HW to settle
+* down and let the message bus to end up
+* in a known state
+*/
+   intel_cx0_bus_reset(i915, port, lane);
+
return 0;
 }
 
-- 
2.34.1



[Intel-gfx] [PATCH v2] drm/i915/display: Reset message bus after each read/write operation

2023-10-13 Thread Mika Kahola
Every know and then we receive the following error when running
for example IGT test kms_flip.

[drm] *ERROR* PHY G Read 0d80 failed after 3 retries.
[drm] *ERROR* PHY G Write 0d81 failed after 3 retries.

Since the error is sporadic in nature, the patch proposes
to reset the message bus after every successful or unsuccessful
read or write operation. However, the testing revealed that this
alone is not sufficient method and therefore an additional
delay is introduced anything from 200us to 300us to let HW to
settle down. This delay is experimental value and has no
specification to back it up.

v2: Add FIXME's to indicate the experimental nature of
this workaround (Rodrigo)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 6e6a1818071e..7c48ec5e54bd 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -221,6 +221,14 @@ static u8 __intel_cx0_read(struct drm_i915_private *i915, 
enum port port,
for (i = 0; i < 3; i++) {
status = __intel_cx0_read_once(i915, port, lane, addr);
 
+   /*
+* FIXME: Workaround to let HW to settle
+* down and let the message bus to end up
+* in a known state
+*/
+   intel_cx0_bus_reset(i915, port, lane);
+   usleep_range(200, 300);
+
if (status >= 0)
return status;
}
@@ -300,6 +308,14 @@ static void __intel_cx0_write(struct drm_i915_private 
*i915, enum port port,
for (i = 0; i < 3; i++) {
status = __intel_cx0_write_once(i915, port, lane, addr, data, 
committed);
 
+   /*
+* FIXME: Workaround to let HW to settle
+* down and let the message bus to end up
+* in a known state
+*/
+   intel_cx0_bus_reset(i915, port, lane);
+   usleep_range(200, 300);
+
if (status == 0)
return;
}
-- 
2.34.1



[Intel-gfx] [PATCH v3] drm/i915/lnl: Remove watchdog timers for PSR

2023-10-10 Thread Mika Kahola
Watchdorg timers for Lunarlake HW were removed for PSR/PSR2
The patch removes the use of these timers from the driver code.

BSpec: 69895

v2: Reword commit message (Ville)
Drop HPD mask from LNL (Ville)
Revise masking logic (Jouni)
v3: Revise commit message (Ville)
Revert HPD mask removal as irrelevant for this patch (Ville)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index bb65881e87cc..4f1f31fc9529 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -676,7 +676,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
 
val |= EDP_PSR_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
 
-   val |= EDP_PSR_MAX_SLEEP_TIME(max_sleep_time);
+   if (DISPLAY_VER(dev_priv) < 20)
+   val |= EDP_PSR_MAX_SLEEP_TIME(max_sleep_time);
+
if (IS_HASWELL(dev_priv))
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
@@ -1400,8 +1402,10 @@ static void intel_psr_enable_source(struct intel_dp 
*intel_dp,
 */
mask = EDP_PSR_DEBUG_MASK_MEMUP |
   EDP_PSR_DEBUG_MASK_HPD |
-  EDP_PSR_DEBUG_MASK_LPSP |
-  EDP_PSR_DEBUG_MASK_MAX_SLEEP;
+  EDP_PSR_DEBUG_MASK_LPSP;
+
+   if (DISPLAY_VER(dev_priv) < 20)
+   mask |= EDP_PSR_DEBUG_MASK_MAX_SLEEP;
 
/*
 * No separate pipe reg write mask on hsw/bdw, so have to unmask all
-- 
2.34.1



[Intel-gfx] [PATCH v2] drm/i915/lnl: Remove watchdog timers for PSR

2023-10-09 Thread Mika Kahola
Currently we are not using watchdog timers for PSR/PSR2
with Lunarlake. The patch removes the use of these timers
from the driver code.

BSpec: 69895

v2: Reword commit message (Ville)
Drop HPD mask from LNL (Ville)
Revise masking logic (Jouni)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 850b11f20285..abdafd04d8e3 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -676,7 +676,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
 
val |= EDP_PSR_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
 
-   val |= EDP_PSR_MAX_SLEEP_TIME(max_sleep_time);
+   if (DISPLAY_VER(dev_priv) < 20)
+   val |= EDP_PSR_MAX_SLEEP_TIME(max_sleep_time);
+
if (IS_HASWELL(dev_priv))
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
@@ -1399,9 +1401,11 @@ static void intel_psr_enable_source(struct intel_dp 
*intel_dp,
 * can rely on frontbuffer tracking.
 */
mask = EDP_PSR_DEBUG_MASK_MEMUP |
-  EDP_PSR_DEBUG_MASK_HPD |
-  EDP_PSR_DEBUG_MASK_LPSP |
-  EDP_PSR_DEBUG_MASK_MAX_SLEEP;
+  EDP_PSR_DEBUG_MASK_LPSP;
+
+   if (DISPLAY_VER(dev_priv) < 20)
+   mask |= EDP_PSR_DEBUG_MASK_HPD |
+   EDP_PSR_DEBUG_MASK_MAX_SLEEP;
 
/*
 * No separate pipe reg write mask on hsw/bdw, so have to unmask all
-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/lnl: Remove watchdog timers for PSR

2023-10-06 Thread Mika Kahola
Currently we are not using watchdog timers for PSR/PSR2.
The patch disables these timers so they are not in use.

BSpec: 69895

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_psr.c | 24 +---
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 850b11f20285..13b58dceb2bf 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -672,11 +672,15 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
u32 max_sleep_time = 0x1f;
-   u32 val = EDP_PSR_ENABLE;
+   u32 val = 0;
 
-   val |= EDP_PSR_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
 
-   val |= EDP_PSR_MAX_SLEEP_TIME(max_sleep_time);
+   if (DISPLAY_VER(dev_priv) < 20) {
+   val =  EDP_PSR_ENABLE;
+   val |= EDP_PSR_MAX_SLEEP_TIME(max_sleep_time);
+   }
+
+   val |= EDP_PSR_IDLE_FRAMES(psr_compute_idle_frames(intel_dp));
if (IS_HASWELL(dev_priv))
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
@@ -1398,10 +1402,16 @@ static void intel_psr_enable_source(struct intel_dp 
*intel_dp,
 * runtime_pm besides preventing  other hw tracking issues now we
 * can rely on frontbuffer tracking.
 */
-   mask = EDP_PSR_DEBUG_MASK_MEMUP |
-  EDP_PSR_DEBUG_MASK_HPD |
-  EDP_PSR_DEBUG_MASK_LPSP |
-  EDP_PSR_DEBUG_MASK_MAX_SLEEP;
+   if (DISPLAY_VER(dev_priv) >= 20)
+   mask = EDP_PSR_DEBUG_MASK_MEMUP |
+  EDP_PSR_DEBUG_MASK_HPD |
+  EDP_PSR_DEBUG_MASK_LPSP;
+   else
+   mask = EDP_PSR_DEBUG_MASK_MEMUP |
+  EDP_PSR_DEBUG_MASK_HPD |
+  EDP_PSR_DEBUG_MASK_LPSP |
+  EDP_PSR_DEBUG_MASK_MAX_SLEEP;
+
 
/*
 * No separate pipe reg write mask on hsw/bdw, so have to unmask all
-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/display: Reset message bus after each read/write operation

2023-10-04 Thread Mika Kahola
Every know and then we receive the following error when running
for example IGT test kms_flip.

[drm] *ERROR* PHY G Read 0d80 failed after 3 retries.
[drm] *ERROR* PHY G Write 0d81 failed after 3 retries.

Since the error is sporadic in nature, the patch proposes
to reset the message bus after every successful or unsuccessful
read or write operation. However, testing revealed that this
alone is not sufficient method an additiona delay is also
introduces anything from 200us to 300us. This delay is experimental
value and has no specification to back it up.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index abd607b564f1..a71b8a29d6b0 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -220,9 +220,12 @@ static u8 __intel_cx0_read(struct drm_i915_private *i915, 
enum port port,
/* 3 tries is assumed to be enough to read successfully */
for (i = 0; i < 3; i++) {
status = __intel_cx0_read_once(i915, port, lane, addr);
+   intel_cx0_bus_reset(i915, port, lane);
 
if (status >= 0)
return status;
+
+   usleep_range(200, 300);
}
 
drm_err_once(>drm, "PHY %c Read %04x failed after %d retries.\n",
@@ -299,9 +302,12 @@ static void __intel_cx0_write(struct drm_i915_private 
*i915, enum port port,
/* 3 tries is assumed to be enough to write successfully */
for (i = 0; i < 3; i++) {
status = __intel_cx0_write_once(i915, port, lane, addr, data, 
committed);
+   intel_cx0_bus_reset(i915, port, lane);
 
if (status == 0)
return;
+
+   usleep_range(200, 300);
}
 
drm_err_once(>drm,
-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/mtl: Cleanup usage of phy lane reset

2023-06-09 Thread Mika Kahola
>From PICA message bus we wait for acknowledgment from
read/write commands. In case of an error, we reset the
bus for the next command.

Current implementation ends up resetting message bus twice
in cases where error is not the timeout. Since, we only need
to reset message bus once, let's move reset to corresponding
timeout error and drop the excess reset function calls from
read/write functions.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 0600fdcd06ef..f235df5646ed 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -116,6 +116,7 @@ static int intel_cx0_wait_for_ack(struct drm_i915_private 
*i915, enum port port,
 XELPDP_MSGBUS_TIMEOUT_SLOW, val)) {
drm_dbg_kms(>drm, "PHY %c Timeout waiting for message 
ACK. Status: 0x%x\n",
phy_name(phy), *val);
+   intel_cx0_bus_reset(i915, port, lane);
return -ETIMEDOUT;
}
 
@@ -158,10 +159,8 @@ static int __intel_cx0_read_once(struct drm_i915_private 
*i915, enum port port,
   XELPDP_PORT_M2P_ADDRESS(addr));
 
ack = intel_cx0_wait_for_ack(i915, port, 
XELPDP_PORT_P2M_COMMAND_READ_ACK, lane, );
-   if (ack < 0) {
-   intel_cx0_bus_reset(i915, port, lane);
+   if (ack < 0)
return ack;
-   }
 
intel_clear_response_ready_flag(i915, port, lane);
 
@@ -202,6 +201,7 @@ static int __intel_cx0_write_once(struct drm_i915_private 
*i915, enum port port,
  int lane, u16 addr, u8 data, bool committed)
 {
enum phy phy = intel_port_to_phy(i915, port);
+   int ack;
u32 val;
 
if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, 
lane),
@@ -230,10 +230,9 @@ static int __intel_cx0_write_once(struct drm_i915_private 
*i915, enum port port,
}
 
if (committed) {
-   if (intel_cx0_wait_for_ack(i915, port, 
XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, ) < 0) {
-   intel_cx0_bus_reset(i915, port, lane);
-   return -EINVAL;
-   }
+   ack = intel_cx0_wait_for_ack(i915, port, 
XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, );
+   if (ack < 0)
+   return ack;
} else if ((intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, 
lane)) &
XELPDP_PORT_P2M_ERROR_SET)) {
drm_dbg_kms(>drm,
-- 
2.34.1



[Intel-gfx] [PATCH v2] drm/i915/mtl: Reset only one lane in case of MFD

2023-06-01 Thread Mika Kahola
In case when only two or less transmit lanes are owned such as MFD
(DP-alt with x2 lanes) we need to reset only one data lane (lane0).
With only x2 lanes we don't need to poll for the phy current
status on both data lanes since only the owned data lane will respond.

v2: Find better naming for lanes and revise the commit message (Luca)

Reviewed-by: Arun R Murthy  (v1)
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 39 
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index ee6902118860..0600fdcd06ef 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2528,13 +2528,23 @@ static u32 intel_cx0_get_pclk_refclk_ack(u8 lane_mask)
return val;
 }
 
-/* FIXME: Some Type-C cases need not reset both the lanes. Handle those cases. 
*/
-static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915, enum port 
port,
+static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915,
+struct intel_encoder *encoder,
 bool lane_reversal)
 {
+   enum port port = encoder->port;
enum phy phy = intel_port_to_phy(i915, port);
+   bool both_lanes =  
intel_tc_port_fia_max_lane_count(enc_to_dig_port(encoder)) > 2;
u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 :
  INTEL_CX0_LANE0;
+   u32 lane_pipe_reset = both_lanes ?
+ XELPDP_LANE_PIPE_RESET(0) |
+ XELPDP_LANE_PIPE_RESET(1) :
+ XELPDP_LANE_PIPE_RESET(0);
+   u32 lane_phy_current_status = both_lanes ?
+ XELPDP_LANE_PHY_CURRENT_STATUS(0) |
+ XELPDP_LANE_PHY_CURRENT_STATUS(1) :
+ XELPDP_LANE_PHY_CURRENT_STATUS(0);
 
if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL1(port),
 XELPDP_PORT_BUF_SOC_PHY_READY,
@@ -2545,23 +2555,24 @@ static void intel_cx0_phy_lane_reset(struct 
drm_i915_private *i915, enum port po
 
intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
 XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1),
-XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1));
+lane_pipe_reset);
 
if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(port),
-XELPDP_LANE_PHY_CURRENT_STATUS(0) |
-XELPDP_LANE_PHY_CURRENT_STATUS(1),
-XELPDP_LANE_PHY_CURRENT_STATUS(0) |
-XELPDP_LANE_PHY_CURRENT_STATUS(1),
+lane_phy_current_status, 
lane_phy_current_status,
 XELPDP_PORT_RESET_START_TIMEOUT_US, 0, 
NULL))
drm_warn(>drm, "PHY %c failed to bring out of Lane reset 
after %dus.\n",
 phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
 
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(port),
-intel_cx0_get_pclk_refclk_request(INTEL_CX0_BOTH_LANES),
+intel_cx0_get_pclk_refclk_request(both_lanes ?
+  INTEL_CX0_BOTH_LANES :
+  INTEL_CX0_LANE0),
 intel_cx0_get_pclk_refclk_request(lane_mask));
 
if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(port),
-
intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES),
+
intel_cx0_get_pclk_refclk_ack(both_lanes ?
+  
INTEL_CX0_BOTH_LANES :
+  
INTEL_CX0_LANE0),
 
intel_cx0_get_pclk_refclk_ack(lane_mask),
 XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, 
NULL))
drm_warn(>drm, "PHY %c failed to request refclk after 
%dus.\n",
@@ -2571,13 +2582,9 @@ static void intel_cx0_phy_lane_reset(struct 
drm_i915_private *i915, enum port po
CX0_P2_STATE_RESET);
intel_cx0_setup_powerdown(i915, port);
 
-   intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
-XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1),
-0);
+   intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port), lane_pipe_reset, 0);
 
-   if (intel_de_wait_for_clear(i915, XELPDP_PORT_BUF_CTL2(port),
-   

[Intel-gfx] [PATCH] drm/i915/mtl: Reset only one lane in case of MFD

2023-05-24 Thread Mika Kahola
In case when only two or less lanes are owned such as MFD (DP-alt with x2 lanes)
we need to reset only one lane (lane0). With only x2 lanes we don't need
to poll for the phy current status on both lanes since only the owned lane
will respond.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 39 
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index ee6902118860..b8c812c5b33f 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2528,13 +2528,23 @@ static u32 intel_cx0_get_pclk_refclk_ack(u8 lane_mask)
return val;
 }
 
-/* FIXME: Some Type-C cases need not reset both the lanes. Handle those cases. 
*/
-static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915, enum port 
port,
+static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915,
+struct intel_encoder *encoder,
 bool lane_reversal)
 {
+   enum port port = encoder->port;
enum phy phy = intel_port_to_phy(i915, port);
+   u8 fia_max =  
intel_tc_port_fia_max_lane_count(enc_to_dig_port(encoder));
u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 :
  INTEL_CX0_LANE0;
+   u32 lane_pipe_reset = fia_max > 2 ?
+ XELPDP_LANE_PIPE_RESET(0) |
+ XELPDP_LANE_PIPE_RESET(1) :
+ XELPDP_LANE_PIPE_RESET(0);
+   u32 lane_phy_current_status = fia_max > 2 ?
+ XELPDP_LANE_PHY_CURRENT_STATUS(0) |
+ XELPDP_LANE_PHY_CURRENT_STATUS(1) :
+ XELPDP_LANE_PHY_CURRENT_STATUS(0);
 
if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL1(port),
 XELPDP_PORT_BUF_SOC_PHY_READY,
@@ -2545,23 +2555,24 @@ static void intel_cx0_phy_lane_reset(struct 
drm_i915_private *i915, enum port po
 
intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
 XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1),
-XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1));
+lane_pipe_reset);
 
if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(port),
-XELPDP_LANE_PHY_CURRENT_STATUS(0) |
-XELPDP_LANE_PHY_CURRENT_STATUS(1),
-XELPDP_LANE_PHY_CURRENT_STATUS(0) |
-XELPDP_LANE_PHY_CURRENT_STATUS(1),
+lane_phy_current_status, 
lane_phy_current_status,
 XELPDP_PORT_RESET_START_TIMEOUT_US, 0, 
NULL))
drm_warn(>drm, "PHY %c failed to bring out of Lane reset 
after %dus.\n",
 phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
 
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(port),
-intel_cx0_get_pclk_refclk_request(INTEL_CX0_BOTH_LANES),
+intel_cx0_get_pclk_refclk_request(fia_max > 2 ?
+  INTEL_CX0_BOTH_LANES :
+  INTEL_CX0_LANE0),
 intel_cx0_get_pclk_refclk_request(lane_mask));
 
if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(port),
-
intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES),
+intel_cx0_get_pclk_refclk_ack(fia_max 
> 2 ?
+  
INTEL_CX0_BOTH_LANES :
+  
INTEL_CX0_LANE0),
 
intel_cx0_get_pclk_refclk_ack(lane_mask),
 XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, 
NULL))
drm_warn(>drm, "PHY %c failed to request refclk after 
%dus.\n",
@@ -2571,13 +2582,9 @@ static void intel_cx0_phy_lane_reset(struct 
drm_i915_private *i915, enum port po
CX0_P2_STATE_RESET);
intel_cx0_setup_powerdown(i915, port);
 
-   intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port),
-XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1),
-0);
+   intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(port), lane_pipe_reset, 0);
 
-   if (intel_de_wait_for_clear(i915, XELPDP_PORT_BUF_CTL2(port),
-   XELPDP_LANE_PHY_CURRENT_STATUS(0) |
-   XELPDP_LANE_PHY_CURRENT_STATUS(1),
+   if (intel_de_wait_

[Intel-gfx] [PATCH] drm/i915/mtl: Fix expected reg value for Thunderbolt PLL disabling

2023-05-12 Thread Mika Kahola
While disabling Thunderbolt PLL, we request PLL to be stopped and
wait for ACK bit to be cleared. The expected value should be '0'
instead of '~XELPDP_TBT_CLOCK_ACK' or otherwise we incorrectly
receive dmesg warn "PHY PLL not unlocked in 10us".

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index d94127e7448b..c64cf6778627 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2861,9 +2861,7 @@ static void intel_mtl_tbt_pll_disable(struct 
intel_encoder *encoder)
 
/* 3. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "0". */
if (__intel_de_wait_for_register(i915, 
XELPDP_PORT_CLOCK_CTL(encoder->port),
-XELPDP_TBT_CLOCK_ACK,
-~XELPDP_TBT_CLOCK_ACK,
-10, 0, NULL))
+XELPDP_TBT_CLOCK_ACK, 0, 10, 0, NULL))
drm_warn(>drm, "[ENCODER:%d:%s][%c] PHY PLL not unlocked 
after 10us.\n",
 encoder->base.base.id, encoder->base.name, 
phy_name(phy));
 
-- 
2.34.1



[Intel-gfx] [PATCH v2 09/13] drm/i915/mtl: Define mask for DDI AUX interrupts

2023-04-28 Thread Mika Kahola
From: Gustavo Sousa 

Xe_LPD+ defines interrupt bits for only DDI ports in the DE Port
Interrupt registers. The bits for Type-C ports are defined in the PICA
interrupt registers.

BSpec: 50064

Reviewed-by: Radhakrishna Sripada 
Signed-off-by: Gustavo Sousa 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/i915_irq.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2b94b8ca8ec9..e5f12aa141f6 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1938,7 +1938,10 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private 
*dev_priv)
 {
u32 mask;
 
-   if (DISPLAY_VER(dev_priv) >= 13)
+   if (DISPLAY_VER(dev_priv) >= 14)
+   return TGL_DE_PORT_AUX_DDIA |
+   TGL_DE_PORT_AUX_DDIB;
+   else if (DISPLAY_VER(dev_priv) >= 13)
return TGL_DE_PORT_AUX_DDIA |
TGL_DE_PORT_AUX_DDIB |
TGL_DE_PORT_AUX_DDIC |
-- 
2.34.1



[Intel-gfx] [PATCH v2 12/13] drm/i915/mtl: Pin assignment for TypeC

2023-04-28 Thread Mika Kahola
From: Anusha Srivatsa 

Unlike previous platforms that used PORT_TX_DFLEXDPSP
for max_lane calculation, MTL uses only PORT_TX_DFLEXPA1
from which the max_lanes has to be calculated.

Bspec: 50235, 65380

Reviewed-by: Matt Atwood 
Signed-off-by: Anusha Srivatsa 
Signed-off-by: Jose Roberto de Souza 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 28 +
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index b192265a3d78..4fca711a58bc 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -16,6 +16,10 @@
 #include "intel_mg_phy_regs.h"
 #include "intel_tc.h"
 
+#define DP_PIN_ASSIGNMENT_C0x3
+#define DP_PIN_ASSIGNMENT_D0x4
+#define DP_PIN_ASSIGNMENT_E0x5
+
 enum tc_port_mode {
TC_PORT_DISCONNECTED,
TC_PORT_TBT_ALT,
@@ -281,6 +285,27 @@ u32 intel_tc_port_get_pin_assignment_mask(struct 
intel_digital_port *dig_port)
   DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
 }
 
+static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port 
*dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   intel_wakeref_t wakeref;
+   u32 pin_mask;
+
+   with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+   pin_mask = intel_tc_port_get_pin_assignment_mask(dig_port);
+
+   switch (pin_mask) {
+   default:
+   MISSING_CASE(pin_mask);
+   fallthrough;
+   case DP_PIN_ASSIGNMENT_D:
+   return 2;
+   case DP_PIN_ASSIGNMENT_C:
+   case DP_PIN_ASSIGNMENT_E:
+   return 4;
+   }
+}
+
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -294,6 +319,9 @@ int intel_tc_port_fia_max_lane_count(struct 
intel_digital_port *dig_port)
 
assert_tc_cold_blocked(tc);
 
+   if (DISPLAY_VER(i915) >= 14)
+   return mtl_tc_port_get_pin_assignment_mask(dig_port);
+
lane_mask = 0;
with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
lane_mask = intel_tc_port_get_lane_mask(dig_port);
-- 
2.34.1



[Intel-gfx] [PATCH v2 13/13] drm/i915/mtl: Enable TC ports

2023-04-28 Thread Mika Kahola
Finally, we can enable TC ports for Meteorlake.

Reviewed-by: Clint Taylor 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_display.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 0b9ae5759ffa..3d3483e6f836 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7336,9 +7336,12 @@ void intel_setup_outputs(struct drm_i915_private 
*dev_priv)
return;
 
if (IS_METEORLAKE(dev_priv)) {
-   /* TODO: initialize TC ports as well */
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
+   intel_ddi_init(dev_priv, PORT_TC1);
+   intel_ddi_init(dev_priv, PORT_TC2);
+   intel_ddi_init(dev_priv, PORT_TC3);
+   intel_ddi_init(dev_priv, PORT_TC4);
} else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
-- 
2.34.1



[Intel-gfx] [PATCH v2 08/13] drm/i915/mtl: Readout Thunderbolt HW state

2023-04-28 Thread Mika Kahola
Readout hw state for Thunderbolt.

Reviewed-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 27 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |  5 +++-
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 7a2bf624eba7..2a364ae538f6 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2685,6 +2685,33 @@ static void intel_cx0pll_enable(struct intel_encoder 
*encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   u32 clock;
+   u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+   drm_WARN_ON(>drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_ACK));
+
+   switch (clock) {
+   case XELPDP_DDI_CLOCK_SELECT_TBT_162:
+   return 162000;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_270:
+   return 27;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_540:
+   return 54;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_810:
+   return 81;
+   default:
+   MISSING_CASE(clock);
+   return 162000;
+   }
+}
+
 static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
 {
switch (clock) {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 9ea6310b6d79..c1b8f7980f69 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -42,5 +42,5 @@ int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi 
*hdmi, int clock);
 void intel_cx0_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
   const struct intel_crtc_state 
*crtc_state,
   u32 level);
-int intel_mtl_tbt_readout_hw_state(struct intel_encoder *encoder);
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
 #endif /* __INTEL_CX0_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index c18226edacac..8f0f858cde31 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3852,8 +3852,11 @@ static void mtl_ddi_get_config(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_digital_port *dig_port = enc_to_dig_port(encoder);
 
-   if (intel_is_c10phy(i915, phy)) {
+   if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
+   crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
+   } else if (intel_is_c10phy(i915, phy)) {
intel_c10pll_readout_hw_state(encoder, 
_state->cx0pll_state.c10);
intel_c10pll_dump_hw_state(i915, _state->cx0pll_state.c10);
crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, 
_state->cx0pll_state.c10);
-- 
2.34.1



[Intel-gfx] [PATCH v2 11/13] drm/i915/mtl: TypeC HPD live status query

2023-04-28 Thread Mika Kahola
From: Imre Deak 

The HPD live status for MTL has to be read from different set of
registers. MTL deserves a new function for this purpose
and cannot reuse the existing  HPD live status detection

Reviewed-by: Matt Atwood 
Signed-off-by: Anusha Srivatsa 
Signed-off-by: Imre Deak 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 30 -
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 951b12ac51dc..b192265a3d78 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -886,6 +886,34 @@ static const struct intel_tc_phy_ops adlp_tc_phy_ops = {
  * XELPDP TC PHY handlers
  * --
  */
+static u32 xelpdp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
+{
+   struct drm_i915_private *i915 = tc_to_i915(tc);
+   struct intel_digital_port *dig_port = tc->dig_port;
+   enum hpd_pin hpd_pin = dig_port->base.hpd_pin;
+   u32 pica_isr_bits = i915->display.hotplug.hpd[hpd_pin];
+   u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin];
+   intel_wakeref_t wakeref;
+   u32 pica_isr;
+   u32 pch_isr;
+   u32 mask = 0;
+
+   with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+   pica_isr = intel_de_read(i915, PICAINTERRUPT_ISR);
+   pch_isr = intel_de_read(i915, SDEISR);
+   }
+
+   if (pica_isr & (pica_isr_bits & XELPDP_DP_ALT_HOTPLUG_MASK))
+   mask |= BIT(TC_PORT_DP_ALT);
+   if (pica_isr & (pica_isr_bits & XELPDP_TBT_HOTPLUG_MASK))
+   mask |= BIT(TC_PORT_TBT_ALT);
+
+   if (tc->legacy_port && (pch_isr & pch_isr_bit))
+   mask |= BIT(TC_PORT_LEGACY);
+
+   return mask;
+}
+
 static bool
 xelpdp_tc_phy_tcss_power_is_enabled(struct intel_tc_port *tc)
 {
@@ -1039,7 +1067,7 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port 
*tc)
 
 static const struct intel_tc_phy_ops xelpdp_tc_phy_ops = {
.cold_off_domain = tgl_tc_phy_cold_off_domain,
-   .hpd_live_status = adlp_tc_phy_hpd_live_status,
+   .hpd_live_status = xelpdp_tc_phy_hpd_live_status,
.is_ready = adlp_tc_phy_is_ready,
.is_owned = xelpdp_tc_phy_is_owned,
.get_hw_state = xelpdp_tc_phy_get_hw_state,
-- 
2.34.1



[Intel-gfx] [PATCH v2 07/13] drm/i915/mtl: Enabling/disabling sequence Thunderbolt pll

2023-04-28 Thread Mika Kahola
Enabling and disabling sequence for Thunderbolt PLL.

Bspec: 64568

v2: Use intel_de_wait_for_register() (RK)

Reviewed-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 135 ++-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   7 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |   4 +-
 3 files changed, 138 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 63d63c23647e..7a2bf624eba7 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2609,8 +2609,8 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
return val;
 }
 
-void intel_cx0pll_enable(struct intel_encoder *encoder,
-const struct intel_crtc_state *crtc_state)
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
@@ -2685,7 +2685,86 @@ void intel_cx0pll_enable(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
-void intel_cx0pll_disable(struct intel_encoder *encoder)
+static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
+{
+   switch (clock) {
+   case 162000:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   case 27:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_270;
+   case 54:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_540;
+   case 81:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_810;
+   default:
+   MISSING_CASE(clock);
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   }
+}
+
+static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+   u32 val = 0;
+
+   /*
+* 1. Program PORT_CLOCK_CTL REGISTER to configure
+* clock muxes, gating and SSC
+*/
+   val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(i915, 
crtc_state->port_clock));
+   val |= XELPDP_FORWARD_CLOCK_UNGATE;
+   intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+XELPDP_DDI_CLOCK_SELECT_MASK | 
XELPDP_FORWARD_CLOCK_UNGATE, val);
+
+   /* 2. Read back PORT_CLOCK_CTL REGISTER */
+   val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   /*
+* 3. Follow the Display Voltage Frequency Switching - Sequence
+* Before Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 4. Set PORT_CLOCK_CTL register TBT CLOCK Request to "1" to enable 
PLL.
+*/
+   val |= XELPDP_TBT_CLOCK_REQUEST;
+   intel_de_write(i915, XELPDP_PORT_CLOCK_CTL(encoder->port), val);
+
+   /* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */
+   if (__intel_de_wait_for_register(i915, 
XELPDP_PORT_CLOCK_CTL(encoder->port),
+XELPDP_TBT_CLOCK_ACK,
+XELPDP_TBT_CLOCK_ACK,
+100, 0, NULL))
+   drm_warn(>drm, "[ENCODER:%d:%s][%c] PHY PLL not locked 
after 100us.\n",
+encoder->base.base.id, encoder->base.name, 
phy_name(phy));
+
+   /*
+* 6. Follow the Display Voltage Frequency Switching Sequence After
+* Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 7. Program DDI_CLK_VALFREQ to match intended DDI
+* clock frequency.
+*/
+   intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+  crtc_state->port_clock);
+}
+
+void intel_mtl_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+   if (intel_tc_port_in_tbt_alt_mode(dig_port))
+   intel_mtl_tbt_pll_enable(encoder, crtc_state);
+   else
+   intel_cx0pll_enable(encoder, crtc_state);
+}
+
+static void intel_cx0pll_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);
@@ -2737,6 +2816,56 @@ void intel_cx0pll_disable(struct intel_encoder *encoder)
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(en

[Intel-gfx] [PATCH v2 10/13] drm/i915/mtl: Power up TCSS

2023-04-28 Thread Mika Kahola
Add register writes to enable powering up Type-C subsystem i.e. TCSS.
For MeteorLake we need to request TCSS to power up and check the TCSS
power state after 500 us.

In addition, for PICA we need to set/clear the Type-C PHY ownnership
bit when Type-C device is connected/disconnected.

Reviewed-by: Matt Atwood 
Signed-off-by: Mika Kahola 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c |  19 ++
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   4 +
 drivers/gpu/drm/i915/display/intel_ddi.c |   1 +
 drivers/gpu/drm/i915/display/intel_display.c |   2 +-
 drivers/gpu/drm/i915/display/intel_tc.c  | 199 ++-
 5 files changed, 216 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 2a364ae538f6..ae559897c3ac 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2893,6 +2893,25 @@ void intel_mtl_pll_disable(struct intel_encoder *encoder)
intel_cx0pll_disable(encoder);
 }
 
+enum icl_port_dpll_id
+intel_mtl_port_pll_type(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   /*
+* TODO: Determine the PLL type from the SW state, once MTL PLL
+* handling is done via the standard shared DPLL framework.
+*/
+   u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+   u32 clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+   if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK ||
+   clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK)
+   return ICL_PORT_DPLL_MG_PHY;
+   else
+   return ICL_PORT_DPLL_DEFAULT;
+}
+
 void intel_c10pll_state_verify(struct intel_atomic_state *state,
   struct intel_crtc_state *new_crtc_state)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index c1b8f7980f69..f99809af257d 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -16,12 +16,16 @@
 struct drm_i915_private;
 struct intel_encoder;
 struct intel_crtc_state;
+enum icl_port_dpll_id;
 enum phy;
 
 bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy);
 void intel_mtl_pll_enable(struct intel_encoder *encoder,
  const struct intel_crtc_state *crtc_state);
 void intel_mtl_pll_disable(struct intel_encoder *encoder);
+enum icl_port_dpll_id
+intel_mtl_port_pll_type(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state);
 void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct 
intel_c10pll_state *pll_state);
 int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct 
intel_encoder *encoder);
 void intel_c10pll_dump_hw_state(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 8f0f858cde31..55f36d9d509c 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4784,6 +4784,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, 
enum port port)
if (DISPLAY_VER(dev_priv) >= 14) {
encoder->enable_clock = intel_mtl_pll_enable;
encoder->disable_clock = intel_mtl_pll_disable;
+   encoder->port_pll_type = intel_mtl_port_pll_type;
encoder->get_config = mtl_ddi_get_config;
} else if (IS_DG2(dev_priv)) {
encoder->enable_clock = intel_mpllb_enable;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index bf391a6cd8d6..0b9ae5759ffa 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1756,7 +1756,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, 
enum phy phy)
if (IS_DG2(dev_priv))
/* DG2's "TC1" output uses a SNPS PHY */
return false;
-   else if (IS_ALDERLAKE_P(dev_priv))
+   else if (IS_ALDERLAKE_P(dev_priv) || IS_METEORLAKE(dev_priv))
return phy >= PHY_F && phy <= PHY_I;
else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 3b60995e9dfb..951b12ac51dc 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -5,6 +5,7 @@
 
 #include "i915_drv.h"
 #include "i915_reg.h"
+#include "intel_cx0_phy_regs.h"
 #include "intel_ddi.h"
 #include "intel_de.h"
 #include "intel_display

[Intel-gfx] [PATCH v2 05/13] drm/i915/mtl: Add voltage swing sequence for C20

2023-04-28 Thread Mika Kahola
DP1.4 and DP20 voltage swing sequence for C20 phy.

Bspec: 65449, 67636, 67610

Reviewed-by: Arun R Murthy 
Signed-off-by: Mika Kahola 
Signed-off-by: Clint Taylor 
Signed-off-by: Radhakrishna Sripada 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  4 ++
 .../drm/i915/display/intel_ddi_buf_trans.c| 53 ++-
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index d3de4df2b682..ab9d1d983b88 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -212,6 +212,10 @@
 #define   C20_MULTIPLIER_MASK  REG_GENMASK(11, 0)
 #define   C20_PHY_USE_MPLLBREG_BIT(7)
 
+/* C20 Phy VSwing Masks */
+#define C20_PHY_VSWING_PREEMPH_MASKREG_GENMASK8(5, 0)
+#define C20_PHY_VSWING_PREEMPH(val)
REG_FIELD_PREP8(C20_PHY_VSWING_PREEMPH_MASK, val)
+
 #define RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(idx) (0x303D + (idx))
 
 #endif /* __INTEL_CX0_REG_DEFS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c 
b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index cd4becbae098..b7d20485bde5 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -9,6 +9,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_cx0_phy.h"
 
 /* HDMI/DVI modes ignore everything but the last 2 items. So we share
  * them for both DP and FDI transports, allowing those ports to
@@ -1048,12 +1049,52 @@ static const union intel_ddi_buf_trans_entry 
_mtl_c10_trans_dp14[] = {
{ .snps = { 62, 0, 0  } },  /* preset 9 */
 };
 
-static const struct intel_ddi_buf_trans mtl_cx0c10_trans = {
+static const struct intel_ddi_buf_trans mtl_cx0_trans = {
.entries = _mtl_c10_trans_dp14,
.num_entries = ARRAY_SIZE(_mtl_c10_trans_dp14),
.hdmi_default_entry = ARRAY_SIZE(_mtl_c10_trans_dp14) - 1,
 };
 
+/* DP2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_uhbr[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 43, 0, 5 } },   /* preset 1 */
+   { .snps = { 40, 0, 8 } },   /* preset 2 */
+   { .snps = { 37, 0, 11 } },  /* preset 3 */
+   { .snps = { 33, 0, 15 } },  /* preset 4 */
+   { .snps = { 46, 2, 0 } },   /* preset 5 */
+   { .snps = { 42, 2, 4 } },   /* preset 6 */
+   { .snps = { 38, 2, 8 } },   /* preset 7 */
+   { .snps = { 35, 2, 11 } },  /* preset 8 */
+   { .snps = { 33, 2, 13 } },  /* preset 9 */
+   { .snps = { 44, 4, 0 } },   /* preset 10 */
+   { .snps = { 40, 4, 4 } },   /* preset 11 */
+   { .snps = { 37, 4, 7 } },   /* preset 12 */
+   { .snps = { 33, 4, 11 } },  /* preset 13 */
+   { .snps = { 40, 8, 0 } },   /* preset 14 */
+   { .snps = { 28, 2, 2 } },   /* preset 15 */
+};
+
+/* HDMI2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_hdmi[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 38, 4, 6 } },   /* preset 1 */
+   { .snps = { 36, 4, 8 } },   /* preset 2 */
+   { .snps = { 34, 4, 10 } },  /* preset 3 */
+   { .snps = { 32, 4, 12 } },  /* preset 4 */
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_hdmi = {
+   .entries = _mtl_c20_trans_hdmi,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_hdmi),
+   .hdmi_default_entry = 0,
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_uhbr = {
+   .entries = _mtl_c20_trans_uhbr,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_uhbr),
+};
+
 bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table)
 {
return table == _combo_phy_trans_edp_hbr2_hobl;
@@ -1630,7 +1671,15 @@ mtl_get_cx0_buf_trans(struct intel_encoder *encoder,
  const struct intel_crtc_state *crtc_state,
  int *n_entries)
 {
-   return intel_get_buf_trans(_cx0c10_trans, n_entries);
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+   if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock >= 
100)
+   return intel_get_buf_trans(_c20_trans_uhbr, n_entries);
+   else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && 
!(intel_is_c10phy(i915, phy)))
+   return intel_get_buf_trans(_c20_trans_hdmi, n_entries);
+   else
+   return intel_get_buf_trans(_cx0_trans, n_entries);
 }
 
 void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
-- 
2.34.1



[Intel-gfx] [PATCH v2 06/13] drm/i915/mtl: For DP2.0 10G and 20G rates use MPLLA

2023-04-28 Thread Mika Kahola
Use MPLLA for DP2.0 rates 10G and 20G, when ssc is enabled.

v2: Fix typo in commit message (Animesh)

Reviewed-by: Radhakrishna Sripada 
Reviewed-by: Arun R Murthy 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 5409be0d5812..63d63c23647e 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2349,8 +2349,11 @@ static void intel_program_port_clock_ctl(struct 
intel_encoder *encoder,
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
 
/* TODO: HDMI FRL */
-   /* TODO: DP2.0 10G and 20G rates enable MPLLA*/
-   val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 
0;
+   /* DP2.0 10G and 20G rates enable MPLLA*/
+   if (crtc_state->port_clock == 100 || crtc_state->port_clock == 
200)
+   val |= crtc_state->cx0pll_state.ssc_enabled ? 
XELPDP_SSC_ENABLE_PLLA : 0;
+   else
+   val |= crtc_state->cx0pll_state.ssc_enabled ? 
XELPDP_SSC_ENABLE_PLLB : 0;
 
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
 XELPDP_LANE1_PHY_CLOCK_SELECT | 
XELPDP_FORWARD_CLOCK_UNGATE |
-- 
2.34.1



[Intel-gfx] [PATCH v2 03/13] drm/i915/mtl: Dump C20 pll hw state

2023-04-28 Thread Mika Kahola
As we already do with C10 chip, let's dump the pll
hw state for C20 as well.

Reviewed-by: Radhakrishna Sripada 
Reviewed-by: Arun R Murthy 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 20 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 ++
 drivers/gpu/drm/i915/display/intel_ddi.c |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index f58b3112baea..8920263cacd7 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2036,6 +2036,26 @@ void intel_c20pll_readout_hw_state(struct intel_encoder 
*encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+   const struct intel_c20pll_state *hw_state)
+{
+   int i;
+
+   drm_dbg_kms(>drm, "c20pll_hw_state:\n");
+   drm_dbg_kms(>drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 
0x%.4x\n",
+   hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
+   drm_dbg_kms(>drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 
0x%.4x, cmn[3] = 0x%.4x\n",
+   hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], 
hw_state->cmn[3]);
+
+   if (intel_c20_use_mplla(hw_state->clock)) {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
+   drm_dbg_kms(>drm, "mplla[%d] = 0x%.4x\n", i, 
hw_state->mplla[i]);
+   } else {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
+   drm_dbg_kms(>drm, "mpllb[%d] = 0x%.4x\n", i, 
hw_state->mpllb[i]);
+   }
+}
+
 static u8 intel_c20_get_dp_rate(u32 clock)
 {
switch (clock) {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 9760c6292c81..c643aae27bac 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -32,6 +32,8 @@ void intel_c10pll_state_verify(struct intel_atomic_state 
*state,
   struct intel_crtc_state *new_crtc_state);
 void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
   struct intel_c20pll_state *pll_state);
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+   const struct intel_c20pll_state *hw_state);
 void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
 const struct intel_crtc_state *crtc_state);
 int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 44f07011245b..d414dd8c26bf 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3858,6 +3858,7 @@ static void mtl_ddi_get_config(struct intel_encoder 
*encoder,
intel_c10pll_dump_hw_state(i915, _state->cx0pll_state.c10);
} else {
intel_c20pll_readout_hw_state(encoder, 
_state->cx0pll_state.c20);
+   intel_c20pll_dump_hw_state(i915, _state->cx0pll_state.c20);
}
 
crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, 
_state->cx0pll_state.c10);
-- 
2.34.1



[Intel-gfx] [PATCH v2 04/13] drm/i915/mtl: C20 port clock calculation

2023-04-28 Thread Mika Kahola
Calculate port clock with C20 phy.

BSpec: 64568

Reviewed-by: Radhakrishna Sripada 
Reviewed-by: Arun R Murthy 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 45 +++
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |  2 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  3 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |  4 +-
 drivers/gpu/drm/i915/display/intel_dpll.c |  2 +
 5 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 8920263cacd7..5409be0d5812 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2283,6 +2283,51 @@ int intel_c10pll_calc_port_clock(struct intel_encoder 
*encoder,
return tmpclk;
 }
 
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+const struct intel_c20pll_state *pll_state)
+{
+   unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
+   unsigned int multiplier, refclk = 38400;
+   unsigned int tx_clk_div;
+   unsigned int ref_clk_mpllb_div;
+   unsigned int fb_clk_div4_en;
+   unsigned int ref, vco;
+   unsigned int tx_rate_mult;
+   unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
+
+   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   tx_rate_mult = 1;
+   frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
+   frac_quot = pll_state->mpllb[8];
+   frac_rem =  pll_state->mpllb[9];
+   frac_den =  pll_state->mpllb[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, 
pll_state->mpllb[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = 0;
+   } else {
+   tx_rate_mult = 2;
+   frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
+   frac_quot = pll_state->mplla[8];
+   frac_rem =  pll_state->mplla[9];
+   frac_den =  pll_state->mplla[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mplla[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, 
pll_state->mplla[1]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mplla[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mplla[0]);
+   }
+
+   if (frac_en)
+   frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den);
+   else
+   frac = 0;
+
+   ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << 
ref_clk_mpllb_div);
+   vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + 
frac) >> 17, 10);
+
+   return vco << tx_rate_mult >> tx_clk_div >> tx_rate;
+}
+
 static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
 const struct intel_crtc_state 
*crtc_state,
 bool lane_reversal)
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index c643aae27bac..83bd3500091b 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -34,6 +34,8 @@ void intel_c20pll_readout_hw_state(struct intel_encoder 
*encoder,
   struct intel_c20pll_state *pll_state);
 void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
const struct intel_c20pll_state *hw_state);
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+const struct intel_c20pll_state *pll_state);
 void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
 const struct intel_crtc_state *crtc_state);
 int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index bfb39bce3b04..d3de4df2b682 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -196,16 +196,19 @@
 #define   PHY_C20_CUSTOM_WIDTH(val)
REG_FIELD_PREP8(PHY_C20_CUSTOM_WIDTH_MASK, val)
 #define PHY_C20_A_TX_CNTX_CFG(idx) (0xCF2E - (idx))
 #define PHY_C20_B_TX_CNTX_CFG(idx) (0xCF2A - (idx))
+#define   C20_PHY_TX_RATE  REG_GENMASK(2, 0)
 #define PHY_C20_A_CMN_CNTX_CFG(idx)(0xCDAA - (idx))
 #define PHY_C20_B_CMN_CNTX_CFG(idx)(0xCDA5 - (idx))
 #define PHY_C20_A_MPLLA_

[Intel-gfx] [PATCH v2 02/13] drm/i915/mtl: C20 HW readout

2023-04-28 Thread Mika Kahola
Create a table for C20 DP1.4, DP2.0 and HDMI2.1 rates.
The PLL settings are based on table, not for algorithmic alternative.
For DP 1.4 only MPLLB is in use.

Once register settings are done, we read back C20 HW state.

BSpec: 64568

v2: Updated pll tables (RK)
MPLLB selection fix (RK)

Signed-off-by: Mika Kahola 
Signed-off-by: Arun R Murthy 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 624 +-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   8 +-
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   1 +
 drivers/gpu/drm/i915/display/intel_ddi.c  |   9 +-
 .../drm/i915/display/intel_display_types.h|   1 +
 drivers/gpu/drm/i915/display/intel_hdmi.c |   6 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h |   1 +
 7 files changed, 630 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 71163bc5bbf5..f58b3112baea 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -11,6 +11,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_hdmi.h"
 #include "intel_panel.h"
 #include "intel_psr.h"
 #include "intel_tc.h"
@@ -285,6 +286,23 @@ static void intel_c20_sram_write(struct drm_i915_private 
*i915, enum port port,
intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1);
 }
 
+static u16 intel_c20_sram_read(struct drm_i915_private *i915, enum port port,
+  int lane, u16 addr)
+{
+   u16 val;
+
+   assert_dc_off(i915);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_H, addr >> 8, 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 1);
+
+   val = intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_H);
+   val <<= 8;
+   val |= intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_L);
+
+   return val;
+}
+
 static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
int lane, u16 addr, u8 clear, u8 set, bool 
committed)
 {
@@ -659,6 +677,199 @@ static const struct intel_c10pll_state * const 
mtl_c10_edp_tables[] = {
NULL,
 };
 
+/* C20 basic DP 1.4 tables */
+static const struct intel_c20pll_state mtl_c20_dp_rbr = {
+   .link_bit_rate = 162000,
+   .clock = 162000,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x5800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x50a8,  /* mpllb cfg0 */
+   0x2120, /* mpllb cfg1 */
+   0xcd9a, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x5ab8, /* mpllb cfg4 */
+   0x4c34, /* mpllb cfg5 */
+   0x2000, /* mpllb cfg6 */
+   0x0001, /* mpllb cfg7 */
+   0x6000, /* mpllb cfg8 */
+   0x, /* mpllb cfg9 */
+   0x, /* mpllb cfg10 */
+   },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr1 = {
+   .link_bit_rate = 27,
+   .clock = 27,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x4800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x308c,  /* mpllb cfg0 */
+   0x2110, /* mpllb cfg1 */
+   0xcc9c, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x4b9a, /* mpllb cfg4 */
+   0x3f81, /* mpllb cfg5 */
+   0x2000, /* mpllb cfg6 */
+   0x0001, /* mpllb cfg7 */
+   0x5000, /* mpllb cfg8 */
+   0x, /* mpllb cfg9 */
+   0x, /* mpllb cfg10 */
+   },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr2 = {
+   .link_bit_rate = 54,
+   .clock = 54,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x4800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x108c,  /* mpllb cfg0 */
+   0x2108, /* mpllb cfg1 */
+   0xcc9c, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */

[Intel-gfx] [PATCH v2 01/13] drm/i915/mtl: C20 PLL programming

2023-04-28 Thread Mika Kahola
C20 phy PLL programming sequence for DP, DP2.0, HDMI2.x non-FRL and
HDMI2.x FRL. This enables C20 MPLLA and MPLLB programming sequence. add
4 lane support for c20.

v2: Add 6.48Gbps and 6.75Gbps modes for eDP (RK)
Fix lane check (RK)
Fix multiline commenting (Arun)
use usleep_range() instead of msleep() (Andi)

Reviewed-by: Arun R Murthy 
Signed-off-by: José Roberto de Souza 
Signed-off-by: Mika Kahola 
Signed-off-by: Bhanuprakash Modem 
Signed-off-by: Imre Deak 
Signed-off-by: Arun R Murthy 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 288 +++---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  33 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |   3 +-
 .../drm/i915/display/intel_display_types.h|  15 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  12 +-
 5 files changed, 309 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 83180074b512..71163bc5bbf5 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -273,6 +273,18 @@ static void intel_cx0_write(struct drm_i915_private *i915, 
enum port port,
__intel_cx0_write(i915, port, lane, addr, data, committed);
 }
 
+static void intel_c20_sram_write(struct drm_i915_private *i915, enum port port,
+int lane, u16 addr, u16 data)
+{
+   assert_dc_off(i915);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_H, addr >> 8, 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_H, data >> 8, 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1);
+}
+
 static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
int lane, u16 addr, u8 clear, u8 set, bool 
committed)
 {
@@ -1415,6 +1427,215 @@ void intel_c10pll_dump_hw_state(struct drm_i915_private 
*i915,
i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i 
+ 3]);
 }
 
+static bool intel_c20_use_mplla(u32 clock)
+{
+   /* 10G and 20G rates use MPLLA */
+   if (clock == 312500 || clock == 625000)
+   return true;
+
+   return false;
+}
+
+static u8 intel_c20_get_dp_rate(u32 clock)
+{
+   switch (clock) {
+   case 162000: /* 1.62 Gbps DP1.4 */
+   return 0;
+   case 27: /* 2.7 Gbps DP1.4 */
+   return 1;
+   case 54: /* 5.4 Gbps DP 1.4 */
+   return 2;
+   case 81: /* 8.1 Gbps DP1.4 */
+   return 3;
+   case 216000: /* 2.16 Gbps eDP */
+   return 4;
+   case 243000: /* 2.43 Gbps eDP */
+   return 5;
+   case 324000: /* 3.24 Gbps eDP */
+   return 6;
+   case 432000: /* 4.32 Gbps eDP */
+   return 7;
+   case 312500: /* 10 Gbps DP2.0 */
+   return 8;
+   case 421875: /* 13.5 Gbps DP2.0 */
+   return 9;
+   case 625000: /* 20 Gbps DP2.0*/
+   return 10;
+   case 648000: /* 6.48 Gbps eDP*/
+   return 11;
+   case 675000: /* 6.75 Gbps eDP*/
+   return 12;
+   default:
+   MISSING_CASE(clock);
+   return 0;
+   }
+}
+
+static u8 intel_c20_get_hdmi_rate(u32 clock)
+{
+   switch (clock) {
+   case 25175:
+   case 27000:
+   case 74250:
+   case 148500:
+   case 594000:
+   return 0;
+   case 166670: /* 3 Gbps */
+   case 30: /* 6 Gbps */
+   case 70: /* 12 Gbps */
+   return 1;
+   case 40: /* 8 Gbps */
+   return 2;
+   case 60: /* 10 Gbps */
+   return 3;
+   default:
+   MISSING_CASE(clock);
+   return 0;
+   }
+}
+
+static bool is_dp2(u32 clock)
+{
+   /* DP2.0 clock rates */
+   if (clock == 312500 || clock == 421875 || clock  == 625000)
+   return true;
+
+   return false;
+}
+
+static bool is_hdmi_frl(u32 clock)
+{
+   switch (clock) {
+   case 166670: /* 3 Gbps */
+   case 30: /* 6 Gbps */
+   case 40: /* 8 Gbps */
+   case 60: /* 10 Gbps */
+   case 70: /* 12 Gbps */
+   return true;
+   default:
+   return false;
+   }
+}
+
+static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder)
+{
+   struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+
+   /* banks should not be cleared for DPALT/USB4/TBT modes */
+   /* TODO: optimize re-calibration in legacy mode */
+   return intel_tc_port_in_legacy_mode(intel_dig_port);
+}
+
+static int intel_get_c20_custom_width(u32 clock, bool dp)
+{
+   if (dp && is_dp2(clock))
+   return 2;
+   else if (is_hdmi_frl(clock))
+   

[Intel-gfx] [PATCH v2 00/13] drm/i915/mtl: Add support for C20 phy

2023-04-28 Thread Mika Kahola
Add support for C20 phy for Type-C connections. C20 phy differs from
C10 and hence we need to separately handle this case.

v2: Fixes for C20 pll programming and hw readout

Signed-off-by: Mika Kahola 

Anusha Srivatsa (1):
  drm/i915/mtl: Pin assignment for TypeC

Gustavo Sousa (1):
  drm/i915/mtl: Define mask for DDI AUX interrupts

Imre Deak (1):
  drm/i915/mtl: TypeC HPD live status query

Mika Kahola (10):
  drm/i915/mtl: C20 PLL programming
  drm/i915/mtl: C20 HW readout
  drm/i915/mtl: Dump C20 pll hw state
  drm/i915/mtl: C20 port clock calculation
  drm/i915/mtl: Add voltage swing sequence for C20
  drm/i915/mtl: For DP2.0 10G and 20G rates use MPLLA
  drm/i915/mtl: Enabling/disabling sequence Thunderbolt pll
  drm/i915/mtl: Readout Thunderbolt HW state
  drm/i915/mtl: Power up TCSS
  drm/i915/mtl: Enable TC ports

 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 1137 -
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   23 +-
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   41 +
 drivers/gpu/drm/i915/display/intel_ddi.c  |   25 +-
 .../drm/i915/display/intel_ddi_buf_trans.c|   53 +-
 drivers/gpu/drm/i915/display/intel_display.c  |7 +-
 .../drm/i915/display/intel_display_types.h|   16 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |   12 +-
 drivers/gpu/drm/i915/display/intel_dpll.c |2 +
 drivers/gpu/drm/i915/display/intel_hdmi.c |6 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h |1 +
 drivers/gpu/drm/i915/display/intel_tc.c   |  255 +++-
 drivers/gpu/drm/i915/i915_irq.c   |5 +-
 13 files changed, 1510 insertions(+), 73 deletions(-)

-- 
2.34.1



[Intel-gfx] [PATCH 13/13] drm/i915/mtl: Enable TC ports

2023-04-20 Thread Mika Kahola
Finally, we can enable TC ports for Meteorlake.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_display.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index e70bdf0e06f3..dc777c3b1b1a 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7587,9 +7587,12 @@ void intel_setup_outputs(struct drm_i915_private 
*dev_priv)
return;
 
if (IS_METEORLAKE(dev_priv)) {
-   /* TODO: initialize TC ports as well */
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
+   intel_ddi_init(dev_priv, PORT_TC1);
+   intel_ddi_init(dev_priv, PORT_TC2);
+   intel_ddi_init(dev_priv, PORT_TC3);
+   intel_ddi_init(dev_priv, PORT_TC4);
} else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
-- 
2.34.1



[Intel-gfx] [PATCH 12/13] drm/i915/mtl: Pin assignment for TypeC

2023-04-20 Thread Mika Kahola
From: Anusha Srivatsa 

Unlike previous platforms that used PORT_TX_DFLEXDPSP
for max_lane calculation, MTL uses only PORT_TX_DFLEXPA1
from which the max_lanes has to be calculated.

Bspec: 50235, 65380

Signed-off-by: Anusha Srivatsa 
Signed-off-by: Jose Roberto de Souza 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 28 +
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index b192265a3d78..4fca711a58bc 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -16,6 +16,10 @@
 #include "intel_mg_phy_regs.h"
 #include "intel_tc.h"
 
+#define DP_PIN_ASSIGNMENT_C0x3
+#define DP_PIN_ASSIGNMENT_D0x4
+#define DP_PIN_ASSIGNMENT_E0x5
+
 enum tc_port_mode {
TC_PORT_DISCONNECTED,
TC_PORT_TBT_ALT,
@@ -281,6 +285,27 @@ u32 intel_tc_port_get_pin_assignment_mask(struct 
intel_digital_port *dig_port)
   DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
 }
 
+static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port 
*dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   intel_wakeref_t wakeref;
+   u32 pin_mask;
+
+   with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+   pin_mask = intel_tc_port_get_pin_assignment_mask(dig_port);
+
+   switch (pin_mask) {
+   default:
+   MISSING_CASE(pin_mask);
+   fallthrough;
+   case DP_PIN_ASSIGNMENT_D:
+   return 2;
+   case DP_PIN_ASSIGNMENT_C:
+   case DP_PIN_ASSIGNMENT_E:
+   return 4;
+   }
+}
+
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -294,6 +319,9 @@ int intel_tc_port_fia_max_lane_count(struct 
intel_digital_port *dig_port)
 
assert_tc_cold_blocked(tc);
 
+   if (DISPLAY_VER(i915) >= 14)
+   return mtl_tc_port_get_pin_assignment_mask(dig_port);
+
lane_mask = 0;
with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
lane_mask = intel_tc_port_get_lane_mask(dig_port);
-- 
2.34.1



[Intel-gfx] [PATCH 10/13] drm/i915/mtl: Power up TCSS

2023-04-20 Thread Mika Kahola
Add register writes to enable powering up Type-C subsystem i.e. TCSS.
For MeteorLake we need to request TCSS to power up and check the TCSS
power state after 500 us.

In addition, for PICA we need to set/clear the Type-C PHY ownnership
bit when Type-C device is connected/disconnected.

Signed-off-by: Mika Kahola 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c |  19 ++
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   4 +
 drivers/gpu/drm/i915/display/intel_ddi.c |   1 +
 drivers/gpu/drm/i915/display/intel_display.c |   2 +-
 drivers/gpu/drm/i915/display/intel_tc.c  | 199 ++-
 5 files changed, 216 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index dc005e61..97d80adb921f 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2884,6 +2884,25 @@ void intel_mtl_pll_disable(struct intel_encoder *encoder)
intel_cx0pll_disable(encoder);
 }
 
+enum icl_port_dpll_id
+intel_mtl_port_pll_type(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   /*
+* TODO: Determine the PLL type from the SW state, once MTL PLL
+* handling is done via the standard shared DPLL framework.
+*/
+   u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+   u32 clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+   if (clock == XELPDP_DDI_CLOCK_SELECT_MAXPCLK ||
+   clock == XELPDP_DDI_CLOCK_SELECT_DIV18CLK)
+   return ICL_PORT_DPLL_MG_PHY;
+   else
+   return ICL_PORT_DPLL_DEFAULT;
+}
+
 void intel_c10pll_state_verify(struct intel_atomic_state *state,
   struct intel_crtc_state *new_crtc_state)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index c1b8f7980f69..f99809af257d 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -16,12 +16,16 @@
 struct drm_i915_private;
 struct intel_encoder;
 struct intel_crtc_state;
+enum icl_port_dpll_id;
 enum phy;
 
 bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy);
 void intel_mtl_pll_enable(struct intel_encoder *encoder,
  const struct intel_crtc_state *crtc_state);
 void intel_mtl_pll_disable(struct intel_encoder *encoder);
+enum icl_port_dpll_id
+intel_mtl_port_pll_type(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state);
 void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct 
intel_c10pll_state *pll_state);
 int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct 
intel_encoder *encoder);
 void intel_c10pll_dump_hw_state(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 8f0f858cde31..55f36d9d509c 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4784,6 +4784,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, 
enum port port)
if (DISPLAY_VER(dev_priv) >= 14) {
encoder->enable_clock = intel_mtl_pll_enable;
encoder->disable_clock = intel_mtl_pll_disable;
+   encoder->port_pll_type = intel_mtl_port_pll_type;
encoder->get_config = mtl_ddi_get_config;
} else if (IS_DG2(dev_priv)) {
encoder->enable_clock = intel_mpllb_enable;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 1c264c17b6e4..e70bdf0e06f3 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1757,7 +1757,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, 
enum phy phy)
if (IS_DG2(dev_priv))
/* DG2's "TC1" output uses a SNPS PHY */
return false;
-   else if (IS_ALDERLAKE_P(dev_priv))
+   else if (IS_ALDERLAKE_P(dev_priv) || IS_METEORLAKE(dev_priv))
return phy >= PHY_F && phy <= PHY_I;
else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 3b60995e9dfb..951b12ac51dc 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -5,6 +5,7 @@
 
 #include "i915_drv.h"
 #include "i915_reg.h"
+#include "intel_cx0_phy_regs.h"
 #include "intel_ddi.h"
 #include "intel_de.h"
 #include "intel_display.h"
@@ -59,6 +60,7 @@ 

[Intel-gfx] [PATCH 05/13] drm/i915/mtl: Add voltage swing sequence for C20

2023-04-20 Thread Mika Kahola
DP1.4 and DP20 voltage swing sequence for C20 phy.

Bspec: 65449, 67636, 67610

Signed-off-by: Mika Kahola 
Signed-off-by: Clint Taylor 
Signed-off-by: Radhakrishna Sripada 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  4 ++
 .../drm/i915/display/intel_ddi_buf_trans.c| 53 ++-
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index a5e5bee24533..5305cc8aad8e 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -211,6 +211,10 @@
 #define   C20_MULTIPLIER_MASK  REG_GENMASK(11, 0)
 #define   C20_PHY_USE_MPLLBREG_BIT(7)
 
+/* C20 Phy VSwing Masks */
+#define C20_PHY_VSWING_PREEMPH_MASKREG_GENMASK8(5, 0)
+#define C20_PHY_VSWING_PREEMPH(val)
REG_FIELD_PREP8(C20_PHY_VSWING_PREEMPH_MASK, val)
+
 #define RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(idx) (0x303D + (idx))
 
 #endif /* __INTEL_CX0_REG_DEFS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c 
b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index cd4becbae098..b7d20485bde5 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -9,6 +9,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_cx0_phy.h"
 
 /* HDMI/DVI modes ignore everything but the last 2 items. So we share
  * them for both DP and FDI transports, allowing those ports to
@@ -1048,12 +1049,52 @@ static const union intel_ddi_buf_trans_entry 
_mtl_c10_trans_dp14[] = {
{ .snps = { 62, 0, 0  } },  /* preset 9 */
 };
 
-static const struct intel_ddi_buf_trans mtl_cx0c10_trans = {
+static const struct intel_ddi_buf_trans mtl_cx0_trans = {
.entries = _mtl_c10_trans_dp14,
.num_entries = ARRAY_SIZE(_mtl_c10_trans_dp14),
.hdmi_default_entry = ARRAY_SIZE(_mtl_c10_trans_dp14) - 1,
 };
 
+/* DP2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_uhbr[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 43, 0, 5 } },   /* preset 1 */
+   { .snps = { 40, 0, 8 } },   /* preset 2 */
+   { .snps = { 37, 0, 11 } },  /* preset 3 */
+   { .snps = { 33, 0, 15 } },  /* preset 4 */
+   { .snps = { 46, 2, 0 } },   /* preset 5 */
+   { .snps = { 42, 2, 4 } },   /* preset 6 */
+   { .snps = { 38, 2, 8 } },   /* preset 7 */
+   { .snps = { 35, 2, 11 } },  /* preset 8 */
+   { .snps = { 33, 2, 13 } },  /* preset 9 */
+   { .snps = { 44, 4, 0 } },   /* preset 10 */
+   { .snps = { 40, 4, 4 } },   /* preset 11 */
+   { .snps = { 37, 4, 7 } },   /* preset 12 */
+   { .snps = { 33, 4, 11 } },  /* preset 13 */
+   { .snps = { 40, 8, 0 } },   /* preset 14 */
+   { .snps = { 28, 2, 2 } },   /* preset 15 */
+};
+
+/* HDMI2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_hdmi[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 38, 4, 6 } },   /* preset 1 */
+   { .snps = { 36, 4, 8 } },   /* preset 2 */
+   { .snps = { 34, 4, 10 } },  /* preset 3 */
+   { .snps = { 32, 4, 12 } },  /* preset 4 */
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_hdmi = {
+   .entries = _mtl_c20_trans_hdmi,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_hdmi),
+   .hdmi_default_entry = 0,
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_uhbr = {
+   .entries = _mtl_c20_trans_uhbr,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_uhbr),
+};
+
 bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table)
 {
return table == _combo_phy_trans_edp_hbr2_hobl;
@@ -1630,7 +1671,15 @@ mtl_get_cx0_buf_trans(struct intel_encoder *encoder,
  const struct intel_crtc_state *crtc_state,
  int *n_entries)
 {
-   return intel_get_buf_trans(_cx0c10_trans, n_entries);
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+   if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock >= 
100)
+   return intel_get_buf_trans(_c20_trans_uhbr, n_entries);
+   else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && 
!(intel_is_c10phy(i915, phy)))
+   return intel_get_buf_trans(_c20_trans_hdmi, n_entries);
+   else
+   return intel_get_buf_trans(_cx0_trans, n_entries);
 }
 
 void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
-- 
2.34.1



[Intel-gfx] [PATCH 06/13] drm/i915/mtl: For DP2.0 10G and 20G rates use MPLLA

2023-04-20 Thread Mika Kahola
Use MPLLA for DP2.0 rates 20G and 20G, when ssc is enabled.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index f7720acaf58c..4231ba98f075 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2340,8 +2340,11 @@ static void intel_program_port_clock_ctl(struct 
intel_encoder *encoder,
val |= XELPDP_DDI_CLOCK_SELECT(XELPDP_DDI_CLOCK_SELECT_MAXPCLK);
 
/* TODO: HDMI FRL */
-   /* TODO: DP2.0 10G and 20G rates enable MPLLA*/
-   val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 
0;
+   /* DP2.0 10G and 20G rates enable MPLLA*/
+   if (crtc_state->port_clock == 100 || crtc_state->port_clock == 
200)
+   val |= crtc_state->cx0pll_state.ssc_enabled ? 
XELPDP_SSC_ENABLE_PLLA : 0;
+   else
+   val |= crtc_state->cx0pll_state.ssc_enabled ? 
XELPDP_SSC_ENABLE_PLLB : 0;
 
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
 XELPDP_LANE1_PHY_CLOCK_SELECT | 
XELPDP_FORWARD_CLOCK_UNGATE |
-- 
2.34.1



[Intel-gfx] [PATCH 07/13] drm/i915/mtl: Enabling/disabling sequence Thunderbolt pll

2023-04-20 Thread Mika Kahola
Enabling and disabling sequence for Thunderbolt PLL.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 135 ++-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   7 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |   4 +-
 3 files changed, 138 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 4231ba98f075..9722d3f1b926 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2600,8 +2600,8 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane_mask)
return val;
 }
 
-void intel_cx0pll_enable(struct intel_encoder *encoder,
-const struct intel_crtc_state *crtc_state)
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
@@ -2676,7 +2676,86 @@ void intel_cx0pll_enable(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
-void intel_cx0pll_disable(struct intel_encoder *encoder)
+static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
+{
+   switch (clock) {
+   case 162000:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   case 27:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_270;
+   case 54:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_540;
+   case 81:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_810;
+   default:
+   MISSING_CASE(clock);
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   }
+}
+
+static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+   u32 val = 0;
+
+   /*
+* 1. Program PORT_CLOCK_CTL REGISTER to configure
+* clock muxes, gating and SSC
+*/
+   val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(i915, 
crtc_state->port_clock));
+   val |= XELPDP_FORWARD_CLOCK_UNGATE;
+   intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+XELPDP_DDI_CLOCK_SELECT_MASK | 
XELPDP_FORWARD_CLOCK_UNGATE, val);
+
+   /* 2. Read back PORT_CLOCK_CTL REGISTER */
+   val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   /*
+* 3. Follow the Display Voltage Frequency Switching - Sequence
+* Before Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 4. Set PORT_CLOCK_CTL register TBT CLOCK Request to "1" to enable 
PLL.
+*/
+   val |= XELPDP_TBT_CLOCK_REQUEST;
+   intel_de_write(i915, XELPDP_PORT_CLOCK_CTL(encoder->port), val);
+
+   /* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */
+   if (__intel_wait_for_register(>uncore, 
XELPDP_PORT_CLOCK_CTL(encoder->port),
+ XELPDP_TBT_CLOCK_ACK,
+ XELPDP_TBT_CLOCK_ACK,
+ 100, 0, NULL))
+   drm_warn(>drm, "[ENCODER:%d:%s][%c] PHY PLL not locked 
after 100us.\n",
+encoder->base.base.id, encoder->base.name, 
phy_name(phy));
+
+   /*
+* 6. Follow the Display Voltage Frequency Switching Sequence After
+* Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 7. Program DDI_CLK_VALFREQ to match intended DDI
+* clock frequency.
+*/
+   intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+  crtc_state->port_clock);
+}
+
+void intel_mtl_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+   if (intel_tc_port_in_tbt_alt_mode(dig_port))
+   intel_mtl_tbt_pll_enable(encoder, crtc_state);
+   else
+   intel_cx0pll_enable(encoder, crtc_state);
+}
+
+static void intel_cx0pll_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);
@@ -2728,6 +2807,56 @@ void intel_cx0pll_disable(struct intel_encoder *encoder)
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+static void intel_mtl_tbt_pll_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);
+
+   /*
+*

[Intel-gfx] [PATCH 09/13] drm/i915/mtl: Define mask for DDI AUX interrupts

2023-04-20 Thread Mika Kahola
From: Gustavo Sousa 

Xe_LPD+ defines interrupt bits for only DDI ports in the DE Port
Interrupt registers. The bits for Type-C ports are defined in the PICA
interrupt registers.

BSpec: 50064
Signed-off-by: Gustavo Sousa 
---
 drivers/gpu/drm/i915/i915_irq.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2b94b8ca8ec9..e5f12aa141f6 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1938,7 +1938,10 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private 
*dev_priv)
 {
u32 mask;
 
-   if (DISPLAY_VER(dev_priv) >= 13)
+   if (DISPLAY_VER(dev_priv) >= 14)
+   return TGL_DE_PORT_AUX_DDIA |
+   TGL_DE_PORT_AUX_DDIB;
+   else if (DISPLAY_VER(dev_priv) >= 13)
return TGL_DE_PORT_AUX_DDIA |
TGL_DE_PORT_AUX_DDIB |
TGL_DE_PORT_AUX_DDIC |
-- 
2.34.1



[Intel-gfx] [PATCH 11/13] drm/i915/mtl: TypeC HPD live status query

2023-04-20 Thread Mika Kahola
From: Imre Deak 

The HPD live status for MTL has to be read from different set of
registers. MTL deserves a new function for this purpose
and cannot reuse the existing  HPD live status detection

Signed-off-by: Anusha Srivatsa 
Signed-off-by: Imre Deak 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 30 -
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 951b12ac51dc..b192265a3d78 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -886,6 +886,34 @@ static const struct intel_tc_phy_ops adlp_tc_phy_ops = {
  * XELPDP TC PHY handlers
  * --
  */
+static u32 xelpdp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
+{
+   struct drm_i915_private *i915 = tc_to_i915(tc);
+   struct intel_digital_port *dig_port = tc->dig_port;
+   enum hpd_pin hpd_pin = dig_port->base.hpd_pin;
+   u32 pica_isr_bits = i915->display.hotplug.hpd[hpd_pin];
+   u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin];
+   intel_wakeref_t wakeref;
+   u32 pica_isr;
+   u32 pch_isr;
+   u32 mask = 0;
+
+   with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+   pica_isr = intel_de_read(i915, PICAINTERRUPT_ISR);
+   pch_isr = intel_de_read(i915, SDEISR);
+   }
+
+   if (pica_isr & (pica_isr_bits & XELPDP_DP_ALT_HOTPLUG_MASK))
+   mask |= BIT(TC_PORT_DP_ALT);
+   if (pica_isr & (pica_isr_bits & XELPDP_TBT_HOTPLUG_MASK))
+   mask |= BIT(TC_PORT_TBT_ALT);
+
+   if (tc->legacy_port && (pch_isr & pch_isr_bit))
+   mask |= BIT(TC_PORT_LEGACY);
+
+   return mask;
+}
+
 static bool
 xelpdp_tc_phy_tcss_power_is_enabled(struct intel_tc_port *tc)
 {
@@ -1039,7 +1067,7 @@ static void xelpdp_tc_phy_disconnect(struct intel_tc_port 
*tc)
 
 static const struct intel_tc_phy_ops xelpdp_tc_phy_ops = {
.cold_off_domain = tgl_tc_phy_cold_off_domain,
-   .hpd_live_status = adlp_tc_phy_hpd_live_status,
+   .hpd_live_status = xelpdp_tc_phy_hpd_live_status,
.is_ready = adlp_tc_phy_is_ready,
.is_owned = xelpdp_tc_phy_is_owned,
.get_hw_state = xelpdp_tc_phy_get_hw_state,
-- 
2.34.1



[Intel-gfx] [PATCH 03/13] drm/i915/mtl: Dump C20 pll hw state

2023-04-20 Thread Mika Kahola
As we already do with C10 chip, let's dump the pll
hw state for C20 as well.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 20 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 ++
 drivers/gpu/drm/i915/display/intel_ddi.c |  1 +
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 61428c5145e5..144474540ef4 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2035,6 +2035,26 @@ void intel_c20pll_readout_hw_state(struct intel_encoder 
*encoder,
}
 }
 
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+   const struct intel_c20pll_state *hw_state)
+{
+   int i;
+
+   drm_dbg_kms(>drm, "c20pll_hw_state:\n");
+   drm_dbg_kms(>drm, "tx[0] = 0x%.4x, tx[1] = 0x%.4x, tx[2] = 
0x%.4x\n",
+   hw_state->tx[0], hw_state->tx[1], hw_state->tx[2]);
+   drm_dbg_kms(>drm, "cmn[0] = 0x%.4x, cmn[1] = 0x%.4x, cmn[2] = 
0x%.4x, cmn[3] = 0x%.4x\n",
+   hw_state->cmn[0], hw_state->cmn[1], hw_state->cmn[2], 
hw_state->cmn[3]);
+
+   if (intel_c20_use_mplla(hw_state->clock)) {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mplla); i++)
+   drm_dbg_kms(>drm, "mplla[%d] = 0x%.4x\n", i, 
hw_state->mplla[i]);
+   } else {
+   for (i = 0; i < ARRAY_SIZE(hw_state->mpllb); i++)
+   drm_dbg_kms(>drm, "mpllb[%d] = 0x%.4x\n", i, 
hw_state->mpllb[i]);
+   }
+}
+
 static u8 intel_c20_get_dp_rate(u32 clock)
 {
switch (clock) {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 9760c6292c81..c643aae27bac 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -32,6 +32,8 @@ void intel_c10pll_state_verify(struct intel_atomic_state 
*state,
   struct intel_crtc_state *new_crtc_state);
 void intel_c20pll_readout_hw_state(struct intel_encoder *encoder,
   struct intel_c20pll_state *pll_state);
+void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
+   const struct intel_c20pll_state *hw_state);
 void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
 const struct intel_crtc_state *crtc_state);
 int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 44f07011245b..d414dd8c26bf 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3858,6 +3858,7 @@ static void mtl_ddi_get_config(struct intel_encoder 
*encoder,
intel_c10pll_dump_hw_state(i915, _state->cx0pll_state.c10);
} else {
intel_c20pll_readout_hw_state(encoder, 
_state->cx0pll_state.c20);
+   intel_c20pll_dump_hw_state(i915, _state->cx0pll_state.c20);
}
 
crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, 
_state->cx0pll_state.c10);
-- 
2.34.1



[Intel-gfx] [PATCH 08/13] drm/i915/mtl: Readout Thunderbolt HW state

2023-04-20 Thread Mika Kahola
Readout hw state for Thunderbolt.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 27 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |  5 +++-
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 9722d3f1b926..dc005e61 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2676,6 +2676,33 @@ static void intel_cx0pll_enable(struct intel_encoder 
*encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   u32 clock;
+   u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+   drm_WARN_ON(>drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_ACK));
+
+   switch (clock) {
+   case XELPDP_DDI_CLOCK_SELECT_TBT_162:
+   return 162000;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_270:
+   return 27;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_540:
+   return 54;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_810:
+   return 81;
+   default:
+   MISSING_CASE(clock);
+   return 162000;
+   }
+}
+
 static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
 {
switch (clock) {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 9ea6310b6d79..c1b8f7980f69 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -42,5 +42,5 @@ int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi 
*hdmi, int clock);
 void intel_cx0_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
   const struct intel_crtc_state 
*crtc_state,
   u32 level);
-int intel_mtl_tbt_readout_hw_state(struct intel_encoder *encoder);
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
 #endif /* __INTEL_CX0_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index c18226edacac..8f0f858cde31 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3852,8 +3852,11 @@ static void mtl_ddi_get_config(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_digital_port *dig_port = enc_to_dig_port(encoder);
 
-   if (intel_is_c10phy(i915, phy)) {
+   if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
+   crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
+   } else if (intel_is_c10phy(i915, phy)) {
intel_c10pll_readout_hw_state(encoder, 
_state->cx0pll_state.c10);
intel_c10pll_dump_hw_state(i915, _state->cx0pll_state.c10);
crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, 
_state->cx0pll_state.c10);
-- 
2.34.1



[Intel-gfx] [PATCH 04/13] drm/i915/mtl: C20 port clock calculation

2023-04-20 Thread Mika Kahola
Calculate port clock with C20 phy.

BSpec: 64568
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 45 +++
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |  2 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  4 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |  4 +-
 drivers/gpu/drm/i915/display/intel_dpll.c |  2 +
 5 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 144474540ef4..f7720acaf58c 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2274,6 +2274,51 @@ int intel_c10pll_calc_port_clock(struct intel_encoder 
*encoder,
return tmpclk;
 }
 
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+const struct intel_c20pll_state *pll_state)
+{
+   unsigned int frac, frac_en, frac_quot, frac_rem, frac_den;
+   unsigned int multiplier, refclk = 38400;
+   unsigned int tx_clk_div;
+   unsigned int ref_clk_mpllb_div;
+   unsigned int fb_clk_div4_en;
+   unsigned int ref, vco;
+   unsigned int tx_rate_mult;
+   unsigned int tx_rate = REG_FIELD_GET(C20_PHY_TX_RATE, pll_state->tx[0]);
+
+   if (pll_state->tx[0] & C20_PHY_USE_MPLLB) {
+   tx_rate_mult = 1;
+   frac_en = REG_FIELD_GET(C20_MPLLB_FRACEN, pll_state->mpllb[6]);
+   frac_quot = pll_state->mpllb[8];
+   frac_rem =  pll_state->mpllb[9];
+   frac_den =  pll_state->mpllb[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLB_TX_CLK_DIV_MASK, 
pll_state->mpllb[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = 0;
+   } else {
+   tx_rate_mult = 2;
+   frac_en = REG_FIELD_GET(C20_MPLLA_FRACEN, pll_state->mplla[6]);
+   frac_quot = pll_state->mplla[8];
+   frac_rem =  pll_state->mplla[9];
+   frac_den =  pll_state->mplla[7];
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mplla[0]);
+   tx_clk_div = REG_FIELD_GET(C20_MPLLA_TX_CLK_DIV_MASK, 
pll_state->mplla[1]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mplla[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mplla[0]);
+   }
+
+   if (frac_en)
+   frac = frac_quot + DIV_ROUND_CLOSEST(frac_rem, frac_den);
+   else
+   frac = 0;
+
+   ref = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << 
ref_clk_mpllb_div);
+   vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(ref, (multiplier << (17 - 2)) + 
frac) >> 17, 10);
+
+   return vco << tx_rate_mult >> tx_clk_div >> tx_rate;
+}
+
 static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
 const struct intel_crtc_state 
*crtc_state,
 bool lane_reversal)
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index c643aae27bac..83bd3500091b 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -34,6 +34,8 @@ void intel_c20pll_readout_hw_state(struct intel_encoder 
*encoder,
   struct intel_c20pll_state *pll_state);
 void intel_c20pll_dump_hw_state(struct drm_i915_private *i915,
const struct intel_c20pll_state *hw_state);
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+const struct intel_c20pll_state *pll_state);
 void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
 const struct intel_crtc_state *crtc_state);
 int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock);
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index 6fcb1680fb54..a5e5bee24533 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -195,17 +195,21 @@
 #define PHY_C20_VDR_CUSTOM_WIDTH   0xD02
 #define PHY_C20_A_TX_CNTX_CFG(idx) (0xCF2E - (idx))
 #define PHY_C20_B_TX_CNTX_CFG(idx) (0xCF2A - (idx))
+#define   C20_PHY_TX_RATE  REG_GENMASK(2, 0)
 #define PHY_C20_A_CMN_CNTX_CFG(idx)(0xCDAA - (idx))
 #define PHY_C20_B_CMN_CNTX_CFG(idx)(0xCDA5 - (idx))
 #define PHY_C20_A_MPLLA_CNTX_CFG(idx)  (0xCCF0 - (idx))
 #define PHY_C20_B_MPLLA_CNTX_CFG(idx)  (0xCCE5 - (idx))
 #define   C20_

[Intel-gfx] [PATCH 02/13] drm/i915/mtl: C20 HW readout

2023-04-20 Thread Mika Kahola
Create a table for C20 DP1.4, DP2.0 and HDMI2.1 rates.
The PLL settings are based on table, not for algorithmic alternative.
For DP 1.4 only MPLLB is in use.

Once register settings are done, we read back C20 HW state.

BSpec: 64568

Signed-off-by: Mika Kahola 
Signed-off-by: Arun R Murthy 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 623 +-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   8 +-
 drivers/gpu/drm/i915/display/intel_ddi.c  |   9 +-
 .../drm/i915/display/intel_display_types.h|   1 +
 drivers/gpu/drm/i915/display/intel_hdmi.c |   6 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h |   1 +
 6 files changed, 628 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index dd96bf5e179e..61428c5145e5 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -11,6 +11,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_hdmi.h"
 #include "intel_panel.h"
 #include "intel_psr.h"
 #include "intel_tc.h"
@@ -285,6 +286,23 @@ static void intel_c20_sram_write(struct drm_i915_private 
*i915, enum port port,
intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1);
 }
 
+static u16 intel_c20_sram_read(struct drm_i915_private *i915, enum port port,
+  int lane, u16 addr)
+{
+   u16 val;
+
+   assert_dc_off(i915);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_H, addr >> 8, 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 1);
+
+   val = intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_H);
+   val <<= 8;
+   val |= intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_L);
+
+   return val;
+}
+
 static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
int lane, u16 addr, u8 clear, u8 set, bool 
committed)
 {
@@ -659,6 +677,199 @@ static const struct intel_c10pll_state * const 
mtl_c10_edp_tables[] = {
NULL,
 };
 
+/* C20 basic DP 1.4 tables */
+static const struct intel_c20pll_state mtl_c20_dp_rbr = {
+   .link_bit_rate = 162000,
+   .clock = 162000,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x5800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x50a8,  /* mpllb cfg0 */
+   0x2120, /* mpllb cfg1 */
+   0xcd9a, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x5ab8, /* mpllb cfg4 */
+   0x4c34, /* mpllb cfg5 */
+   0x2000, /* mpllb cfg6 */
+   0x0001, /* mpllb cfg7 */
+   0x6000, /* mpllb cfg8 */
+   0x, /* mpllb cfg9 */
+   0x, /* mpllb cfg10 */
+   },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr1 = {
+   .link_bit_rate = 27,
+   .clock = 27,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x4800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x308c,  /* mpllb cfg0 */
+   0x2110, /* mpllb cfg1 */
+   0xcc9c, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x489a, /* mpllb cfg4 */
+   0x3f81, /* mpllb cfg5 */
+   0x2000, /* mpllb cfg6 */
+   0x0001, /* mpllb cfg7 */
+   0x5000, /* mpllb cfg8 */
+   0x, /* mpllb cfg9 */
+   0x, /* mpllb cfg10 */
+   },
+};
+
+static const struct intel_c20pll_state mtl_c20_dp_hbr2 = {
+   .link_bit_rate = 54,
+   .clock = 54,
+   .tx = { 0xbe88, /* tx cfg0 */
+   0x4800, /* tx cfg1 */
+   0x, /* tx cfg2 */
+   },
+   .cmn = {0x0500, /* cmn cfg0*/
+   0x0005, /* cmn cfg1 */
+   0x, /* cmn cfg2 */
+   0x, /* cmn cfg3 */
+   },
+   .mpllb = { 0x108c,  /* mpllb cfg0 */
+   0x2108, /* mpllb cfg1 */
+   0xcc9c, /* mpllb cfg2 */
+   0xbfc1, /* mpllb cfg3 */
+   0x489a, /* mpllb cfg4 */
+   0x3f81, /* mpllb cfg5 */
+   

[Intel-gfx] [PATCH 01/13] drm/i915/mtl: C20 PLL programming

2023-04-20 Thread Mika Kahola
C20 phy PLL programming sequence for DP, DP2.0, HDMI2.x non-FRL and
HDMI2.x FRL. This enables C20 MPLLA and MPLLB programming sequence. add
4 lane support for c20.

Signed-off-by: José Roberto de Souza 
Signed-off-by: Mika Kahola 
Signed-off-by: Bhanuprakash Modem 
Signed-off-by: Imre Deak 
Signed-off-by: Arun R Murthy 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 280 +++---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  32 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |   3 +-
 .../drm/i915/display/intel_display_types.h|  15 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  12 +-
 5 files changed, 300 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 83180074b512..dd96bf5e179e 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -273,6 +273,18 @@ static void intel_cx0_write(struct drm_i915_private *i915, 
enum port port,
__intel_cx0_write(i915, port, lane, addr, data, committed);
 }
 
+static void intel_c20_sram_write(struct drm_i915_private *i915, enum port port,
+int lane, u16 addr, u16 data)
+{
+   assert_dc_off(i915);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_H, addr >> 8, 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0);
+
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_H, data >> 8, 0);
+   intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1);
+}
+
 static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port,
int lane, u16 addr, u8 clear, u8 set, bool 
committed)
 {
@@ -1415,6 +1427,207 @@ void intel_c10pll_dump_hw_state(struct drm_i915_private 
*i915,
i + 2, hw_state->pll[i + 2], i + 3, hw_state->pll[i 
+ 3]);
 }
 
+static bool intel_c20_use_mplla(u32 clock)
+{
+   /* 10G and 20G rates use MPLLA */
+   if (clock == 312500 || clock == 625000)
+   return true;
+
+   return false;
+}
+
+static u8 intel_c20_get_dp_rate(u32 clock)
+{
+   switch (clock) {
+   case 162000: /* 1.62 Gbps DP1.4 */
+   return 0;
+   case 27: /* 2.7 Gbps DP1.4 */
+   return 1;
+   case 54: /* 5.4 Gbps DP 1.4 */
+   return 2;
+   case 81: /* 8.1 Gbps DP1.4 */
+   return 3;
+   case 216000: /* 2.16 Gbps eDP */
+   return 4;
+   case 243000: /* 2.43 Gbps eDP */
+   return 5;
+   case 324000: /* 3.24 Gbps eDP */
+   return 6;
+   case 432000: /* 4.32 Gbps eDP */
+   return 7;
+   case 312500: /* 10 Gbps DP2.0 */
+   return 8;
+   case 421875: /* 13.5 Gbps DP2.0 */
+   return 9;
+   case 625000: /* 20 Gbps DP2.0*/
+   return 10;
+   default:
+   MISSING_CASE(clock);
+   return 0;
+   }
+}
+
+static u8 intel_c20_get_hdmi_rate(u32 clock)
+{
+   switch (clock) {
+   case 25175:
+   case 27000:
+   case 74250:
+   case 148500:
+   case 594000:
+   return 0;
+   case 166670: /* 3 Gbps */
+   case 30: /* 6 Gbps */
+   case 70: /* 12 Gbps */
+   return 1;
+   case 40: /* 8 Gbps */
+   return 2;
+   case 60: /* 10 Gbps */
+   return 3;
+   default:
+   MISSING_CASE(clock);
+   return 0;
+   }
+}
+
+static bool is_dp2(u32 clock)
+{
+   /* DP2.0 clock rates */
+   if (clock == 312500 || clock == 421875 || clock  == 625000)
+   return true;
+
+   return false;
+}
+
+static bool is_hdmi_frl(u32 clock)
+{
+   switch (clock) {
+   case 166670: /* 3 Gbps */
+   case 30: /* 6 Gbps */
+   case 40: /* 8 Gbps */
+   case 60: /* 10 Gbps */
+   case 70: /* 12 Gbps */
+   return true;
+   default:
+   return false;
+   }
+}
+
+static bool intel_c20_protocol_switch_valid(struct intel_encoder *encoder)
+{
+   struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+
+   /* banks should not be cleared for DPALT/USB4/TBT modes */
+   /* TODO: optimize re-calibration in legacy mode */
+   return intel_tc_port_in_legacy_mode(intel_dig_port);
+}
+
+static void intel_c20_pll_program(struct drm_i915_private *i915,
+ const struct intel_crtc_state *crtc_state,
+ struct intel_encoder *encoder)
+{
+   const struct intel_c20pll_state *pll_state = 
_state->cx0pll_state.c20;
+   bool dp = false;
+   int lane = crtc_state->lane_count == 4 ? INTEL_CX0_BOTH_LANES : 
INTEL_CX0_LANE0;
+   bool cntx;
+   int i;
+
+   if (intel_crtc_has_dp_encoder(crtc_s

[Intel-gfx] [PATCH 00/13] drm/i915/mtl: Add support for C20 phy

2023-04-20 Thread Mika Kahola
Add support for C20 phy for Type-C connections. C20 phy differs from
C10 and hence we need to separately handle this case.

Signed-off-by: Mika Kahola 

Anusha Srivatsa (1):
  drm/i915/mtl: Pin assignment for TypeC

Gustavo Sousa (1):
  drm/i915/mtl: Define mask for DDI AUX interrupts

Imre Deak (1):
  drm/i915/mtl: TypeC HPD live status query

Mika Kahola (10):
  drm/i915/mtl: C20 PLL programming
  drm/i915/mtl: C20 HW readout
  drm/i915/mtl: Dump C20 pll hw state
  drm/i915/mtl: C20 port clock calculation
  drm/i915/mtl: Add voltage swing sequence for C20
  drm/i915/mtl: For DP2.0 10G and 20G rates use MPLLA
  drm/i915/mtl: Enabling/disabling sequence Thunderbolt pll
  drm/i915/mtl: Readout Thunderbolt HW state
  drm/i915/mtl: Power up TCSS
  drm/i915/mtl: Enable TC ports

 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 1128 -
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   23 +-
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   40 +
 drivers/gpu/drm/i915/display/intel_ddi.c  |   25 +-
 .../drm/i915/display/intel_ddi_buf_trans.c|   53 +-
 drivers/gpu/drm/i915/display/intel_display.c  |7 +-
 .../drm/i915/display/intel_display_types.h|   16 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |   12 +-
 drivers/gpu/drm/i915/display/intel_dpll.c |2 +
 drivers/gpu/drm/i915/display/intel_hdmi.c |6 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h |1 +
 drivers/gpu/drm/i915/display/intel_tc.c   |  255 +++-
 drivers/gpu/drm/i915/i915_irq.c   |5 +-
 13 files changed, 1500 insertions(+), 73 deletions(-)

-- 
2.34.1



[Intel-gfx] [PATCH v3 7/8] drm/i915/display/mtl: Fill port width in DDI_BUF_/TRANS_DDI_FUNC_/PORT_BUF_CTL for HDMI

2023-04-06 Thread Mika Kahola
From: Ankit Nautiyal 

MTL requires the PORT_CTL_WIDTH, TRANS_DDI_FUNC_CTL and DDI_BUF_CTL
to be filled with 4 lanes for TMDS mode.
This patch enables D2D link and fills PORT_WIDTH in appropriate
registers.

v2:
  - Added fixes from Clint's Add HDMI implementation changes.
  - Modified commit message.
v3:
  - Use TRANS_DDI_PORT_WIDTH() instead of DDI_PORT_WIDTH() for the value
of TRANS_DDI_FUNC_CTL_*. (Gustavo)

Signed-off-by: Ankit Nautiyal 
Signed-off-by: Taylor, Clinton A 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 48 +---
 drivers/gpu/drm/i915/i915_reg.h  |  2 +
 2 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index e97d7627d9d1..20b0844b8240 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -516,6 +516,8 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder 
*encoder,
temp |= TRANS_DDI_HDMI_SCRAMBLING;
if (crtc_state->hdmi_high_tmds_clock_ratio)
temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
+   if (DISPLAY_VER(dev_priv) >= 14)
+   temp |= TRANS_DDI_PORT_WIDTH(crtc_state->lane_count);
} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
temp |= (crtc_state->fdi_lanes - 1) << 1;
@@ -2891,6 +2893,10 @@ static void intel_enable_ddi_hdmi(struct 
intel_atomic_state *state,
if (has_buf_trans_select(dev_priv))
hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state);
 
+   /* e. Enable D2D Link for C10/C20 Phy */
+   if (DISPLAY_VER(dev_priv) >= 14)
+   mtl_ddi_enable_d2d(encoder);
+
encoder->set_signal_levels(encoder, crtc_state);
 
/* Display WA #1143: skl,kbl,cfl */
@@ -2936,13 +2942,39 @@ static void intel_enable_ddi_hdmi(struct 
intel_atomic_state *state,
 *
 * On ADL_P the PHY link rate and lane count must be programmed but
 * these are both 0 for HDMI.
+*
+* But MTL onwards HDMI2.1 is supported and in TMDS mode this
+* is always filled with 4 lanes, already set in the crtc_state.
+* The same is required to be filled in PORT_BUF_CTL for C10/20 Phy.
 */
-   buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
-   if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
-   drm_WARN_ON(_priv->drm, 
!intel_tc_port_in_legacy_mode(dig_port));
-   buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+   if (DISPLAY_VER(dev_priv) >= 14) {
+   u32 ddi_buf = 0;
+   u8  lane_count = mtl_get_port_width(crtc_state->lane_count);
+   u32 port_buf = 0;
+
+   port_buf |= XELPDP_PORT_WIDTH(lane_count);
+
+   if (intel_bios_is_lane_reversal_needed(dev_priv, port))
+   port_buf |= XELPDP_PORT_REVERSAL;
+
+   intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port), 0, port_buf);
+
+   ddi_buf |= DDI_BUF_CTL_ENABLE |
+  DDI_PORT_WIDTH(lane_count);
+
+   intel_de_write(dev_priv, DDI_BUF_CTL(port),
+  dig_port->saved_port_bits | ddi_buf);
+
+   /* i. Poll for PORT_BUF_CTL Idle Status == 0, timeout after 100 
us */
+   intel_wait_ddi_buf_active(dev_priv, port);
+   } else {
+   buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
+   if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) 
{
+   drm_WARN_ON(_priv->drm, 
!intel_tc_port_in_legacy_mode(dig_port));
+   buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
+   }
+   intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
}
-   intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
 
intel_wait_ddi_buf_active(dev_priv, port);
 
@@ -3357,7 +3389,11 @@ static void intel_ddi_read_func_ctl(struct intel_encoder 
*encoder,
fallthrough;
case TRANS_DDI_MODE_SELECT_DVI:
pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
-   pipe_config->lane_count = 4;
+   if (DISPLAY_VER(dev_priv) >= 14)
+   pipe_config->lane_count =
+   ((temp & DDI_PORT_WIDTH_MASK) >> 
DDI_PORT_WIDTH_SHIFT) + 1;
+   else
+   pipe_config->lane_count = 4;
break;
case TRANS_DDI_MODE_SELECT_DP_SST:
if (encoder->type == INTEL_OUTPUT_EDP)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8d49676148f2..c4d363248bd2 100644
--- a/drivers/gpu/drm/i915/i

[Intel-gfx] [PATCH v3 8/8] drm/i915/mtl/display: Implement DisplayPort sequences

2023-04-06 Thread Mika Kahola
From: José Roberto de Souza 

The differences between MTL and TGL DP sequences are big enough to
MTL have its own functions.

Also it is much easier to follow MTL sequences against spec with
its own functions.

One change worthy to mention is the move of
'intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain)'.
This call is not necessary for MTL but we have _put() counter part in
intel_ddi_post_disable_dp() that needs to balanced.
We could add a display version check on it but instead here it is
moving it to intel_ddi_pre_enable_dp() so it is executed for all
platforms in a single place and this will not cause any harm in MTL
and newer platforms.

v2:
 - Fix logic to wait for buf idle.
 - Use the right register to wait for ddi active.(RK)
v3:
 - Increase wait timeout for ddi buf active (Mika)
v4:
 - Increase idle timeout for ddi buf idle (Mika)

BSpec: 65448 65505
Acked-by: Matt Roper 
Signed-off-by: Satyeshwar Singh 
Signed-off-by: Clint Taylor 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Ankit Nautiyal 
Signed-off-by: José Roberto de Souza 
Signed-off-by: Mika Kahola 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   8 +
 drivers/gpu/drm/i915/display/intel_ddi.c  | 375 +-
 drivers/gpu/drm/i915/i915_reg.h   |   5 +
 3 files changed, 373 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index a72f79ea5e6c..e23f921a5168 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -59,8 +59,16 @@

 _XELPDP_PORT_BUF_CTL1_LN0_B, \

 _XELPDP_PORT_BUF_CTL1_LN0_USBC1, \

 _XELPDP_PORT_BUF_CTL1_LN0_USBC2))
+#define   XELPDP_PORT_BUF_D2D_LINK_ENABLE  REG_BIT(29)
+#define   XELPDP_PORT_BUF_D2D_LINK_STATE   REG_BIT(28)
 #define   XELPDP_PORT_BUF_SOC_PHY_READYREG_BIT(24)
+#define   XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK REG_GENMASK(19, 18)
+#define   XELPDP_PORT_BUF_PORT_DATA_10BIT  
REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 0)
+#define   XELPDP_PORT_BUF_PORT_DATA_20BIT  
REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 1)
+#define   XELPDP_PORT_BUF_PORT_DATA_40BIT  
REG_FIELD_PREP(XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK, 2)
 #define   XELPDP_PORT_REVERSAL REG_BIT(16)
+#define   XELPDP_PORT_BUF_IO_SELECTION REG_BIT(11)
+#define   XELPDP_PORT_BUF_PHY_IDLE REG_BIT(7)
 #define   XELPDP_TC_PHY_OWNERSHIP  REG_BIT(6)
 #define   XELPDP_TCSS_POWER_REQUESTREG_BIT(5)
 #define   XELPDP_TCSS_POWER_STATE  REG_BIT(4)
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 20b0844b8240..c3178cac3dee 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -40,6 +40,7 @@
 #include "intel_connector.h"
 #include "intel_crtc.h"
 #include "intel_cx0_phy.h"
+#include "intel_cx0_phy_regs.h"
 #include "intel_ddi.h"
 #include "intel_ddi_buf_trans.h"
 #include "intel_de.h"
@@ -170,6 +171,18 @@ static void hsw_prepare_hdmi_ddi_buffers(struct 
intel_encoder *encoder,
   trans->entries[level].hsw.trans2);
 }
 
+static void mtl_wait_ddi_buf_idle(struct drm_i915_private *i915, enum port 
port)
+{
+   int ret;
+
+   /* FIXME: find out why Bspec's 100us timeout is too short */
+   ret = wait_for_us((intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port)) &
+  XELPDP_PORT_BUF_PHY_IDLE), 1);
+   if (ret)
+   drm_err(>drm, "Timeout waiting for DDI BUF %c to get 
idle\n",
+   port_name(port));
+}
+
 void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
 enum port port)
 {
@@ -197,7 +210,9 @@ static void intel_wait_ddi_buf_active(struct 
drm_i915_private *dev_priv,
return;
}
 
-   if (IS_DG2(dev_priv)) {
+   if (DISPLAY_VER(dev_priv) >= 14) {
+   timeout_us = 1;
+   } else if (IS_DG2(dev_priv)) {
timeout_us = 1200;
} else if (DISPLAY_VER(dev_priv) >= 12) {
if (intel_phy_is_tc(dev_priv, phy))
@@ -208,8 +223,12 @@ static void intel_wait_ddi_buf_active(struct 
drm_i915_private *dev_priv,
timeout_us = 500;
}
 
-   ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
- DDI_BUF_IS_IDLE), timeout_us, 10, 10);
+   if (DISPL

[Intel-gfx] [PATCH v3 3/8] drm/i915/mtl: Create separate reg file for PICA registers

2023-04-06 Thread Mika Kahola
Create a separate file to store registers for PICA chips
C10 and C20.

v2: Rename file (Jani)
v3: Use _PICK_EVEN_2RANGES() macro (Lucas)
Coding style fixed (Lucas)
v4: Redefine macros (Imre)

Reviewed-by: Vinod Govindapillai  (v3)
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 133 ++
 1 file changed, 133 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
new file mode 100644
index ..27723c1a93d9
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_CX0_PHY_REGS_H__
+#define __INTEL_CX0_PHY_REGS_H__
+
+#include "i915_reg_defs.h"
+
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A  0x64040
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B  0x64140
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1  0x16F240
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2  0x16F440
+#define XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) 
_MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) + (lane) * 4)
+#define   XELPDP_PORT_M2P_TRANSACTION_PENDING  REG_BIT(31)
+#define   XELPDP_PORT_M2P_COMMAND_TYPE_MASKREG_GENMASK(30, 27)
+#define   XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1)
+#define   XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED  
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2)
+#define   XELPDP_PORT_M2P_COMMAND_READ 
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3)
+#define   XELPDP_PORT_M2P_DATA_MASKREG_GENMASK(23, 16)
+#define   XELPDP_PORT_M2P_DATA(val)
REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val)
+#define   XELPDP_PORT_M2P_TRANSACTION_RESETREG_BIT(15)
+#define   XELPDP_PORT_M2P_ADDRESS_MASK REG_GENMASK(11, 0)
+#define   XELPDP_PORT_M2P_ADDRESS(val) 
REG_FIELD_PREP(XELPDP_PORT_M2P_ADDRESS_MASK, val)
+#define XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)  
_MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) + (lane) * 4 + 8)
+#define   XELPDP_PORT_P2M_RESPONSE_READY   REG_BIT(31)
+#define   XELPDP_PORT_P2M_COMMAND_TYPE_MASKREG_GENMASK(30, 27)
+#define   XELPDP_PORT_P2M_COMMAND_READ_ACK 0x4
+#define   XELPDP_PORT_P2M_COMMAND_WRITE_ACK0x5
+#define   XELPDP_PORT_P2M_DATA_MASKREG_GENMASK(23, 16)
+#define   XELPDP_PORT_P2M_DATA(val)
REG_FIELD_PREP(XELPDP_PORT_P2M_DATA_MASK, val)
+#define   XELPDP_PORT_P2M_ERROR_SETREG_BIT(15)
+
+#define XELPDP_MSGBUS_TIMEOUT_SLOW 1
+#define XELPDP_MSGBUS_TIMEOUT_FAST_US  2
+#define XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US  3200
+#define XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US 20
+#define XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US   100
+#define XELPDP_PORT_RESET_START_TIMEOUT_US 5
+#define XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US100
+#define XELPDP_PORT_RESET_END_TIMEOUT  15
+#define XELPDP_REFCLK_ENABLE_TIMEOUT_US1
+
+#define _XELPDP_PORT_BUF_CTL1_LN0_A0x64004
+#define _XELPDP_PORT_BUF_CTL1_LN0_B0x64104
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC10x16F200
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC20x16F400
+#define XELPDP_PORT_BUF_CTL1(port) 
_MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+   
 _XELPDP_PORT_BUF_CTL1_LN0_A, \
+   
 _XELPDP_PORT_BUF_

[Intel-gfx] [PATCH v3 6/8] drm/i915/mtl: MTL PICA hotplug detection

2023-04-06 Thread Mika Kahola
PICA is used for DP alt mode and TBT modes. Hotplug interruption is routed
from PICA chip to south display engine and from there to north display
engine. This patch adds functionality to enable hotplug detection for
all Type-C ports (4 ports available).

Differently from HPD in south display, PICA provides a dedicated HPD
control register for each supported port, so we loop over ports
ourselves instead of using intel_hpd_hotplug_enables() or
intel_get_hpd_pins().

BSpec: 49305, 55726, 65107, 65300

Signed-off-by: Madhumitha Tolakanahalli Pradeep 

Signed-off-by: Gustavo Sousa 
Signed-off-by: Imre Deak 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/i915_irq.c | 249 +++-
 drivers/gpu/drm/i915/i915_reg.h |  31 +++-
 2 files changed, 273 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d24bdea65a3d..54ca5b65493f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -162,6 +162,13 @@ static const u32 hpd_gen11[HPD_NUM_PINS] = {
[HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | 
GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
 };
 
+static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
+   [HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
+   [HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
+   [HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
+   [HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
+};
+
 static const u32 hpd_icp[HPD_NUM_PINS] = {
[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
@@ -182,6 +189,16 @@ static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
[HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
 };
 
+static const u32 hpd_mtp[HPD_NUM_PINS] = {
+   [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
+   [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
+   [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
+   [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
+   [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
+   [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
+};
+
+
 static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
 {
struct intel_hotplug *hpd = _priv->display.hotplug;
@@ -195,7 +212,9 @@ static void intel_hpd_init_pins(struct drm_i915_private 
*dev_priv)
return;
}
 
-   if (DISPLAY_VER(dev_priv) >= 11)
+   if (DISPLAY_VER(dev_priv) >= 14)
+   hpd->hpd = hpd_xelpdp;
+   else if (DISPLAY_VER(dev_priv) >= 11)
hpd->hpd = hpd_gen11;
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
hpd->hpd = hpd_bxt;
@@ -214,6 +233,8 @@ static void intel_hpd_init_pins(struct drm_i915_private 
*dev_priv)
 
if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
hpd->pch_hpd = hpd_sde_dg1;
+   else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
+   hpd->pch_hpd = hpd_mtp;
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
hpd->pch_hpd = hpd_icp;
else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
@@ -1559,6 +1580,44 @@ static void cpt_irq_handler(struct drm_i915_private 
*dev_priv, u32 pch_iir)
cpt_serr_int_handler(dev_priv);
 }
 
+static void xelpdp_pica_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
+{
+   enum hpd_pin pin;
+   u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | 
XELPDP_TBT_HOTPLUG_MASK);
+   u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
+   u32 pin_mask = 0, long_mask = 0;
+
+   for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
+   u32 val;
+
+   if (!(dev_priv->display.hotplug.hpd[pin] & hotplug_trigger))
+   continue;
+
+   pin_mask |= BIT(pin);
+
+   val = intel_uncore_read(_priv->uncore, 
XELPDP_PORT_HOTPLUG_CTL(pin));
+   intel_uncore_write(_priv->uncore, 
XELPDP_PORT_HOTPLUG_CTL(pin), val);
+
+   if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | 
XELPDP_TBT_HPD_LONG_DETECT))
+   long_mask |= BIT(pin);
+   }
+
+   if (pin_mask) {
+   drm_dbg(_priv->drm,
+   "pica hotplug event received, stat 0x%08x, pins 0x%08x, 
long 0x%08x\n",
+   hotplug_trigger, pin_mask, long_mask);
+
+   intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+   }
+
+   if (trigger_aux)
+   dp_aux_irq_handler(dev_priv);
+
+   if (!pin_mask && !trigger_aux)
+   drm_err(_priv->drm,
+   "Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
+}
+
 static void icp_irq

[Intel-gfx] [PATCH v3 2/8] drm/i915/mtl: Add DP rates

2023-04-06 Thread Mika Kahola
Add DP rates for Meteorlake.

Reviewed-by: Vinod Govindapillai 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index f0bace9d98a1..3367ae98c2bd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -421,6 +421,11 @@ static int ehl_max_source_rate(struct intel_dp *intel_dp)
return 81;
 }
 
+static int mtl_max_source_rate(struct intel_dp *intel_dp)
+{
+   return intel_dp_is_edp(intel_dp) ? 675000 : 81;
+}
+
 static int vbt_max_link_rate(struct intel_dp *intel_dp)
 {
struct intel_encoder *encoder = _to_dig_port(intel_dp)->base;
@@ -445,6 +450,10 @@ static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
/* The values must be in increasing order */
+   static const int mtl_rates[] = {
+   162000, 216000, 243000, 27, 324000, 432000, 54, 675000,
+   81,
+   };
static const int icl_rates[] = {
162000, 216000, 27, 324000, 432000, 54, 648000, 81,
100, 135,
@@ -470,7 +479,11 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
drm_WARN_ON(_priv->drm,
intel_dp->source_rates || intel_dp->num_source_rates);
 
-   if (DISPLAY_VER(dev_priv) >= 11) {
+   if (DISPLAY_VER(dev_priv) >= 14) {
+   source_rates = mtl_rates;
+   size = ARRAY_SIZE(mtl_rates);
+   max_rate = mtl_max_source_rate(intel_dp);
+   } else if (DISPLAY_VER(dev_priv) >= 11) {
source_rates = icl_rates;
size = ARRAY_SIZE(icl_rates);
if (IS_DG2(dev_priv))
-- 
2.34.1



[Intel-gfx] [PATCH v3 4/8] drm/i915/mtl: Add Support for C10 PHY message bus and pll programming

2023-04-06 Thread Mika Kahola
From: Radhakrishna Sripada 

XELPDP has C10 and C20 phys from Synopsys to drive displays. Each phy
has a dedicated PIPE 5.2 Message bus for configuration. This message
bus is used to configure the phy internal registers.

XELPDP has C10 phys to drive output to the EDP and the native output
from the display engine. Add structures, programming hardware state
readout logic. Port clock calculations are similar to DG2. Use the DG2
formulae to calculate the port clock but use the relevant pll signals.
Note: PHY lane 0 is always used for PLL programming.

Add sequences for C10 phy enable/disable phy lane reset,
powerdown change sequence and phy lane programming.

Bspec: 64539, 64568, 64599, 65100, 65101, 65450, 65451, 67610, 67636

v2: Squash patches related to C10 phy message bus and pll
programming support (Jani)
Move register definitions to a new file i.e. intel_cx0_reg_defs.h (Jani)
Move macro definitions (Jani)
DP rates as separate patch (Jani)
Spin out xelpdp register definitions into a separate file (Jani)
Replace macro to select registers based on phy lane with
function calls (Jani)
Fix styling issues (Jani)
Call XELPDP_PORT_P2M_MSGBUS_STATUS() with port instead of phy (Lucas)
v3: Move clear request flag into try-loop
v4: On PHY idle change drm_err_once() as drm_dbg_kms() (Jani)
use __intel_de_wait_for_register() instead of __intel_wait_for_register
and uncomment intel_uncore.h (Jani)
Add DP-alt support for PHY lane programming (Khaled)
v4: Add tx and cmn on c10mpllb_state (Imre)
Add missing waits for pending transactions between two message bus
writes (Imre)
General cleanups and simplifications (Imre)

Cc: Mika Kahola 
Cc: Imre Deak 
Cc: Uma Shankar 
Cc: Gustavo Sousa 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 1206 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   44 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   53 +-
 drivers/gpu/drm/i915/display/intel_ddi.c  |   22 +-
 .../drm/i915/display/intel_display_types.h|   13 +
 drivers/gpu/drm/i915/display/intel_dpll.c |   26 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c |2 +-
 .../drm/i915/display/intel_modeset_verify.c   |2 +
 drivers/gpu/drm/i915/i915_reg.h   |5 +
 drivers/gpu/drm/i915/i915_reg_defs.h  |   57 +
 11 files changed, 1419 insertions(+), 12 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 97b0d4ae221a..4ee3b5850dd0 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -298,6 +298,7 @@ i915-y += \
display/icl_dsi.o \
display/intel_backlight.o \
display/intel_crt.o \
+   display/intel_cx0_phy.o \
display/intel_ddi.o \
display/intel_ddi_buf_trans.o \
display/intel_display_trace.o \
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
new file mode 100644
index ..f3e13edd27ba
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -0,0 +1,1206 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "i915_reg.h"
+#include "intel_cx0_phy.h"
+#include "intel_cx0_phy_regs.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_panel.h"
+#include "intel_psr.h"
+#include "intel_tc.h"
+
+#define MB_WRITE_COMMITTED  true
+#define MB_WRITE_UNCOMMITTEDfalse
+
+bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
+{
+   if (IS_METEORLAKE(dev_priv) && (phy < PHY_C))
+   return true;
+
+   return false;
+}
+
+static int lane_mask_to_lane(u8 lane_mask)
+{
+   if (WARN_ON((lane_mask & ~INTEL_CX0_BOTH_LANES) ||
+   hweight8(lane_mask) != 1))
+   return 0;
+
+   return ilog2(lane_mask);
+}
+
+static void
+assert_dc_off(struct drm_i915_private *i915)
+{
+   bool enabled;
+
+   enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
+   drm_WARN_ON(>drm, !enabled);
+}
+
+/*
+ * Prepare HW for CX0 phy transactions.
+ *
+ * It is required that PSR and DC5/6 are disabled before any CX0 message
+ * bus transaction is executed.
+ */
+static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder 
*encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+   intel_psr_pause(intel_dp);
+   return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
+}
+
+static void intel_cx0_phy_tr

[Intel-gfx] [PATCH v3 5/8] drm/i915/mtl: Add vswing programming for C10 phys

2023-04-06 Thread Mika Kahola
C10 phys uses direct mapping internally for voltage and pre-emphasis levels.
Program the levels directly to the fields in the VDR Registers.

Bspec: 65449

v2: From table "C10: Tx EQ settings for DP 1.4x" it shows level 1
and preemphasis 1 instead of two times of level 1 preemphasis 0.
Fix this in the driver code as well.
v3: VSwing update (Clint)

Cc: Imre Deak 
Cc: Uma Shankar 
Signed-off-by: Clint Taylor 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 61 +--
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |  3 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 14 +
 drivers/gpu/drm/i915/display/intel_ddi.c  |  4 +-
 .../drm/i915/display/intel_ddi_buf_trans.c| 31 +-
 .../drm/i915/display/intel_ddi_buf_trans.h|  6 ++
 .../i915/display/intel_display_power_map.c|  1 +
 7 files changed, 114 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index f3e13edd27ba..81910d55bb63 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -6,6 +6,8 @@
 #include "i915_reg.h"
 #include "intel_cx0_phy.h"
 #include "intel_cx0_phy_regs.h"
+#include "intel_ddi.h"
+#include "intel_ddi_buf_trans.h"
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
@@ -292,6 +294,57 @@ static void intel_cx0_rmw(struct drm_i915_private *i915, 
enum port port,
__intel_cx0_rmw(i915, port, lane, addr, clear, set, committed);
 }
 
+void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   const struct intel_ddi_buf_trans *trans;
+   intel_wakeref_t wakeref;
+   int n_entries, ln;
+
+   wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+   trans = encoder->get_buf_trans(encoder, crtc_state, _entries);
+   if (drm_WARN_ON_ONCE(>drm, !trans))
+   return;
+
+   intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, 
PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MSGBUS_ACCESS,
+ MB_WRITE_COMMITTED);
+
+   for (ln = 0; ln < 4; ln++) {
+   int level = intel_ddi_level(encoder, crtc_state, ln);
+   int lane, tx;
+
+   lane = ln / 2;
+   tx = ln % 2 + 1;
+
+   intel_cx0_rmw(i915, encoder->port, lane + 1, 
PHY_CX0_VDR_OVRD_CONTROL(lane, tx, 0),
+   C10_PHY_OVRD_LEVEL_MASK,
+   
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.pre_cursor),
+   MB_WRITE_COMMITTED);
+   intel_cx0_rmw(i915, encoder->port, lane + 1, 
PHY_CX0_VDR_OVRD_CONTROL(lane, tx, 1),
+   C10_PHY_OVRD_LEVEL_MASK,
+   
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.vswing),
+   MB_WRITE_COMMITTED);
+   intel_cx0_rmw(i915, encoder->port, lane + 1, 
PHY_CX0_VDR_OVRD_CONTROL(lane, tx, 2),
+   C10_PHY_OVRD_LEVEL_MASK,
+   
C10_PHY_OVRD_LEVEL(trans->entries[level].snps.post_cursor),
+   MB_WRITE_COMMITTED);
+   }
+
+   /* Write Override enables in 0xD71 */
+   intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, 
PHY_C10_VDR_OVRD,
+   0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2,
+   MB_WRITE_COMMITTED);
+
+   intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, 
PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_UPDATE_CFG,
+ MB_WRITE_COMMITTED);
+
+   intel_cx0_phy_transaction_end(encoder, wakeref);
+}
+
 /*
  * Basic DP link rates with 38.4 MHz reference clock.
  * Note: The tables below are with SSC. In non-ssc
@@ -765,10 +818,9 @@ static void intel_program_port_clock_ctl(struct 
intel_encoder *encoder,
val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 
0;
 
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
-XELPDP_LANE1_PHY_CLOCK_SELECT |
-XELPDP_FORWARD_CLOCK_UNGATE |
+XELPDP_LANE1_PHY_CLOCK_SELECT | 
XELPDP_FORWARD_CLOCK_UNGATE |
 XELPDP_DDI_CLOCK_SELECT_MASK |
-XELPDP_SSC_ENABLE_PLLB, val);
+XELPDP_SSC_ENABLE_PLLA | XELPDP_SSC_ENABLE_PLLB, val);
 }
 
 static u32 intel_cx0_get_powerdown_update(u8 lane_mask)
@@ -1143,7 +1195,8 @@ static void intel_c10pll_disable(struct intel_encoder 
*encoder)
 

[Intel-gfx] [PATCH v3 0/8] drm/i915/mtl: Add Support for C10 phy

2023-04-06 Thread Mika Kahola
Phy programming support for C10 phy. This is the first part of
the series that adds support for PICA phy. Later stage the support
for C20 phy is added. This series gets the eDP going.

v2: Register refinitions in intel_cx0_phy_regs.h file (Jani)
v3: Add waits for between message bus writes (Imre)
General cleanups and macro definitions (Imre)

Signed-off-by: Mika Kahola 

Ankit Nautiyal (1):
  drm/i915/display/mtl: Fill port width in
DDI_BUF_/TRANS_DDI_FUNC_/PORT_BUF_CTL for HDMI

Clint Taylor (1):
  drm/i915/mtl: Initial DDI port setup

José Roberto de Souza (1):
  drm/i915/mtl/display: Implement DisplayPort sequences

Mika Kahola (4):
  drm/i915/mtl: Add DP rates
  drm/i915/mtl: Create separate reg file for PICA registers
  drm/i915/mtl: Add vswing programming for C10 phys
  drm/i915/mtl: MTL PICA hotplug detection

Radhakrishna Sripada (1):
  drm/i915/mtl: Add Support for C10 PHY message bus and pll programming

 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 1259 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   47 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  190 +++
 drivers/gpu/drm/i915/display/intel_ddi.c  |  447 +-
 .../drm/i915/display/intel_ddi_buf_trans.c|   31 +-
 .../drm/i915/display/intel_ddi_buf_trans.h|6 +
 drivers/gpu/drm/i915/display/intel_display.c  |6 +-
 .../i915/display/intel_display_power_map.c|1 +
 .../drm/i915/display/intel_display_types.h|   13 +
 drivers/gpu/drm/i915/display/intel_dp.c   |   15 +-
 drivers/gpu/drm/i915/display/intel_dpll.c |   26 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c |2 +-
 .../drm/i915/display/intel_modeset_verify.c   |2 +
 drivers/gpu/drm/i915/i915_irq.c   |  249 +++-
 drivers/gpu/drm/i915/i915_reg.h   |   43 +-
 drivers/gpu/drm/i915/i915_reg_defs.h  |   57 +
 17 files changed, 2361 insertions(+), 34 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h

-- 
2.34.1



[Intel-gfx] [PATCH v3 1/8] drm/i915/mtl: Initial DDI port setup

2023-04-06 Thread Mika Kahola
From: Clint Taylor 

Initialization sequences and C10 phy are in place to be able to enable
the first 2 ports of MTL. The other ports use C20 phy that still need
to be properly added. Enable the first ports for now, keeping a TODO
comment about the others.

Cc: Radhakrishna Sripada 
Reviewed-by: Lucas De Marchi 
Signed-off-by: Clint Taylor 
---
 drivers/gpu/drm/i915/display/intel_display.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 010ee793e1ff..fa7807d04ac2 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7729,7 +7729,11 @@ static void intel_setup_outputs(struct drm_i915_private 
*dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
 
-   if (IS_DG2(dev_priv)) {
+   if (IS_METEORLAKE(dev_priv)) {
+   /* TODO: initialize TC ports as well */
+   intel_ddi_init(dev_priv, PORT_A);
+   intel_ddi_init(dev_priv, PORT_B);
+   } else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
-- 
2.34.1



[Intel-gfx] [PATCH] drm/i915/mtl: Add support for PM DEMAND

2023-04-03 Thread Mika Kahola
Display14 introduces a new way to instruct the PUnit with
power and bandwidth requirements of DE. Add the functionality
to program the registers and handle waits using interrupts.
The current wait time for timeouts is programmed for 10 msecs to
factor in the worst case scenarios. Changes made to use REG_BIT
for a register that we touched(GEN8_DE_MISC_IER _MMIO).

v2:
  - Removed repeated definition of dbuf, which has been moved to struct
intel_display. (Gustavo)
  - s/dev_priv->dbuf/dev_priv->display.dbuf/ (Gustavo)

Bspec: 66451, 64636, 64602, 64603
Cc: Matt Atwood 
Cc: Matt Roper 
Cc: Lucas De Marchi 
Cc: Gustavo Sousa 
Signed-off-by: José Roberto de Souza 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_bw.c   |   4 +-
 drivers/gpu/drm/i915/display/intel_bw.h   |   2 +
 drivers/gpu/drm/i915/display/intel_display.c  |  14 +
 .../drm/i915/display/intel_display_power.c|   8 +
 drivers/gpu/drm/i915/i915_drv.h   |   6 +
 drivers/gpu/drm/i915/i915_irq.c   |  22 +-
 drivers/gpu/drm/i915/i915_reg.h   |  33 +-
 drivers/gpu/drm/i915/intel_pm.c   | 293 ++
 drivers/gpu/drm/i915/intel_pm.h   |  35 +++
 9 files changed, 412 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bw.c 
b/drivers/gpu/drm/i915/display/intel_bw.c
index 202321ffbe2a..87c20bf52123 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -746,8 +746,8 @@ static unsigned int intel_bw_num_active_planes(struct 
drm_i915_private *dev_priv
return num_active_planes;
 }
 
-static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
-  const struct intel_bw_state *bw_state)
+unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
+   const struct intel_bw_state *bw_state)
 {
unsigned int data_rate = 0;
enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/display/intel_bw.h 
b/drivers/gpu/drm/i915/display/intel_bw.h
index f20292143745..17fc0b61db04 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_bw.h
@@ -62,6 +62,8 @@ int intel_bw_init(struct drm_i915_private *dev_priv);
 int intel_bw_atomic_check(struct intel_atomic_state *state);
 void intel_bw_crtc_update(struct intel_bw_state *bw_state,
  const struct intel_crtc_state *crtc_state);
+unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
+   const struct intel_bw_state *bw_state);
 int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
  u32 points_mask);
 int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index b53a1d969344..ee7ca33123b1 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -959,6 +959,9 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state 
*state,
num_encoders++;
}
 
+   if (!encoder)
+   return NULL;
+
drm_WARN(encoder->base.dev, num_encoders != 1,
 "%d encoders for pipe %c\n",
 num_encoders, pipe_name(master_crtc->pipe));
@@ -6767,6 +6770,10 @@ int intel_atomic_check(struct drm_device *dev,
ret = intel_modeset_calc_cdclk(state);
if (ret)
return ret;
+
+   ret = intel_pmdemand_atomic_check(state);
+   if (ret)
+   goto fail;
}
 
ret = intel_atomic_check_crtcs(state);
@@ -7411,6 +7418,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
}
 
intel_sagv_pre_plane_update(state);
+   intel_pmdemand_pre_plane_update(state);
 
/* Complete the events for pipes that have now been disabled */
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
@@ -7523,6 +7531,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
intel_verify_planes(state);
 
intel_sagv_post_plane_update(state);
+   intel_pmdemand_post_plane_update(state);
 
drm_atomic_helper_commit_hw_done(>base);
 
@@ -8250,6 +8259,7 @@ void intel_init_display_hooks(struct drm_i915_private 
*dev_priv)
intel_color_init_hooks(dev_priv);
intel_init_cdclk_hooks(dev_priv);
intel_audio_hooks_init(dev_priv);
+   intel_init_pmdemand(dev_priv);
 
intel_dpll_init_clock_hook(dev_priv);
 
@@ -8476,6 +8486,10 @@ int intel_modeset_init_noirq(struct drm_i915_private 
*i915)
if (ret)
goto cleanup_vga_client_pw_domain_dmc;
 
+   ret = intel_pmdemand_init(i915);
+   if (

[Intel-gfx] [PATCH 6/7] drm/i915/mtl: Add vswing programming for C10 phys

2023-03-27 Thread Mika Kahola
From: Radhakrishna Sripada 

C10 phys uses direct mapping internally for voltage and pre-emphasis levels.
Program the levels directly to the fields in the VDR Registers.

Bspec: 65449

v2: From table "C10: Tx EQ settings for DP 1.4x" it shows level 1
and preemphasis 1 instead of two times of level 1 preemphasis 0.
Fix this in the driver code as well.
v3: VSwing update (Clint)

Cc: Imre Deak 
Cc: Uma Shankar 
Signed-off-by: Clint Taylor 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 140 --
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   2 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  14 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |   4 +-
 .../drm/i915/display/intel_ddi_buf_trans.c|  31 +++-
 .../drm/i915/display/intel_ddi_buf_trans.h|   6 +
 .../i915/display/intel_display_power_map.c|   1 +
 7 files changed, 187 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 3aa8031f8373..fb54f56ac5ef 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -6,11 +6,15 @@
 #include "i915_reg.h"
 #include "intel_cx0_phy.h"
 #include "intel_cx0_phy_regs.h"
+#include "intel_ddi.h"
+#include "intel_ddi_buf_trans.h"
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
 #include "intel_panel.h"
+#include "intel_psr.h"
 #include "intel_tc.h"
+#include "intel_uncore.h"
 
 bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
 {
@@ -20,6 +24,15 @@ bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum 
phy phy)
return false;
 }
 
+static void
+assert_dc_off(struct drm_i915_private *i915)
+{
+   bool enabled;
+
+   enabled = intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF);
+   drm_WARN_ON(>drm, !enabled);
+}
+
 static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, 
int lane)
 {
enum phy phy = intel_port_to_phy(i915, port);
@@ -112,6 +125,8 @@ static u8 intel_cx0_read(struct drm_i915_private *i915, 
enum port port,
int i, status = 0;
u32 val;
 
+   assert_dc_off(i915);
+
for (i = 0; i < 3; i++) {
status = __intel_cx0_read(i915, port, lane, addr, );
 
@@ -194,6 +209,8 @@ static void __intel_cx0_write(struct drm_i915_private 
*i915, enum port port,
enum phy phy = intel_port_to_phy(i915, port);
int i, status;
 
+   assert_dc_off(i915);
+
for (i = 0; i < 3; i++) {
status = __intel_cx0_write_once(i915, port, lane, addr, data, 
committed);
 
@@ -241,6 +258,89 @@ static void intel_cx0_rmw(struct drm_i915_private *i915, 
enum port port,
}
 }
 
+/*
+ * Prepare HW for CX0 phy transactions.
+ *
+ * It is required that PSR and DC5/6 are disabled before any CX0 message
+ * bus transaction is executed.
+ */
+static intel_wakeref_t intel_cx0_phy_transaction_begin(struct intel_encoder 
*encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+   intel_psr_pause(intel_dp);
+   return intel_display_power_get(i915, POWER_DOMAIN_DC_OFF);
+}
+
+static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, 
intel_wakeref_t wakeref)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+   intel_psr_resume(intel_dp);
+   intel_display_power_put(i915, POWER_DOMAIN_DC_OFF, wakeref);
+}
+
+void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+   bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
+   u8 master_lane = lane_reversal ? INTEL_CX0_LANE1 :
+INTEL_CX0_LANE0;
+   u8 follower_lane = lane_reversal ? INTEL_CX0_LANE0 :
+  INTEL_CX0_LANE1;
+   const struct intel_ddi_buf_trans *trans;
+   intel_wakeref_t wakeref;
+   int n_entries, ln;
+
+   wakeref = intel_cx0_phy_transaction_begin(encoder);
+
+   trans = encoder->get_buf_trans(encoder, crtc_state, _entries);
+   if (drm_WARN_ON_ONCE(>drm, !trans))
+   return;
+
+   intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, 
PHY_C10_VDR_CONTROL(1),
+ 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED);
+
+   for (ln = 0; ln < 4; ln++) {
+   int level = intel_d

[Intel-gfx] [PATCH 7/7] drm/i915/mtl: Add support for PM DEMAND

2023-03-27 Thread Mika Kahola
Display14 introduces a new way to instruct the PUnit with
power and bandwidth requirements of DE. Add the functionality
to program the registers and handle waits using interrupts.
The current wait time for timeouts is programmed for 10 msecs to
factor in the worst case scenarios. Changes made to use REG_BIT
for a register that we touched(GEN8_DE_MISC_IER _MMIO).

v2:
  - Removed repeated definition of dbuf, which has been moved to struct
intel_display. (Gustavo)
  - s/dev_priv->dbuf/dev_priv->display.dbuf/ (Gustavo)

Bspec: 66451, 64636, 64602, 64603
Cc: Matt Atwood 
Cc: Matt Roper 
Cc: Lucas De Marchi 
Cc: Gustavo Sousa 
Signed-off-by: José Roberto de Souza 
Signed-off-by: Radhakrishna Sripada 
---
 drivers/gpu/drm/i915/display/intel_bw.c   |   4 +-
 drivers/gpu/drm/i915/display/intel_bw.h   |   2 +
 drivers/gpu/drm/i915/display/intel_display.c  |  14 +
 .../drm/i915/display/intel_display_power.c|   8 +
 drivers/gpu/drm/i915/i915_drv.h   |   6 +
 drivers/gpu/drm/i915/i915_irq.c   |  22 +-
 drivers/gpu/drm/i915/i915_reg.h   |  33 +-
 drivers/gpu/drm/i915/intel_pm.c   | 286 ++
 drivers/gpu/drm/i915/intel_pm.h   |  35 +++
 9 files changed, 405 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bw.c 
b/drivers/gpu/drm/i915/display/intel_bw.c
index 202321ffbe2a..87c20bf52123 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -746,8 +746,8 @@ static unsigned int intel_bw_num_active_planes(struct 
drm_i915_private *dev_priv
return num_active_planes;
 }
 
-static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
-  const struct intel_bw_state *bw_state)
+unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
+   const struct intel_bw_state *bw_state)
 {
unsigned int data_rate = 0;
enum pipe pipe;
diff --git a/drivers/gpu/drm/i915/display/intel_bw.h 
b/drivers/gpu/drm/i915/display/intel_bw.h
index f20292143745..17fc0b61db04 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_bw.h
@@ -62,6 +62,8 @@ int intel_bw_init(struct drm_i915_private *dev_priv);
 int intel_bw_atomic_check(struct intel_atomic_state *state);
 void intel_bw_crtc_update(struct intel_bw_state *bw_state,
  const struct intel_crtc_state *crtc_state);
+unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
+   const struct intel_bw_state *bw_state);
 int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
  u32 points_mask);
 int intel_bw_calc_min_cdclk(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 9fe6e33a66d6..3a9d71c80d5c 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -959,6 +959,9 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state 
*state,
num_encoders++;
}
 
+   if (!encoder)
+   return NULL;
+
drm_WARN(encoder->base.dev, num_encoders != 1,
 "%d encoders for pipe %c\n",
 num_encoders, pipe_name(master_crtc->pipe));
@@ -6767,6 +6770,10 @@ int intel_atomic_check(struct drm_device *dev,
ret = intel_modeset_calc_cdclk(state);
if (ret)
return ret;
+
+   ret = intel_pmdemand_atomic_check(state);
+   if (ret)
+   goto fail;
}
 
ret = intel_atomic_check_crtcs(state);
@@ -7405,6 +7412,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
}
 
intel_sagv_pre_plane_update(state);
+   intel_pmdemand_pre_plane_update(state);
 
/* Complete the events for pipes that have now been disabled */
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
@@ -7517,6 +7525,7 @@ static void intel_atomic_commit_tail(struct 
intel_atomic_state *state)
intel_verify_planes(state);
 
intel_sagv_post_plane_update(state);
+   intel_pmdemand_post_plane_update(state);
 
drm_atomic_helper_commit_hw_done(>base);
 
@@ -8248,6 +8257,7 @@ void intel_init_display_hooks(struct drm_i915_private 
*dev_priv)
intel_color_init_hooks(dev_priv);
intel_init_cdclk_hooks(dev_priv);
intel_audio_hooks_init(dev_priv);
+   intel_init_pmdemand(dev_priv);
 
intel_dpll_init_clock_hook(dev_priv);
 
@@ -8474,6 +8484,10 @@ int intel_modeset_init_noirq(struct drm_i915_private 
*i915)
if (ret)
goto cleanup_vga_client_pw_domain_dmc;
 
+   ret = intel_pmdemand_init(i915);
+   if (ret)
+   goto cleanup_vga_client_pw_domain_dmc;
+

[Intel-gfx] [PATCH 5/7] drm/i915/mtl: Add C10 phy programming for HDMI

2023-03-27 Thread Mika Kahola
From: Radhakrishna Sripada 

Like DG2, we still don't have a proper algorithm that can be used
for calculating PHY settings, but we do have tables of register
values for a handful of the more common link rates. Some support is
better than none, so let's go ahead and add/use these tables when we
can, and also add some logic to hdmi_port_clock_valid() to filter the
modelist to just the modes we can actually support with these link
rates.

Hopefully we'll have a proper / non-encumbered algorithm to calculate
these registers by the time we upstream and we'll be able to replace
this patch with something more general purpose.

Bspec: 64568

v2: Rebasing with Clint's HDMI C10 PLL tables (Mika)
v3: Add missing use_hdmi checks from Clint's HDMI implementation changes (Ankit)

Cc: Imre Deak 
Cc: Uma Shankar 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Clint Taylor 
Signed-off-by: Mika Kahola 
Signed-off-by: Ankit Nautiyal 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 576 +-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   1 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  13 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c |   5 +-
 4 files changed, 579 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index ced8c8aa6c82..3aa8031f8373 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -485,6 +485,538 @@ static const struct intel_c10mpllb_state * const 
mtl_c10_edp_tables[] = {
NULL,
 };
 
+/*
+ * HDMI link rates with 38.4 MHz reference clock.
+ */
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_25_2 = {
+   .clock = 25200,
+   .pll[0] = 0x4,
+   .pll[1] = 0,
+   .pll[2] = 0xB2,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xD,
+   .pll[16] = 0x6,
+   .pll[17] = 0x8F,
+   .pll[18] = 0x84,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_27_0 = {
+   .clock = 27000,
+   .pll[0] = 0x34,
+   .pll[1] = 0,
+   .pll[2] = 0xC0,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x80,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xD,
+   .pll[16] = 0x6,
+   .pll[17] = 0xCF,
+   .pll[18] = 0x84,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_74_25 = {
+   .clock = 74250,
+   .pll[0] = 0xF4,
+   .pll[1] = 0,
+   .pll[2] = 0x7A,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x58,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xB,
+   .pll[16] = 0x6,
+   .pll[17] = 0xF,
+   .pll[18] = 0x85,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_148_5 = {
+   .clock = 148500,
+   .pll[0] = 0xF4,
+   .pll[1] = 0,
+   .pll[2] = 0x7A,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x58,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0xA,
+   .pll[16] = 0x6,
+   .pll[17] = 0xF,
+   .pll[18] = 0x85,
+   .pll[19] = 0x23,
+};
+
+static const struct intel_c10mpllb_state mtl_c10_hdmi_594 = {
+   .clock = 594000,
+   .pll[0] = 0xF4,
+   .pll[1] = 0,
+   .pll[2] = 0x7A,
+   .pll[3] = 0,
+   .pll[4] = 0,
+   .pll[5] = 0,
+   .pll[6] = 0,
+   .pll[7] = 0,
+   .pll[8] = 0x20,
+   .pll[9] = 0x1,
+   .pll[10] = 0,
+   .pll[11] = 0,
+   .pll[12] = 0x58,
+   .pll[13] = 0,
+   .pll[14] = 0,
+   .pll[15] = 0x8,
+   .pll[16] = 0x6,
+   .pll[17] = 0xF,
+   .pll[18] = 0x85,
+   .pll[19] = 0x23,
+};
+
+/* Precomputed C10 HDMI PLL tables */
+static const struct intel_c10mpllb_state mtl_c10_hdmi_25175 = {
+   .clock = 25175,
+   .pll[0]=0x34,
+   .pll[1]=0x00,
+   .pll[2]=0xB0,
+   .pll[3]=0x00,
+   .pll[4]=0x00,
+   .pll[5]=0x00,
+   .pll[6]=0x00,
+   .pll[7]=0x00,
+   .pll[8]=0x20,
+   .pll[9]=0xFF,
+   .pll[10]=0xFF,
+   .pll[11]=0x55,
+   .pll[12]=0xE5,
+   .pll[13]=0x55,
+   .pll[14]=0x55,
+   .pll[15]=0x0D,
+   .pll[16]=0x09,
+   .pll[17]=0x8F,
+   .pll[18]=0x84,
+   .pll[19]=0x23

[Intel-gfx] [PATCH 4/7] drm/i915/mtl: Add Support for C10 PHY message bus and pll programming

2023-03-27 Thread Mika Kahola
From: Radhakrishna Sripada 

XELPDP has C10 and C20 phys from Synopsys to drive displays. Each phy
has a dedicated PIPE 5.2 Message bus for configuration. This message
bus is used to configure the phy internal registers.

XELPDP has C10 phys to drive output to the EDP and the native output
from the display engine. Add structures, programming hardware state
readout logic. Port clock calculations are similar to DG2. Use the DG2
formulae to calculate the port clock but use the relevant pll signals.
Note: PHY lane 0 is always used for PLL programming.

Add sequences for C10 phy enable/disable phy lane reset,
powerdown change sequence and phy lane programming.

Bspec: 64539, 64568, 64599, 65100, 65101, 65450, 65451, 67610, 67636

v2: Squash patches related to C10 phy message bus and pll
programming support (Jani)
Move register definitions to a new file i.e. intel_cx0_reg_defs.h (Jani)
Move macro definitions (Jani)
DP rates as separate patch (Jani)
Spin out xelpdp register definitions into a separate file (Jani)
Replace macro to select registers based on phy lane with
function calls (Jani)
Fix styling issues (Jani)
Call XELPDP_PORT_P2M_MSGBUS_STATUS() with port instead of phy (Lucas)
v3: Move clear request flag into try-loop
v4: On PHY idle change drm_err_once() as drm_dbg_kms() (Jani)
use __intel_de_wait_for_register() instead of __intel_wait_for_register
and uncomment intel_uncore.h (Jani)
Add DP-alt support for PHY lane programming (Khaled)

Cc: Mika Kahola 
Cc: Imre Deak 
Cc: Uma Shankar 
Cc: Gustavo Sousa 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 1120 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   43 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |   32 +-
 drivers/gpu/drm/i915/display/intel_ddi.c  |   22 +-
 .../drm/i915/display/intel_display_power.c|3 +-
 .../i915/display/intel_display_power_well.c   |2 +-
 .../drm/i915/display/intel_display_types.h|6 +
 drivers/gpu/drm/i915/display/intel_dpll.c |   20 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c |2 +-
 .../drm/i915/display/intel_modeset_verify.c   |2 +
 drivers/gpu/drm/i915/i915_reg.h   |5 +
 drivers/gpu/drm/i915/i915_reg_defs.h  |   57 +
 13 files changed, 1309 insertions(+), 6 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 057ef22fa9c6..57b1417792b4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -298,6 +298,7 @@ i915-y += \
display/icl_dsi.o \
display/intel_backlight.o \
display/intel_crt.o \
+   display/intel_cx0_phy.o \
display/intel_ddi.o \
display/intel_ddi_buf_trans.o \
display/intel_display_trace.o \
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
new file mode 100644
index ..ced8c8aa6c82
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -0,0 +1,1120 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include "i915_reg.h"
+#include "intel_cx0_phy.h"
+#include "intel_cx0_phy_regs.h"
+#include "intel_de.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_panel.h"
+#include "intel_tc.h"
+
+bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
+{
+   if (IS_METEORLAKE(dev_priv) && (phy < PHY_C))
+   return true;
+
+   return false;
+}
+
+static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, 
int lane)
+{
+   enum phy phy = intel_port_to_phy(i915, port);
+
+   /* Bring the phy to idle. */
+   intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane - 1),
+  XELPDP_PORT_M2P_TRANSACTION_RESET);
+
+   /* Wait for Idle Clear. */
+   if (intel_de_wait_for_clear(i915, XELPDP_PORT_M2P_MSGBUS_CTL(port, lane 
- 1),
+   XELPDP_PORT_M2P_TRANSACTION_RESET,
+   XELPDP_MSGBUS_TIMEOUT_SLOW)) {
+   drm_dbg_kms(>drm, "Failed to bring PHY %c to idle.\n", 
phy_name(phy));
+   return;
+   }
+
+   intel_de_write(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane - 1), ~0);
+}
+
+static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port 
port, int lane, u32 *val)
+{
+   enum phy phy = intel_port_to_phy(i915, port);
+
+   if (__intel_de_wait_for_register(i915,
+XELPDP_PORT_P2M

[Intel-gfx] [PATCH 3/7] drm/i915/mtl: Create separate reg file for PICA registers

2023-03-27 Thread Mika Kahola
Create a separate file to store registers for PICA chips
C10 and C20.

v2: Rename file (Jani)
v3: Use _PICK_EVEN_2RANGES() macro (Lucas)
Coding style fixed (Lucas)

Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 131 ++
 1 file changed, 131 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
new file mode 100644
index ..d1ee8a2fc9cf
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_CX0_PHY_REGS_H__
+#define __INTEL_CX0_PHY_REGS_H__
+
+#include "i915_reg_defs.h"
+
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A  0x64040
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B  0x64140
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1  0x16F240
+#define _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2  0x16F440
+#define XELPDP_PORT_M2P_MSGBUS_CTL(port, lane) 
_MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) + (lane) * 4)
+#define   XELPDP_PORT_M2P_TRANSACTION_PENDING  REG_BIT(31)
+#define   XELPDP_PORT_M2P_COMMAND_TYPE_MASKREG_GENMASK(30, 27)
+#define   XELPDP_PORT_M2P_COMMAND_WRITE_UNCOMMITTED
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x1)
+#define   XELPDP_PORT_M2P_COMMAND_WRITE_COMMITTED  
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x2)
+#define   XELPDP_PORT_M2P_COMMAND_READ 
REG_FIELD_PREP(XELPDP_PORT_M2P_COMMAND_TYPE_MASK, 0x3)
+#define   XELPDP_PORT_M2P_DATA_MASKREG_GENMASK(23, 16)
+#define   XELPDP_PORT_M2P_DATA(val)
REG_FIELD_PREP(XELPDP_PORT_M2P_DATA_MASK, val)
+#define   XELPDP_PORT_M2P_TRANSACTION_RESETREG_BIT(15)
+#define   XELPDP_PORT_M2P_ADDRESS_MASK REG_GENMASK(11, 0)
+#define   XELPDP_PORT_M2P_ADDRESS(val) 
REG_FIELD_PREP(XELPDP_PORT_M2P_ADDRESS_MASK, val)
+#define XELPDP_PORT_P2M_MSGBUS_STATUS(port, lane)  
_MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_A, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_B, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC1, \
+   
 _XELPDP_PORT_M2P_MSGBUS_CTL_LN0_USBC2) + (lane) * 4 + 8)
+#define   XELPDP_PORT_P2M_RESPONSE_READY   REG_BIT(31)
+#define   XELPDP_PORT_P2M_COMMAND_TYPE_MASKREG_GENMASK(30, 27)
+#define   XELPDP_PORT_P2M_COMMAND_READ_ACK 0x4
+#define   XELPDP_PORT_P2M_COMMAND_WRITE_ACK0x5
+#define   XELPDP_PORT_P2M_DATA_MASKREG_GENMASK(23, 16)
+#define   XELPDP_PORT_P2M_DATA(val)
REG_FIELD_PREP(XELPDP_PORT_P2M_DATA_MASK, val)
+#define   XELPDP_PORT_P2M_ERROR_SETREG_BIT(15)
+
+#define XELPDP_MSGBUS_TIMEOUT_SLOW 1
+#define XELPDP_MSGBUS_TIMEOUT_FAST_US  2
+#define XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US  3200
+#define XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US 20
+#define XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US   100
+#define XELPDP_PORT_RESET_START_TIMEOUT_US 5
+#define XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US100
+#define XELPDP_PORT_RESET_END_TIMEOUT  15
+#define XELPDP_REFCLK_ENABLE_TIMEOUT_US1
+
+#define _XELPDP_PORT_BUF_CTL1_LN0_A0x64004
+#define _XELPDP_PORT_BUF_CTL1_LN0_B0x64104
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC10x16F200
+#define _XELPDP_PORT_BUF_CTL1_LN0_USBC20x16F400
+#define XELPDP_PORT_BUF_CTL1(port) 
_MMIO(_PICK_EVEN_2RANGES(port, PORT_TC1, \
+   
 _XELPDP_PORT_BUF_CTL1_LN0_A, \
+   
 _XELPDP_PORT_BUF_CTL1_LN0_B, \
+   
 _XELPDP_PORT_BUF_CTL1

[Intel-gfx] [PATCH 2/7] drm/i915/mtl: Add DP rates

2023-03-27 Thread Mika Kahola
Add DP rates for Meteorlake.

Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index da1c00ee92fb..4927aeb64f23 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -420,6 +420,11 @@ static int ehl_max_source_rate(struct intel_dp *intel_dp)
return 81;
 }
 
+static int mtl_max_source_rate(struct intel_dp *intel_dp)
+{
+   return intel_dp_is_edp(intel_dp) ? 675000 : 81;
+}
+
 static int vbt_max_link_rate(struct intel_dp *intel_dp)
 {
struct intel_encoder *encoder = _to_dig_port(intel_dp)->base;
@@ -444,6 +449,10 @@ static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
/* The values must be in increasing order */
+   static const int mtl_rates[] = {
+   162000, 216000, 243000, 27, 324000, 432000, 54, 675000,
+   81,
+   };
static const int icl_rates[] = {
162000, 216000, 27, 324000, 432000, 54, 648000, 81,
100, 135,
@@ -469,7 +478,11 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp)
drm_WARN_ON(_priv->drm,
intel_dp->source_rates || intel_dp->num_source_rates);
 
-   if (DISPLAY_VER(dev_priv) >= 11) {
+   if (DISPLAY_VER(dev_priv) >= 14) {
+   source_rates = mtl_rates;
+   size = ARRAY_SIZE(mtl_rates);
+   max_rate = mtl_max_source_rate(intel_dp);
+   } else if (DISPLAY_VER(dev_priv) >= 11) {
source_rates = icl_rates;
size = ARRAY_SIZE(icl_rates);
if (IS_DG2(dev_priv))
-- 
2.34.1



[Intel-gfx] [PATCH 1/7] drm/i915/mtl: Initial DDI port setup

2023-03-27 Thread Mika Kahola
From: Clint Taylor 

Initialization sequences and C10 phy are in place to be able to enable
the first 2 ports of MTL. The other ports use C20 phy that still need
to be properly added. Enable the first ports for now, keeping a TODO
comment about the others.

Cc: Radhakrishna Sripada 
Reviewed-by: Lucas De Marchi 
Signed-off-by: Clint Taylor 
---
 drivers/gpu/drm/i915/display/intel_display.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 5a386c7c0bc9..9fe6e33a66d6 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7796,7 +7796,11 @@ static void intel_setup_outputs(struct drm_i915_private 
*dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
 
-   if (IS_DG2(dev_priv)) {
+   if (IS_METEORLAKE(dev_priv)) {
+   /* TODO: initialize TC ports as well */
+   intel_ddi_init(dev_priv, PORT_A);
+   intel_ddi_init(dev_priv, PORT_B);
+   } else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
intel_ddi_init(dev_priv, PORT_C);
-- 
2.34.1



[Intel-gfx] [PATCH 0/7] drm/i915/mtl: Add Support for C10 chips

2023-03-27 Thread Mika Kahola
Phy programming support for C10 PICA chips. This is the first part of
the series that adds support for PICA chips. Later the support for
C20 chips are added.

Signed-off-by: Mika Kahola 

Clint Taylor (1):
  drm/i915/mtl: Initial DDI port setup

Mika Kahola (3):
  drm/i915/mtl: Add DP rates
  drm/i915/mtl: Create separate reg file for PICA registers
  drm/i915/mtl: Add support for PM DEMAND

Radhakrishna Sripada (3):
  drm/i915/mtl: Add Support for C10 PHY message bus and pll programming
  drm/i915/mtl: Add C10 phy programming for HDMI
  drm/i915/mtl: Add vswing programming for C10 phys

 drivers/gpu/drm/i915/Makefile |1 +
 drivers/gpu/drm/i915/display/intel_bw.c   |4 +-
 drivers/gpu/drm/i915/display/intel_bw.h   |2 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 1798 +
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |   46 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  178 ++
 drivers/gpu/drm/i915/display/intel_ddi.c  |   26 +-
 .../drm/i915/display/intel_ddi_buf_trans.c|   31 +-
 .../drm/i915/display/intel_ddi_buf_trans.h|6 +
 drivers/gpu/drm/i915/display/intel_display.c  |   20 +-
 .../drm/i915/display/intel_display_power.c|   11 +-
 .../i915/display/intel_display_power_map.c|1 +
 .../i915/display/intel_display_power_well.c   |2 +-
 .../drm/i915/display/intel_display_types.h|6 +
 drivers/gpu/drm/i915/display/intel_dp.c   |   15 +-
 drivers/gpu/drm/i915/display/intel_dpll.c |   20 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c |2 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c |5 +-
 .../drm/i915/display/intel_modeset_verify.c   |2 +
 drivers/gpu/drm/i915/i915_drv.h   |6 +
 drivers/gpu/drm/i915/i915_irq.c   |   22 +-
 drivers/gpu/drm/i915/i915_reg.h   |   38 +-
 drivers/gpu/drm/i915/i915_reg_defs.h  |   57 +
 drivers/gpu/drm/i915/intel_pm.c   |  286 +++
 drivers/gpu/drm/i915/intel_pm.h   |   35 +
 25 files changed, 2605 insertions(+), 15 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h

-- 
2.34.1



[Intel-gfx] [PATCH v5 20/22] drm/i915/mtl: Power up TCSS

2023-03-16 Thread Mika Kahola
Add register writes to enable powering up Type-C subsystem i.e. TCSS.
For MeteorLake we need to request TCSS to power up and check the TCSS
power state after 500 us.

In addition, for PICA we need to set/clear the Type-C PHY ownnership
bit when Type-C device is connected/disconnected.

v2: Call tcss power request with correct parameter.
v3: Use de variant for register wait (Jani)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_display.c |   2 +-
 drivers/gpu/drm/i915/display/intel_tc.c  | 117 ++-
 2 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 89279814e789..71fa60cf4953 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1978,7 +1978,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, 
enum phy phy)
if (IS_DG2(dev_priv))
/* DG2's "TC1" output uses a SNPS PHY */
return false;
-   else if (IS_ALDERLAKE_P(dev_priv))
+   else if (IS_ALDERLAKE_P(dev_priv) || IS_METEORLAKE(dev_priv))
return phy >= PHY_F && phy <= PHY_I;
else if (IS_TIGERLAKE(dev_priv))
return phy >= PHY_D && phy <= PHY_I;
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index f45328712bff..89dfc19de1b8 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -5,6 +5,7 @@
 
 #include "i915_drv.h"
 #include "i915_reg.h"
+#include "intel_cx0_phy_regs.h"
 #include "intel_de.h"
 #include "intel_display.h"
 #include "intel_display_power_map.h"
@@ -300,7 +301,7 @@ static u32 tc_port_live_status_mask(struct 
intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 
-   if (IS_ALDERLAKE_P(i915))
+   if (DISPLAY_VER(i915) >= 13)
return adl_tc_port_live_status_mask(dig_port);
 
return icl_tc_port_live_status_mask(dig_port);
@@ -354,11 +355,69 @@ static bool adl_tc_phy_status_complete(struct 
intel_digital_port *dig_port)
return val & TCSS_DDI_STATUS_READY;
 }
 
+static bool xelpdp_wait_phy_status_complete(struct intel_digital_port 
*dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+
+   if (intel_de_wait_for_register(i915,
+  TCSS_DDI_STATUS(tc_port),
+  TCSS_DDI_STATUS_READY,
+  TCSS_DDI_STATUS_READY,
+  1)) {
+   drm_dbg_kms(>drm,
+   "Port %s: PHY in TCCOLD, assuming not complete\n",
+   dig_port->tc_port_name);
+   return false;
+   }
+
+   return true;
+}
+
+static bool xelpdp_wait_for_tcss_power(struct intel_digital_port *dig_port,
+  bool enabled)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+   if (intel_de_wait_for_register(i915,
+  
XELPDP_PORT_BUF_CTL1(dig_port->base.port),
+  XELPDP_TCSS_POWER_STATE,
+  enabled ? XELPDP_TCSS_POWER_STATE : 0,
+  5)) {
+   drm_dbg_kms(>drm,
+   "Port %s: TCSS power state not as expected\n",
+   dig_port->tc_port_name);
+   return false;
+   }
+
+   return true;
+}
+
+static bool xelpdp_tc_power_request(struct intel_digital_port *dig_port, bool 
request)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   struct intel_uncore *uncore = >uncore;
+   enum port port = dig_port->base.port;
+   u32 val;
+
+   val = intel_uncore_read(uncore, XELPDP_PORT_BUF_CTL1(port));
+   if (request)
+   val |= XELPDP_TCSS_POWER_REQUEST;
+   else
+   val &= ~XELPDP_TCSS_POWER_REQUEST;
+   intel_uncore_write(uncore, XELPDP_PORT_BUF_CTL1(port), val);
+
+   return xelpdp_wait_phy_status_complete(dig_port) &&
+  xelpdp_wait_for_tcss_power(dig_port, request);
+}
+
 static bool tc_phy_status_complete(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 
-   if (IS_ALDERLAKE_P(i915))
+   if (DISPLAY_VER(i915) >= 14)
+   return xelpdp_wait_phy_status_complete(dig_port);
+   else if (IS_ALDERLAKE_P(i915))
return adl_tc_phy_status_complete(dig_

[Intel-gfx] [PATCH v5 22/22] drm/i915/mtl: Pin assignment for TypeC

2023-03-16 Thread Mika Kahola
From: Anusha Srivatsa 

Unlike previous platforms that used PORT_TX_DFLEXDPSP
for max_lane calculation, MTL uses only PORT_TX_DFLEXPA1
from which the max_lanes has to be calculated.

Bspec: 50235, 65380

Cc: Mika Kahola 
Cc: Imre Deak 
Cc: Matt Roper 
Signed-off-by: Anusha Srivatsa 
Signed-off-by: Jose Roberto de Souza 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 30 +
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 5756daac91d9..694d74088980 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -15,6 +15,10 @@
 #include "intel_mg_phy_regs.h"
 #include "intel_tc.h"
 
+#define DP_PIN_ASSIGNMENT_C0x3
+#define DP_PIN_ASSIGNMENT_D0x4
+#define DP_PIN_ASSIGNMENT_E0x5
+
 static const char *tc_port_mode_name(enum tc_port_mode mode)
 {
static const char * const names[] = {
@@ -147,6 +151,29 @@ u32 intel_tc_port_get_pin_assignment_mask(struct 
intel_digital_port *dig_port)
   DP_PIN_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx);
 }
 
+static int mtl_tc_port_get_pin_assignment_mask(struct intel_digital_port 
*dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   intel_wakeref_t wakeref;
+   u32 pin_mask;
+
+   assert_tc_cold_blocked(dig_port);
+
+   with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+   pin_mask = intel_tc_port_get_pin_assignment_mask(dig_port);
+
+   switch(pin_mask) {
+   default:
+   MISSING_CASE(pin_mask);
+   fallthrough;
+   case DP_PIN_ASSIGNMENT_D:
+   return 2;
+   case DP_PIN_ASSIGNMENT_C:
+   case DP_PIN_ASSIGNMENT_E:
+   return 4;
+   }
+}
+
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -156,6 +183,9 @@ int intel_tc_port_fia_max_lane_count(struct 
intel_digital_port *dig_port)
if (dig_port->tc_mode != TC_PORT_DP_ALT)
return 4;
 
+   if (DISPLAY_VER(i915) >= 14)
+   return mtl_tc_port_get_pin_assignment_mask(dig_port);
+
assert_tc_cold_blocked(dig_port);
 
lane_mask = 0;
-- 
2.34.1



[Intel-gfx] [PATCH v5 21/22] drm/i915/mtl: TypeC HPD live status query

2023-03-16 Thread Mika Kahola
From: Imre Deak 

The HPD live status for MTL has to be read from different set of
registers. MTL deserves a new function for this purpose
and cannot reuse the existing  HPD live status detection

Signed-off-by: Anusha Srivatsa 
Signed-off-by: Imre Deak 
Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_tc.c | 30 +
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c 
b/drivers/gpu/drm/i915/display/intel_tc.c
index 89dfc19de1b8..5756daac91d9 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -297,10 +297,40 @@ static u32 adl_tc_port_live_status_mask(struct 
intel_digital_port *dig_port)
return mask;
 }
 
+static u32 xelpdp_tc_port_live_status_mask(struct intel_digital_port *dig_port)
+{
+   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+   u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin];
+   struct intel_uncore *uncore = >uncore;
+   u32 val, mask = 0;
+   enum hpd_pin pin;
+
+   val = intel_uncore_read(uncore, PICAINTERRUPT_ISR);
+   pin = HPD_PORT_TC1 + tc_port - TC_PORT_1;
+   if (val & XELPDP_DP_ALT_HOTPLUG(pin))
+   mask |= BIT(TC_PORT_DP_ALT);
+   if (val & XELPDP_TBT_HOTPLUG(pin))
+   mask |= BIT(TC_PORT_TBT_ALT);
+
+   if (dig_port->tc_legacy_port &&
+   intel_uncore_read(uncore, SDEISR) & isr_bit)
+   mask |= BIT(TC_PORT_LEGACY);
+
+   /* The sink can be connected only in a single mode. */
+   if (!drm_WARN_ON(>drm, hweight32(mask) > 1))
+   tc_port_fixup_legacy_flag(dig_port, mask);
+
+   return mask;
+}
+
 static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 
+   if (DISPLAY_VER(i915) >= 14)
+   return xelpdp_tc_port_live_status_mask(dig_port);
+
if (DISPLAY_VER(i915) >= 13)
return adl_tc_port_live_status_mask(dig_port);
 
-- 
2.34.1



[Intel-gfx] [PATCH v5 17/22] drm/i915/mtl: Enable TC ports

2023-03-16 Thread Mika Kahola
Finally, we can enable TC ports for Meteorlake.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_display.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 505e99ef17f8..89279814e789 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -7842,9 +7842,12 @@ static void intel_setup_outputs(struct drm_i915_private 
*dev_priv)
return;
 
if (IS_METEORLAKE(dev_priv)) {
-   /* TODO: initialize TC ports as well */
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
+   intel_ddi_init(dev_priv, PORT_TC1);
+   intel_ddi_init(dev_priv, PORT_TC2);
+   intel_ddi_init(dev_priv, PORT_TC3);
+   intel_ddi_init(dev_priv, PORT_TC4);
} else if (IS_DG2(dev_priv)) {
intel_ddi_init(dev_priv, PORT_A);
intel_ddi_init(dev_priv, PORT_B);
-- 
2.34.1



[Intel-gfx] [PATCH v5 15/22] drm/i915/mtl: Enabling/disabling sequence Thunderbolt pll

2023-03-16 Thread Mika Kahola
Enabling and disabling sequence for Thunderbolt PLL.

v2: Use __intel_de_wait_for_register() instead of
__intel_wait_for_register() (Jani)
Use '0' instead of ~XELPDP_TBT_CLOCK_ACK (Gustavo)

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 136 ++-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |   7 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |   4 +-
 3 files changed, 138 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index e1a919803241..ee281e9de301 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -15,7 +15,6 @@
 #include "intel_panel.h"
 #include "intel_tc.h"
 #include "intel_psr.h"
-#include "intel_uncore.h"
 #include "intel_tc.h"
 
 bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy)
@@ -2466,8 +2465,8 @@ static u32 intel_cx0_get_pclk_pll_ack(u8 lane)
   XELPDP_LANE1_PCLK_PLL_ACK;
 }
 
-void intel_cx0pll_enable(struct intel_encoder *encoder,
-const struct intel_crtc_state *crtc_state)
+static void intel_cx0pll_enable(struct intel_encoder *encoder,
+   const struct intel_crtc_state *crtc_state)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
@@ -2540,7 +2539,86 @@ void intel_cx0pll_enable(struct intel_encoder *encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
-void intel_cx0pll_disable(struct intel_encoder *encoder)
+static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
+{
+   switch (clock) {
+   case 162000:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   case 27:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_270;
+   case 54:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_540;
+   case 81:
+   return XELPDP_DDI_CLOCK_SELECT_TBT_810;
+   default:
+   MISSING_CASE(clock);
+   return XELPDP_DDI_CLOCK_SELECT_TBT_162;
+   }
+}
+
+static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder,
+const struct intel_crtc_state *crtc_state)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+   u32 val = 0;
+
+   /*
+* 1. Program PORT_CLOCK_CTL REGISTER to configure
+* clock muxes, gating and SSC
+*/
+   val |= XELPDP_DDI_CLOCK_SELECT(intel_mtl_tbt_clock_select(i915, 
crtc_state->port_clock));
+   val |= XELPDP_FORWARD_CLOCK_UNGATE;
+   intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
+XELPDP_DDI_CLOCK_SELECT_MASK | 
XELPDP_FORWARD_CLOCK_UNGATE, val);
+
+   /* 2. Read back PORT_CLOCK_CTL REGISTER */
+   val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   /*
+* 3. Follow the Display Voltage Frequency Switching - Sequence
+* Before Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 4. Set PORT_CLOCK_CTL register TBT CLOCK Request to "1" to enable 
PLL.
+*/
+   val |= XELPDP_TBT_CLOCK_REQUEST;
+   intel_de_write(i915, XELPDP_PORT_CLOCK_CTL(encoder->port), val);
+
+   /* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */
+   if (__intel_de_wait_for_register(i915, 
XELPDP_PORT_CLOCK_CTL(encoder->port),
+XELPDP_TBT_CLOCK_ACK,
+XELPDP_TBT_CLOCK_ACK,
+100, 0, NULL))
+   drm_warn(>drm, "[ENCODER:%d:%s][%c] PHY PLL not locked 
after 100us.\n",
+encoder->base.base.id, encoder->base.name, 
phy_name(phy));
+
+   /*
+* 6. Follow the Display Voltage Frequency Switching Sequence After
+* Frequency Change. We handle this step in bxt_set_cdclk().
+*/
+
+   /*
+* 7. Program DDI_CLK_VALFREQ to match intended DDI
+* clock frequency.
+*/
+   intel_de_write(i915, DDI_CLK_VALFREQ(encoder->port),
+  crtc_state->port_clock);
+}
+
+void intel_mtl_pll_enable(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+{
+   struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+
+   if (intel_tc_port_in_tbt_alt_mode(dig_port))
+   intel_mtl_tbt_pll_enable(encoder, crtc_state);
+   else
+   intel_cx0pll_enable(encoder, crtc_state);
+}
+
+static void intel_cx0pll_disable(struct intel_encoder *encoder)
 {
struct drm_i915_private *i915 = to_i915(encoder->base

[Intel-gfx] [PATCH v5 14/22] drm/i915/mtl: For DP2.0 10G and 20G rates use MPLLA

2023-03-16 Thread Mika Kahola
Use MPLLA for DP2.0 rates 20G and 20G, when ssc is enabled.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 55ec256c0379..e1a919803241 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2220,8 +2220,12 @@ static void intel_program_port_clock_ctl(struct 
intel_encoder *encoder,
if (!intel_panel_use_ssc(i915))
ssc_enabled = false;
 
-   /* TODO: DP2.0 10G and 20G rates enable MPLLA*/
-   val |= ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+   /* DP2.0 10G and 20G rates enable MPLLA*/
+   if (crtc_state->port_clock == 100 || crtc_state->port_clock 
== 200) {
+   val |= ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0;
+   } else {
+   val |= ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0;
+   }
}
 
intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(encoder->port),
-- 
2.34.1



[Intel-gfx] [PATCH v5 12/22] drm/i915/mtl: C20 HDMI state calculations

2023-03-16 Thread Mika Kahola
Add C20 HDMI state calculations and put HDMI table definitions
in use.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 23ebea25aaa9..55ec256c0379 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -1632,6 +1632,8 @@ intel_c20_pll_tables_get(struct intel_crtc_state 
*crtc_state,
 {
if (intel_crtc_has_dp_encoder(crtc_state)) {
return mtl_c20_dp_tables;
+   } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+   return mtl_c20_hdmi_tables;
}
 
MISSING_CASE(encoder->type);
@@ -1672,9 +1674,19 @@ static int intel_c10mpllb_calc_state(struct 
intel_crtc_state *crtc_state,
 static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
   struct intel_encoder *encoder)
 {
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
const struct intel_c20pll_state * const *tables;
int i;
 
+   if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+   if (intel_c20_phy_check_hdmi_link_rate(crtc_state->port_clock) 
!= MODE_OK) {
+   drm_dbg_kms(>drm, "Can't support HDMI link rate 
%d on phy %c.\n",
+   crtc_state->port_clock, phy_name(phy));
+   return -EINVAL;
+   }
+   }
+
tables = intel_c20_pll_tables_get(crtc_state, encoder);
if (!tables)
return -EINVAL;
-- 
2.34.1



[Intel-gfx] [PATCH v5 16/22] drm/i915/mtl: Readout Thunderbolt HW state

2023-03-16 Thread Mika Kahola
Readout hw state for Thunderbolt.

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c | 27 
 drivers/gpu/drm/i915/display/intel_cx0_phy.h |  2 +-
 drivers/gpu/drm/i915/display/intel_ddi.c |  5 +++-
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index ee281e9de301..083595cbc33b 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2539,6 +2539,33 @@ static void intel_cx0pll_enable(struct intel_encoder 
*encoder,
intel_cx0_phy_transaction_end(encoder, wakeref);
 }
 
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder)
+{
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   u32 clock;
+   u32 val = intel_de_read(i915, XELPDP_PORT_CLOCK_CTL(encoder->port));
+
+   clock = REG_FIELD_GET(XELPDP_DDI_CLOCK_SELECT_MASK, val);
+
+   drm_WARN_ON(>drm, !(val & XELPDP_FORWARD_CLOCK_UNGATE));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_REQUEST));
+   drm_WARN_ON(>drm, !(val & XELPDP_TBT_CLOCK_ACK));
+
+   switch (clock) {
+   case XELPDP_DDI_CLOCK_SELECT_TBT_162:
+   return 162000;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_270:
+   return 27;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_540:
+   return 54;
+   case XELPDP_DDI_CLOCK_SELECT_TBT_810:
+   return 81;
+   default:
+   MISSING_CASE(clock);
+   return 162000;
+   }
+}
+
 static int intel_mtl_tbt_clock_select(struct drm_i915_private *i915, int clock)
 {
switch (clock) {
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index f8a86da4a3f7..9e115ec619ea 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -53,5 +53,5 @@ int intel_c20_phy_check_hdmi_link_rate(int clock);
 void intel_cx0_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
   const struct intel_crtc_state 
*crtc_state,
   u32 level);
-int intel_mtl_tbt_readout_hw_state(struct intel_encoder *encoder);
+int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
 #endif /* __INTEL_CX0_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
index 298cc3ef6c4f..45df36b89162 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3515,8 +3515,11 @@ static void mtl_ddi_get_config(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_digital_port *dig_port = enc_to_dig_port(encoder);
 
-   if (intel_is_c10phy(i915, phy)) {
+   if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
+   crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
+   } else if (intel_is_c10phy(i915, phy)) {
intel_c10mpllb_readout_hw_state(encoder, 
_state->cx0pll_state.c10mpllb_state);
intel_c10mpllb_dump_hw_state(i915, 
_state->cx0pll_state.c10mpllb_state);
crtc_state->port_clock = 
intel_c10mpllb_calc_port_clock(encoder, 
_state->cx0pll_state.c10mpllb_state);
-- 
2.34.1



[Intel-gfx] [PATCH v5 19/22] drm/i915/mtl: Define mask for DDI AUX interrupts

2023-03-16 Thread Mika Kahola
From: Gustavo Sousa 

Xe_LPD+ defines interrupt bits for only DDI ports in the DE Port
Interrupt registers. The bits for Type-C ports are defined in the PICA
interrupt registers.

BSpec: 50064
Signed-off-by: Gustavo Sousa 
---
 drivers/gpu/drm/i915/i915_irq.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index e301f4755417..7eef4a5bab46 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1923,7 +1923,10 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private 
*dev_priv)
 {
u32 mask;
 
-   if (DISPLAY_VER(dev_priv) >= 13)
+   if (DISPLAY_VER(dev_priv) >= 14)
+   return TGL_DE_PORT_AUX_DDIA |
+   TGL_DE_PORT_AUX_DDIB;
+   else if (DISPLAY_VER(dev_priv) >= 13)
return TGL_DE_PORT_AUX_DDIA |
TGL_DE_PORT_AUX_DDIB |
TGL_DE_PORT_AUX_DDIC |
-- 
2.34.1



[Intel-gfx] [PATCH v5 18/22] drm/i915/mtl: MTL PICA hotplug detection

2023-03-16 Thread Mika Kahola
PICA is used for DP alt mode and TBT modes. Hotplug interruption is routed
from PICA chip to south display engine and from there to north display
engine. This patch adds functionality to enable hotplug detection for
all Type-C ports (4 ports available).

Differently from HPD in south display, PICA provides a dedicated HPD
control register for each supported port, so we loop over ports
ourselves instead of using intel_hpd_hotplug_enables() or
intel_get_hpd_pins().

BSpec: 49305, 55726, 65107, 65300

Signed-off-by: Mika Kahola 
Signed-off-by: Madhumitha Tolakanahalli Pradeep 

Signed-off-by: Gustavo Sousa 
Signed-off-by: Imre Deak 
---
 drivers/gpu/drm/i915/i915_irq.c | 249 +++-
 drivers/gpu/drm/i915/i915_reg.h |  31 +++-
 2 files changed, 273 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4de7edc6c751..e301f4755417 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -160,6 +160,13 @@ static const u32 hpd_gen11[HPD_NUM_PINS] = {
[HPD_PORT_TC6] = GEN11_TC_HOTPLUG(HPD_PORT_TC6) | 
GEN11_TBT_HOTPLUG(HPD_PORT_TC6),
 };
 
+static const u32 hpd_xelpdp[HPD_NUM_PINS] = {
+   [HPD_PORT_TC1] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC1) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC1),
+   [HPD_PORT_TC2] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC2) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC2),
+   [HPD_PORT_TC3] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC3) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC3),
+   [HPD_PORT_TC4] = XELPDP_TBT_HOTPLUG(HPD_PORT_TC4) | 
XELPDP_DP_ALT_HOTPLUG(HPD_PORT_TC4),
+};
+
 static const u32 hpd_icp[HPD_NUM_PINS] = {
[HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
[HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
@@ -180,6 +187,16 @@ static const u32 hpd_sde_dg1[HPD_NUM_PINS] = {
[HPD_PORT_TC1] = SDE_TC_HOTPLUG_DG2(HPD_PORT_TC1),
 };
 
+static const u32 hpd_mtp[HPD_NUM_PINS] = {
+   [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_A),
+   [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(HPD_PORT_B),
+   [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC1),
+   [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC2),
+   [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC3),
+   [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(HPD_PORT_TC4),
+};
+
+
 static void intel_hpd_init_pins(struct drm_i915_private *dev_priv)
 {
struct intel_hotplug *hpd = _priv->display.hotplug;
@@ -193,7 +210,9 @@ static void intel_hpd_init_pins(struct drm_i915_private 
*dev_priv)
return;
}
 
-   if (DISPLAY_VER(dev_priv) >= 11)
+   if (DISPLAY_VER(dev_priv) >= 14)
+   hpd->hpd = hpd_xelpdp;
+   else if (DISPLAY_VER(dev_priv) >= 11)
hpd->hpd = hpd_gen11;
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
hpd->hpd = hpd_bxt;
@@ -212,6 +231,8 @@ static void intel_hpd_init_pins(struct drm_i915_private 
*dev_priv)
 
if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1)
hpd->pch_hpd = hpd_sde_dg1;
+   else if (INTEL_PCH_TYPE(dev_priv) >= PCH_MTP)
+   hpd->pch_hpd = hpd_mtp;
else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
hpd->pch_hpd = hpd_icp;
else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv))
@@ -1557,6 +1578,44 @@ static void cpt_irq_handler(struct drm_i915_private 
*dev_priv, u32 pch_iir)
cpt_serr_int_handler(dev_priv);
 }
 
+static void xelpdp_pica_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
+{
+   enum hpd_pin pin;
+   u32 hotplug_trigger = iir & (XELPDP_DP_ALT_HOTPLUG_MASK | 
XELPDP_TBT_HOTPLUG_MASK);
+   u32 trigger_aux = iir & XELPDP_AUX_TC_MASK;
+   u32 pin_mask = 0, long_mask = 0;
+
+   for (pin = HPD_PORT_TC1; pin <= HPD_PORT_TC4; pin++) {
+   u32 val;
+
+   if (!(dev_priv->display.hotplug.hpd[pin] & hotplug_trigger))
+   continue;
+
+   pin_mask |= BIT(pin);
+
+   val = intel_uncore_read(_priv->uncore, 
XELPDP_PORT_HOTPLUG_CTL(pin));
+   intel_uncore_write(_priv->uncore, 
XELPDP_PORT_HOTPLUG_CTL(pin), val);
+
+   if (val & (XELPDP_DP_ALT_HPD_LONG_DETECT | 
XELPDP_TBT_HPD_LONG_DETECT))
+   long_mask |= BIT(pin);
+   }
+
+   if (pin_mask) {
+   drm_dbg(_priv->drm,
+   "pica hotplug event received, stat 0x%08x, pins 0x%08x, 
long 0x%08x\n",
+   hotplug_trigger, pin_mask, long_mask);
+
+   intel_hpd_irq_handler(dev_priv, pin_mask, long_mask);
+   }
+
+   if (trigger_aux)
+   dp_aux_irq_handler(dev_priv);
+
+   if (!pin_mask && !trigger_aux)
+   drm_err(_priv->drm,
+   "Unexpected DE HPD/AUX interrupt 0x%08x\n", iir);
+}
+
 static void icp_irq

[Intel-gfx] [PATCH v5 13/22] drm/i915/mtl: Add voltage swing sequence for C20

2023-03-16 Thread Mika Kahola
DP1.4 and DP20 voltage swing sequence for C20 phy.

Bspec: 65449, 67636, 67610

v2: DP2.0 Tx Eq tables has been updated in BSpec.
Update also the driver code as per BSpec 65449

Signed-off-by: Mika Kahola 
Signed-off-by: Radhakrishna Sripada 
Signed-off-by: Clint Taylor 
---
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h |  4 ++
 .../drm/i915/display/intel_ddi_buf_trans.c| 51 ++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
index 929a8aa243c3..f8917f20a151 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy_regs.h
@@ -216,6 +216,10 @@
 #define C20_MPLLA_TX_CLK_DIV_MASK   REG_GENMASK(10, 8)
 #define C20_FB_CLK_DIV4_EN  REG_BIT(13)
 
+/* C20 Phy VSwing Masks */
+#define C20_PHY_VSWING_PREEMPH_MASKREG_GENMASK8(5, 0)
+#define C20_PHY_VSWING_PREEMPH(val)
REG_FIELD_PREP8(C20_PHY_VSWING_PREEMPH_MASK, val)
+
 #define RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(idx)(0x303D + (idx))
 
 #endif /* __INTEL_CX0_PHY_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c 
b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
index d5a9aa2de2fa..883084422f1f 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
@@ -9,6 +9,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_cx0_phy.h"
 
 /* HDMI/DVI modes ignore everything but the last 2 items. So we share
  * them for both DP and FDI transports, allowing those ports to
@@ -1059,6 +1060,46 @@ static const struct intel_ddi_buf_trans mtl_cx0_trans = {
.hdmi_default_entry = ARRAY_SIZE(_mtl_c10_trans_dp14) - 1,
 };
 
+/* HDMI2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_hdmi[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 38, 4, 6 } },   /* preset 1 */
+   { .snps = { 36, 4, 8 } },   /* preset 2 */
+   { .snps = { 34, 4, 10 } },  /* preset 3 */
+   { .snps = { 32, 4, 12 } },  /* preset 4 */
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_hdmi = {
+   .entries = _mtl_c20_trans_hdmi,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_hdmi),
+   .hdmi_default_entry = 0,
+};
+
+/* DP2.0 */
+static const union intel_ddi_buf_trans_entry _mtl_c20_trans_uhbr[] = {
+   { .snps = { 48, 0, 0 } },   /* preset 0 */
+   { .snps = { 43, 0, 5 } },   /* preset 1 */
+   { .snps = { 40, 0, 8 } },   /* preset 2 */
+   { .snps = { 37, 0, 11 } },  /* preset 3 */
+   { .snps = { 33, 0, 15 } },  /* preset 4 */
+   { .snps = { 46, 2, 0 } },   /* preset 5 */
+   { .snps = { 42, 2, 4 } },   /* preset 6 */
+   { .snps = { 38, 2, 8 } },   /* preset 7 */
+   { .snps = { 35, 2, 11 } },  /* preset 8 */
+   { .snps = { 33, 2, 13 } },  /* preset 9 */
+   { .snps = { 44, 4, 0 } },   /* preset 10 */
+   { .snps = { 40, 4, 4 } },   /* preset 11 */
+   { .snps = { 37, 4, 7 } },   /* preset 12 */
+   { .snps = { 33, 4, 11 } },  /* preset 13 */
+   { .snps = { 40, 8, 0 } },   /* preset 14 */
+   { .snps = { 28, 2, 2 } },   /* preset 15 */
+};
+
+static const struct intel_ddi_buf_trans mtl_c20_trans_uhbr = {
+   .entries = _mtl_c20_trans_uhbr,
+   .num_entries = ARRAY_SIZE(_mtl_c20_trans_uhbr),
+};
+
 bool is_hobl_buf_trans(const struct intel_ddi_buf_trans *table)
 {
return table == _combo_phy_trans_edp_hbr2_hobl;
@@ -1635,7 +1676,15 @@ mtl_get_cx0_buf_trans(struct intel_encoder *encoder,
  const struct intel_crtc_state *crtc_state,
  int *n_entries)
 {
-   return intel_get_buf_trans(_cx0_trans, n_entries);
+   struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+   enum phy phy = intel_port_to_phy(i915, encoder->port);
+
+   if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock > 
100)
+   return intel_get_buf_trans(_c20_trans_uhbr, n_entries);
+   else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && 
!(intel_is_c10phy(i915, phy)))
+   return intel_get_buf_trans(_c20_trans_hdmi, n_entries);
+   else
+   return intel_get_buf_trans(_cx0_trans, n_entries);
 }
 
 void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
-- 
2.34.1



[Intel-gfx] [PATCH v5 11/22] drm/i915/mtl: C20 port clock calculation

2023-03-16 Thread Mika Kahola
Calculate port clock with C20 phy.

v2: Initialize parameters
v3: Revised formula for port clock check

Signed-off-by: Mika Kahola 
---
 drivers/gpu/drm/i915/display/intel_cx0_phy.c  | 70 ++-
 drivers/gpu/drm/i915/display/intel_cx0_phy.h  |  2 +
 .../gpu/drm/i915/display/intel_cx0_phy_regs.h | 12 ++--
 drivers/gpu/drm/i915/display/intel_ddi.c  |  4 +-
 4 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index bc6913a7444a..23ebea25aaa9 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -1626,6 +1626,18 @@ intel_c10_mpllb_tables_get(struct intel_crtc_state 
*crtc_state,
return NULL;
 }
 
+static const struct intel_c20pll_state * const *
+intel_c20_pll_tables_get(struct intel_crtc_state *crtc_state,
+struct intel_encoder *encoder)
+{
+   if (intel_crtc_has_dp_encoder(crtc_state)) {
+   return mtl_c20_dp_tables;
+   }
+
+   MISSING_CASE(encoder->type);
+   return NULL;
+}
+
 static int intel_c10mpllb_calc_state(struct intel_crtc_state *crtc_state,
 struct intel_encoder *encoder)
 {
@@ -1657,15 +1669,36 @@ static int intel_c10mpllb_calc_state(struct 
intel_crtc_state *crtc_state,
return -EINVAL;
 }
 
+static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state,
+  struct intel_encoder *encoder)
+{
+   const struct intel_c20pll_state * const *tables;
+   int i;
+
+   tables = intel_c20_pll_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->cx0pll_state.c20pll_state = *tables[i];
+   return 0;
+   }
+   }
+
+   return -EINVAL;
+}
+
 int intel_cx0mpllb_calc_state(struct intel_crtc_state *crtc_state,
  struct intel_encoder *encoder)
 {
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(i915, encoder->port);
 
-   drm_WARN_ON(>drm, !intel_is_c10phy(i915, phy));
-
-   return intel_c10mpllb_calc_state(crtc_state, encoder);
+   if (intel_is_c10phy(i915, phy))
+   return intel_c10mpllb_calc_state(crtc_state, encoder);
+   else
+   return intel_c20pll_calc_state(crtc_state, encoder);
 }
 
 void intel_c10mpllb_readout_hw_state(struct intel_encoder *encoder,
@@ -2111,6 +2144,37 @@ int intel_c10mpllb_calc_port_clock(struct intel_encoder 
*encoder,
return tmpclk;
 }
 
+int intel_c20pll_calc_port_clock(struct intel_encoder *encoder,
+const struct intel_c20pll_state *pll_state)
+{
+   unsigned int frac_quot = 0, frac_rem = 0, frac_den = 1;
+   unsigned int multiplier, refclk = 38400;
+   unsigned ref_clk_mpllb_div = 0;
+   unsigned fb_clk_div4_en = 0;
+   unsigned long tmp1, tmp2;
+
+   if (pll_state->mpllb[6] & C20_MPLLB_FRACEN) {
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mpllb[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mpllb[6]);
+   frac_den = pll_state->mpllb[7];
+   frac_quot = pll_state->mpllb[8];
+   frac_rem = pll_state->mpllb[9];
+   } else if (pll_state->mplla[6] & C20_MPLLA_FRACEN) {
+   multiplier = REG_FIELD_GET(C20_MULTIPLIER_MASK, 
pll_state->mplla[0]);
+   ref_clk_mpllb_div = REG_FIELD_GET(C20_REF_CLK_MPLLB_DIV_MASK, 
pll_state->mpllb[6]);
+   fb_clk_div4_en = REG_FIELD_GET(C20_FB_CLK_DIV4_EN, 
pll_state->mpllb[6]);
+   frac_den = pll_state->mpllb[7];
+   frac_quot = pll_state->mplla[8];
+   frac_rem = pll_state->mplla[9];
+   }
+
+   tmp1 = DIV_ROUND_CLOSEST(refclk * (1 << (1 + fb_clk_div4_en)), 1 << 
ref_clk_mpllb_div);
+   tmp2 = (multiplier << 15) + frac_quot + 
DIV_ROUND_CLOSEST(frac_rem,frac_den);
+
+   return DIV_ROUND_CLOSEST((tmp1 * tmp2) >> 17, 10);
+}
+
 static void intel_program_port_clock_ctl(struct intel_encoder *encoder,
 const struct intel_crtc_state 
*crtc_state,
 bool lane_reversal)
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h 
b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
index 0b46b2ad48a9..0a8e76fd101e 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h
@@ -43,6 +43,8 @@ int intel_c10mpllb_calc_port_clock(st

  1   2   3   4   5   6   7   8   9   10   >