Skip to content

Commit

Permalink
drm/i915: Create a struct to hold information about the broxton phys
Browse files Browse the repository at this point in the history
Information about which phy is dual channel is hardcoded in the phy init
sequence. Split that to a separate struct so the init sequence is more
generic.

v2: Restore mangled part that ended up in following patch. (Imre)

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/9102f4c984044126057e4fdd1b91a615ff25fae6.1475770848.git-series.ander.conselvan.de.oliveira@intel.com
  • Loading branch information
Ander Conselvan de Oliveira committed Oct 28, 2016
1 parent b6e0820 commit 842d416
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 12 deletions.
9 changes: 7 additions & 2 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1307,8 +1307,13 @@ enum skl_disp_power_wells {
#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \
_PORT_CL1CM_DW30_A)

/* Defined for PHY0 only */
#define BXT_PORT_CL2CM_DW6_BC _MMIO(0x6C358)
/* The spec defines this only for BXT PHY0, but lets assume that this
* would exist for PHY1 too if it had a second channel.
*/
#define _PORT_CL2CM_DW6_A 0x162358
#define _PORT_CL2CM_DW6_BC 0x6C358
#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC, \
_PORT_CL2CM_DW6_A)
#define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28)

/* BXT PHY Ref registers */
Expand Down
65 changes: 55 additions & 10 deletions drivers/gpu/drm/i915/intel_dpio_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,50 @@
* -----------------
*/

/**
* struct bxt_ddi_phy_info - Hold info for a broxton DDI phy
*/
struct bxt_ddi_phy_info {
/**
* @dual_channel: true if this phy has a second channel.
*/
bool dual_channel;

/**
* @channel: struct containing per channel information.
*/
struct {
/**
* @port: which port maps to this channel.
*/
enum port port;
} channel[2];
};

static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = {
[DPIO_PHY0] = {
.dual_channel = true,

.channel = {
[DPIO_CH0] = { .port = PORT_B },
[DPIO_CH1] = { .port = PORT_C },
}
},
[DPIO_PHY1] = {
.dual_channel = false,

.channel = {
[DPIO_CH0] = { .port = PORT_A },
}
},
};

static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info)
{
return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) |
BIT(phy_info->channel[DPIO_CH0].port);
}

void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
enum port port, u32 margin, u32 scale,
u32 enable, u32 deemphasis)
Expand Down Expand Up @@ -156,6 +200,7 @@ void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
enum dpio_phy phy)
{
const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
enum port port;

if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy)))
Expand Down Expand Up @@ -183,9 +228,7 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
return false;
}

for_each_port_masked(port,
phy == DPIO_PHY0 ? BIT(PORT_B) | BIT(PORT_C) :
BIT(PORT_A)) {
for_each_port_masked(port, bxt_phy_port_mask(phy_info)) {
u32 tmp = I915_READ(BXT_PHY_CTL(port));

if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) {
Expand Down Expand Up @@ -220,6 +263,7 @@ static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv,

void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
{
const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
u32 val;

if (bxt_ddi_phy_is_enabled(dev_priv, phy)) {
Expand Down Expand Up @@ -272,10 +316,10 @@ void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
SUS_CLK_CONFIG;
I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val);

if (phy == DPIO_PHY0) {
val = I915_READ(BXT_PORT_CL2CM_DW6_BC);
if (phy_info->dual_channel) {
val = I915_READ(BXT_PORT_CL2CM_DW6(phy));
val |= DW6_OLDO_DYN_PWR_DOWN_EN;
I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val);
I915_WRITE(BXT_PORT_CL2CM_DW6(phy), val);
}

val = I915_READ(BXT_PORT_CL1CM_DW30(phy));
Expand All @@ -290,7 +334,7 @@ void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
* FIXME: Clarify programming of the following, the register is
* read-only with bit 6 fixed at 0 at least in stepping A.
*/
if (phy == DPIO_PHY1)
if (!phy_info->dual_channel)
val |= OCL2_LDOFUSE_PWR_DIS;
I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val);

Expand Down Expand Up @@ -363,6 +407,7 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
enum dpio_phy phy)
{
const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
uint32_t mask;
bool ok;

Expand All @@ -388,10 +433,10 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask,
"BXT_PORT_CL1CM_DW28(%d)", phy);

if (phy == DPIO_PHY0)
ok &= _CHK(BXT_PORT_CL2CM_DW6_BC,
if (phy_info->dual_channel)
ok &= _CHK(BXT_PORT_CL2CM_DW6(phy),
DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN,
"BXT_PORT_CL2CM_DW6_BC");
"BXT_PORT_CL2CM_DW6(%d)", phy);

/*
* TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS,
Expand Down

0 comments on commit 842d416

Please sign in to comment.