Skip to content

Commit

Permalink
drm/i915/tgl: Finish modular FIA support on registers
Browse files Browse the repository at this point in the history
If platform supports and has modular FIA is enabled, the registers
bits also change, example: reading TC3 registers with modular FIA
enabled, driver should read from FIA2 but with TC1 bits offsets.

It is described in BSpec 50231 for DFLEXDPSP, other registers don't
have the BSpec description but testing in real hardware have proven
that it had moved for all other registers too.

v2:
- Caching index in tc_phy_fia_idx, instead of calculate it each time

v3:
- Setting tc_phy_fia and tc_phy_fia_idx in the same function

Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190920205810.211048-3-jose.souza@intel.com
  • Loading branch information
José Roberto de Souza committed Sep 23, 2019
1 parent 6171e58 commit 31d9ae9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 48 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/display/intel_display_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,7 @@ struct intel_digital_port {
char tc_port_name[8];
enum tc_port_mode tc_mode;
enum phy_fia tc_phy_fia;
u8 tc_phy_fia_idx;

void (*write_infoframe)(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
Expand Down
72 changes: 38 additions & 34 deletions drivers/gpu/drm/i915/display/intel_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,38 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
return names[mode];
}

static bool has_modular_fia(struct drm_i915_private *i915)
{
if (!INTEL_INFO(i915)->display.has_modular_fia)
return false;

return intel_uncore_read(&i915->uncore,
PORT_TX_DFLEXDPSP(FIA1)) & MODULAR_FIA_MASK;
}

static enum phy_fia tc_port_to_fia(struct drm_i915_private *i915,
enum tc_port tc_port)
static void
tc_port_load_fia_params(struct drm_i915_private *i915,
struct intel_digital_port *dig_port)
{
if (!has_modular_fia(i915))
return FIA1;
enum port port = dig_port->base.port;
enum tc_port tc_port = intel_port_to_tc(i915, port);
u32 modular_fia;

if (INTEL_INFO(i915)->display.has_modular_fia) {
modular_fia = intel_uncore_read(&i915->uncore,
PORT_TX_DFLEXDPSP(FIA1));
modular_fia &= MODULAR_FIA_MASK;
} else {
modular_fia = 0;
}

/*
* Each Modular FIA instance houses 2 TC ports. In SOC that has more
* than two TC ports, there are multiple instances of Modular FIA.
*/
return tc_port / 2;
if (modular_fia) {
dig_port->tc_phy_fia = tc_port / 2;
dig_port->tc_phy_fia_idx = tc_port % 2;
} else {
dig_port->tc_phy_fia = FIA1;
dig_port->tc_phy_fia_idx = tc_port;
}
}

u32 intel_tc_port_get_lane_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);
struct intel_uncore *uncore = &i915->uncore;
u32 lane_mask;

Expand All @@ -57,8 +63,8 @@ u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)

WARN_ON(lane_mask == 0xffffffff);

return (lane_mask & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
DP_LANE_ASSIGNMENT_SHIFT(tc_port);
lane_mask &= DP_LANE_ASSIGNMENT_MASK(dig_port->tc_phy_fia_idx);
return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx);
}

int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
Expand Down Expand Up @@ -95,7 +101,6 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
int required_lanes)
{
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);
bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
struct intel_uncore *uncore = &i915->uncore;
u32 val;
Expand All @@ -104,19 +109,21 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,

val = intel_uncore_read(uncore,
PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia));
val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc_port);
val &= ~DFLEXDPMLE1_DPMLETC_MASK(dig_port->tc_phy_fia_idx);

switch (required_lanes) {
case 1:
val |= lane_reversal ? DFLEXDPMLE1_DPMLETC_ML3(tc_port) :
DFLEXDPMLE1_DPMLETC_ML0(tc_port);
val |= lane_reversal ?
DFLEXDPMLE1_DPMLETC_ML3(dig_port->tc_phy_fia_idx) :
DFLEXDPMLE1_DPMLETC_ML0(dig_port->tc_phy_fia_idx);
break;
case 2:
val |= lane_reversal ? DFLEXDPMLE1_DPMLETC_ML3_2(tc_port) :
DFLEXDPMLE1_DPMLETC_ML1_0(tc_port);
val |= lane_reversal ?
DFLEXDPMLE1_DPMLETC_ML3_2(dig_port->tc_phy_fia_idx) :
DFLEXDPMLE1_DPMLETC_ML1_0(dig_port->tc_phy_fia_idx);
break;
case 4:
val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc_port);
val |= DFLEXDPMLE1_DPMLETC_ML3_0(dig_port->tc_phy_fia_idx);
break;
default:
MISSING_CASE(required_lanes);
Expand Down Expand Up @@ -164,9 +171,9 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
return mask;
}

if (val & TC_LIVE_STATE_TBT(tc_port))
if (val & TC_LIVE_STATE_TBT(dig_port->tc_phy_fia_idx))
mask |= BIT(TC_PORT_TBT_ALT);
if (val & TC_LIVE_STATE_TC(tc_port))
if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx))
mask |= BIT(TC_PORT_DP_ALT);

if (intel_uncore_read(uncore, SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
Expand All @@ -182,7 +189,6 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
static bool icl_tc_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);
struct intel_uncore *uncore = &i915->uncore;
u32 val;

Expand All @@ -194,14 +200,13 @@ static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
return false;
}

return val & DP_PHY_MODE_STATUS_COMPLETED(tc_port);
return val & DP_PHY_MODE_STATUS_COMPLETED(dig_port->tc_phy_fia_idx);
}

static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
bool enable)
{
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);
struct intel_uncore *uncore = &i915->uncore;
u32 val;

Expand All @@ -215,9 +220,9 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
return false;
}

val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
if (!enable)
val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);

intel_uncore_write(uncore,
PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val);
Expand All @@ -232,7 +237,6 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
static bool icl_tc_phy_is_in_safe_mode(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);
struct intel_uncore *uncore = &i915->uncore;
u32 val;

Expand All @@ -244,7 +248,7 @@ static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
return true;
}

return !(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port));
return !(val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx));
}

/*
Expand Down Expand Up @@ -540,5 +544,5 @@ void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
mutex_init(&dig_port->tc_lock);
dig_port->tc_legacy_port = is_legacy;
dig_port->tc_link_refcount = 0;
dig_port->tc_phy_fia = tc_port_to_fia(i915, tc_port);
tc_port_load_fia_params(i915, dig_port);
}
28 changes: 14 additions & 14 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -2166,13 +2166,13 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define _MMIO_FIA(fia, off) _MMIO(_FIA(fia) + (off))

/* ICL PHY DFLEX registers */
#define PORT_TX_DFLEXDPMLE1(fia) _MMIO_FIA((fia), 0x008C0)
#define DFLEXDPMLE1_DPMLETC_MASK(tc_port) (0xf << (4 * (tc_port)))
#define DFLEXDPMLE1_DPMLETC_ML0(tc_port) (1 << (4 * (tc_port)))
#define DFLEXDPMLE1_DPMLETC_ML1_0(tc_port) (3 << (4 * (tc_port)))
#define DFLEXDPMLE1_DPMLETC_ML3(tc_port) (8 << (4 * (tc_port)))
#define DFLEXDPMLE1_DPMLETC_ML3_2(tc_port) (12 << (4 * (tc_port)))
#define DFLEXDPMLE1_DPMLETC_ML3_0(tc_port) (15 << (4 * (tc_port)))
#define PORT_TX_DFLEXDPMLE1(fia) _MMIO_FIA((fia), 0x008C0)
#define DFLEXDPMLE1_DPMLETC_MASK(idx) (0xf << (4 * (idx)))
#define DFLEXDPMLE1_DPMLETC_ML0(idx) (1 << (4 * (idx)))
#define DFLEXDPMLE1_DPMLETC_ML1_0(idx) (3 << (4 * (idx)))
#define DFLEXDPMLE1_DPMLETC_ML3(idx) (8 << (4 * (idx)))
#define DFLEXDPMLE1_DPMLETC_ML3_2(idx) (12 << (4 * (idx)))
#define DFLEXDPMLE1_DPMLETC_ML3_0(idx) (15 << (4 * (idx)))

/* BXT PHY Ref registers */
#define _PORT_REF_DW3_A 0x16218C
Expand Down Expand Up @@ -11688,17 +11688,17 @@ enum skl_power_gate {

#define PORT_TX_DFLEXDPSP(fia) _MMIO_FIA((fia), 0x008A0)
#define MODULAR_FIA_MASK (1 << 4)
#define TC_LIVE_STATE_TBT(tc_port) (1 << ((tc_port) * 8 + 6))
#define TC_LIVE_STATE_TC(tc_port) (1 << ((tc_port) * 8 + 5))
#define DP_LANE_ASSIGNMENT_SHIFT(tc_port) ((tc_port) * 8)
#define DP_LANE_ASSIGNMENT_MASK(tc_port) (0xf << ((tc_port) * 8))
#define DP_LANE_ASSIGNMENT(tc_port, x) ((x) << ((tc_port) * 8))
#define TC_LIVE_STATE_TBT(idx) (1 << ((idx) * 8 + 6))
#define TC_LIVE_STATE_TC(idx) (1 << ((idx) * 8 + 5))
#define DP_LANE_ASSIGNMENT_SHIFT(idx) ((idx) * 8)
#define DP_LANE_ASSIGNMENT_MASK(idx) (0xf << ((idx) * 8))
#define DP_LANE_ASSIGNMENT(idx, x) ((x) << ((idx) * 8))

#define PORT_TX_DFLEXDPPMS(fia) _MMIO_FIA((fia), 0x00890)
#define DP_PHY_MODE_STATUS_COMPLETED(tc_port) (1 << (tc_port))
#define DP_PHY_MODE_STATUS_COMPLETED(idx) (1 << (idx))

#define PORT_TX_DFLEXDPCSSS(fia) _MMIO_FIA((fia), 0x00894)
#define DP_PHY_MODE_STATUS_NOT_SAFE(tc_port) (1 << (tc_port))
#define DP_PHY_MODE_STATUS_NOT_SAFE(idx) (1 << (idx))

/* This register controls the Display State Buffer (DSB) engines. */
#define _DSBSL_INSTANCE_BASE 0x70B00
Expand Down

0 comments on commit 31d9ae9

Please sign in to comment.