mirror of
https://github.com/torvalds/linux.git
synced 2026-05-22 22:22:08 +02:00
drm/i915/ltphy: Phy lane reset for LT Phy
Define function to bring phy lane out of reset for LT Phy and the corresponding pre-requisite steps before we follow the steps for Phy lane reset. Also create a skeleton of LT PHY PLL enable sequence function in which we can place this function Bspec: 77449, 74749, 74499, 74495, 68960 Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com> Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com> Link: https://patch.msgid.link/20251101032513.4171255-4-suraj.kandpal@intel.com
This commit is contained in:
parent
66354f7f12
commit
154ebdb77a
|
|
@ -357,6 +357,7 @@ i915-y += \
|
|||
display/intel_gmbus.o \
|
||||
display/intel_hdmi.o \
|
||||
display/intel_lspcon.o \
|
||||
display/intel_lt_phy.o \
|
||||
display/intel_lvds.o \
|
||||
display/intel_panel.o \
|
||||
display/intel_pfit.o \
|
||||
|
|
|
|||
|
|
@ -2854,7 +2854,7 @@ static void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder,
|
|||
phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US);
|
||||
}
|
||||
|
||||
static void intel_cx0_setup_powerdown(struct intel_encoder *encoder)
|
||||
void intel_cx0_setup_powerdown(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
enum port port = encoder->port;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ bool intel_cx0pll_compare_hw_state(const struct intel_cx0pll_state *a,
|
|||
const struct intel_cx0pll_state *b);
|
||||
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);
|
||||
void intel_cx0_setup_powerdown(struct intel_encoder *encoder);
|
||||
int intel_mtl_tbt_calc_port_clock(struct intel_encoder *encoder);
|
||||
void intel_cx0_pll_power_save_wa(struct intel_display *display);
|
||||
void intel_lnl_mac_transmit_lfps(struct intel_encoder *encoder,
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@
|
|||
#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 XE3PLPDP_PHY_MODE_MASK REG_GENMASK(15, 12)
|
||||
#define XE3PLPDP_PHY_MODE_DP REG_FIELD_PREP(XE3PLPDP_PHY_MODE_MASK, 0x3)
|
||||
#define XELPDP_PORT_BUF_IO_SELECT_TBT REG_BIT(11)
|
||||
#define XELPDP_PORT_BUF_PHY_IDLE REG_BIT(7)
|
||||
#define XELPDP_TC_PHY_OWNERSHIP REG_BIT(6)
|
||||
|
|
@ -124,6 +126,7 @@
|
|||
_XELPDP_PORT_BUF_CTL2(port))
|
||||
#define XELPDP_LANE_PIPE_RESET(lane) _PICK(lane, REG_BIT(31), REG_BIT(30))
|
||||
#define XELPDP_LANE_PHY_CURRENT_STATUS(lane) _PICK(lane, REG_BIT(29), REG_BIT(28))
|
||||
#define XE3PLPDP_LANE_PHY_PULSE_STATUS(lane) _PICK(lane, REG_BIT(27), REG_BIT(26))
|
||||
#define XELPDP_LANE_POWERDOWN_UPDATE(lane) _PICK(lane, REG_BIT(25), REG_BIT(24))
|
||||
#define _XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK REG_GENMASK(23, 20)
|
||||
#define _XELPDP_LANE0_POWERDOWN_NEW_STATE(val) REG_FIELD_PREP(_XELPDP_LANE0_POWERDOWN_NEW_STATE_MASK, val)
|
||||
|
|
@ -151,6 +154,7 @@
|
|||
#define XELPDP_POWER_STATE_ACTIVE(val) REG_FIELD_PREP(XELPDP_POWER_STATE_ACTIVE_MASK, val)
|
||||
#define XELPDP_P0_STATE_ACTIVE 0x0
|
||||
#define XELPDP_P2_STATE_READY 0x2
|
||||
#define XE3PLPD_P4_STATE_DISABLE 0x4
|
||||
#define XELPDP_P2PG_STATE_DISABLE 0x9
|
||||
#define XELPDP_P4PG_STATE_DISABLE 0xC
|
||||
#define XELPDP_P2_STATE_RESET 0x2
|
||||
|
|
|
|||
159
drivers/gpu/drm/i915/display/intel_lt_phy.c
Normal file
159
drivers/gpu/drm/i915/display/intel_lt_phy.c
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "intel_cx0_phy.h"
|
||||
#include "intel_cx0_phy_regs.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_lt_phy.h"
|
||||
#include "intel_lt_phy_regs.h"
|
||||
#include "intel_tc.h"
|
||||
|
||||
#define INTEL_LT_PHY_LANE0 BIT(0)
|
||||
#define INTEL_LT_PHY_LANE1 BIT(1)
|
||||
#define INTEL_LT_PHY_BOTH_LANES (INTEL_LT_PHY_LANE1 |\
|
||||
INTEL_LT_PHY_LANE0)
|
||||
|
||||
static u8 intel_lt_phy_get_owned_lane_mask(struct intel_encoder *encoder)
|
||||
{
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
|
||||
if (!intel_tc_port_in_dp_alt_mode(dig_port))
|
||||
return INTEL_LT_PHY_BOTH_LANES;
|
||||
|
||||
return intel_tc_port_max_lane_count(dig_port) > 2
|
||||
? INTEL_LT_PHY_BOTH_LANES : INTEL_LT_PHY_LANE0;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_lt_phy_setup_powerdown(struct intel_encoder *encoder, u8 lane_count)
|
||||
{
|
||||
/*
|
||||
* The new PORT_BUF_CTL6 stuff for dc5 entry and exit needs to be handled
|
||||
* by dmc firmware not explicitly mentioned in Bspec. This leaves this
|
||||
* function as a wrapper only but keeping it expecting future changes.
|
||||
*/
|
||||
intel_cx0_setup_powerdown(encoder);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_lt_phy_lane_reset(struct intel_encoder *encoder,
|
||||
u8 lane_count)
|
||||
{
|
||||
struct intel_display *display = to_intel_display(encoder);
|
||||
enum port port = encoder->port;
|
||||
enum phy phy = intel_encoder_to_phy(encoder);
|
||||
u8 owned_lane_mask = intel_lt_phy_get_owned_lane_mask(encoder);
|
||||
u32 lane_pipe_reset = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
|
||||
? XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1)
|
||||
: XELPDP_LANE_PIPE_RESET(0);
|
||||
u32 lane_phy_current_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
|
||||
? (XELPDP_LANE_PHY_CURRENT_STATUS(0) |
|
||||
XELPDP_LANE_PHY_CURRENT_STATUS(1))
|
||||
: XELPDP_LANE_PHY_CURRENT_STATUS(0);
|
||||
u32 lane_phy_pulse_status = owned_lane_mask == INTEL_LT_PHY_BOTH_LANES
|
||||
? (XE3PLPDP_LANE_PHY_PULSE_STATUS(0) |
|
||||
XE3PLPDP_LANE_PHY_PULSE_STATUS(1))
|
||||
: XE3PLPDP_LANE_PHY_PULSE_STATUS(0);
|
||||
|
||||
intel_de_rmw(display, XE3PLPD_PORT_BUF_CTL5(port),
|
||||
XE3PLPD_MACCLK_RATE_MASK, XE3PLPD_MACCLK_RATE_DEF);
|
||||
|
||||
intel_de_rmw(display, XELPDP_PORT_BUF_CTL1(display, port),
|
||||
XE3PLPDP_PHY_MODE_MASK, XE3PLPDP_PHY_MODE_DP);
|
||||
|
||||
intel_lt_phy_setup_powerdown(encoder, lane_count);
|
||||
|
||||
intel_de_rmw(display, XE3PLPD_PORT_BUF_CTL5(port),
|
||||
XE3PLPD_MACCLK_RESET_0, 0);
|
||||
|
||||
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port),
|
||||
XELPDP_LANE_PCLK_PLL_REQUEST(0),
|
||||
XELPDP_LANE_PCLK_PLL_REQUEST(0));
|
||||
|
||||
if (intel_de_wait_custom(display, XELPDP_PORT_CLOCK_CTL(display, port),
|
||||
XELPDP_LANE_PCLK_PLL_ACK(0),
|
||||
XELPDP_LANE_PCLK_PLL_ACK(0),
|
||||
XE3PLPD_MACCLK_TURNON_LATENCY_US,
|
||||
XE3PLPD_MACCLK_TURNON_LATENCY_MS, NULL))
|
||||
drm_warn(display->drm, "PHY %c PLL MacCLK assertion Ack not done after %dus.\n",
|
||||
phy_name(phy), XE3PLPD_MACCLK_TURNON_LATENCY_MS * 1000);
|
||||
|
||||
intel_de_rmw(display, XELPDP_PORT_CLOCK_CTL(display, port),
|
||||
XELPDP_FORWARD_CLOCK_UNGATE,
|
||||
XELPDP_FORWARD_CLOCK_UNGATE);
|
||||
|
||||
intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port),
|
||||
lane_pipe_reset | lane_phy_pulse_status, 0);
|
||||
|
||||
if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port),
|
||||
lane_phy_current_status, 0,
|
||||
XE3PLPD_RESET_END_LATENCY_US, 2, NULL))
|
||||
drm_warn(display->drm,
|
||||
"PHY %c failed to bring out of Lane reset after %dus.\n",
|
||||
phy_name(phy), XE3PLPD_RESET_END_LATENCY_US);
|
||||
|
||||
if (intel_de_wait_custom(display, XELPDP_PORT_BUF_CTL2(display, port),
|
||||
lane_phy_pulse_status, lane_phy_pulse_status,
|
||||
XE3PLPD_RATE_CALIB_DONE_LATENCY_US, 0, NULL))
|
||||
drm_warn(display->drm, "PHY %c PLL rate not changed after %dus.\n",
|
||||
phy_name(phy), XE3PLPD_RATE_CALIB_DONE_LATENCY_US);
|
||||
|
||||
intel_de_rmw(display, XELPDP_PORT_BUF_CTL2(display, port), lane_phy_pulse_status, 0);
|
||||
}
|
||||
|
||||
void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
/* 1. Enable MacCLK at default 162 MHz frequency. */
|
||||
intel_lt_phy_lane_reset(encoder, crtc_state->lane_count);
|
||||
|
||||
/* 2. Program PORT_CLOCK_CTL register to configure clock muxes, gating, and SSC. */
|
||||
/* 3. Change owned PHY lanes power to Ready state. */
|
||||
/*
|
||||
* 4. Read the PHY message bus VDR register PHY_VDR_0_Config check enabled PLL type,
|
||||
* encoded rate and encoded mode.
|
||||
*/
|
||||
/*
|
||||
* 5. Program the PHY internal PLL registers over PHY message bus for the desired
|
||||
* frequency and protocol type
|
||||
*/
|
||||
/* 6. Use the P2P transaction flow */
|
||||
/*
|
||||
* 6.1. Set the PHY VDR register 0xCC4[Rate Control VDR Update] = 1 over PHY message
|
||||
* bus for Owned PHY Lanes.
|
||||
*/
|
||||
/*
|
||||
* 6.2. Poll for P2P Transaction Ready = "1" and read the MAC message bus VDR register
|
||||
* at offset 0xC00 for Owned PHY Lanes.
|
||||
*/
|
||||
/* 6.3. Clear P2P transaction Ready bit. */
|
||||
/* 7. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 0. */
|
||||
/* 8. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 0. */
|
||||
/*
|
||||
* 9. Follow the Display Voltage Frequency Switching - Sequence Before Frequency Change.
|
||||
* We handle this step in bxt_set_cdclk()
|
||||
*/
|
||||
/* 10. Program DDI_CLK_VALFREQ to match intended DDI clock frequency. */
|
||||
/* 11. Program PORT_CLOCK_CTL[PCLK PLL Request LN0] = 1. */
|
||||
/* 12. Poll for PORT_CLOCK_CTL[PCLK PLL Ack LN0]= 1. */
|
||||
/* 13. Ungate the forward clock by setting PORT_CLOCK_CTL[Forward Clock Ungate] = 1. */
|
||||
/* 14. SW clears PORT_BUF_CTL2 [PHY Pulse Status]. */
|
||||
/*
|
||||
* 15. Clear the PHY VDR register 0xCC4[Rate Control VDR Update] over PHY message bus for
|
||||
* Owned PHY Lanes.
|
||||
*/
|
||||
/* 16. Poll for PORT_BUF_CTL2 register PHY Pulse Status = 1 for Owned PHY Lanes. */
|
||||
/* 17. SW clears PORT_BUF_CTL2 [PHY Pulse Status]. */
|
||||
/*
|
||||
* 18. Follow the Display Voltage Frequency Switching - Sequence After Frequency Change.
|
||||
* We handle this step in bxt_set_cdclk()
|
||||
*/
|
||||
/* 19. Move the PHY powerdown state to Active and program to enable/disable transmitters */
|
||||
}
|
||||
17
drivers/gpu/drm/i915/display/intel_lt_phy.h
Normal file
17
drivers/gpu/drm/i915/display/intel_lt_phy.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright © 2025 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_LT_PHY_H__
|
||||
#define __INTEL_LT_PHY_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct intel_encoder;
|
||||
struct intel_crtc_state;
|
||||
|
||||
void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_LT_PHY_H__ */
|
||||
|
|
@ -6,6 +6,12 @@
|
|||
#ifndef __INTEL_LT_PHY_REGS_H__
|
||||
#define __INTEL_LT_PHY_REGS_H__
|
||||
|
||||
#define XE3PLPD_MACCLK_TURNON_LATENCY_MS 1
|
||||
#define XE3PLPD_MACCLK_TURNON_LATENCY_US 21
|
||||
#define XE3PLPD_RATE_CALIB_DONE_LATENCY_US 50
|
||||
#define XE3PLPD_RESET_START_LATENCY_US 10
|
||||
#define XE3PLPD_RESET_END_LATENCY_US 200
|
||||
|
||||
/* LT Phy Vendor Register */
|
||||
#define LT_PHY_VDR_0_CONFIG 0xC02
|
||||
#define LT_PHY_VDR_DP_PLL_ENABLE REG_BIT(7)
|
||||
|
|
@ -21,4 +27,15 @@
|
|||
|
||||
#define LT_PHY_RATE_UPDATE 0xCC4
|
||||
|
||||
#define _XE3PLPD_PORT_BUF_CTL5(idx) _MMIO(_PICK_EVEN_2RANGES(idx, PORT_TC1, \
|
||||
_XELPDP_PORT_BUF_CTL1_LN0_A, \
|
||||
_XELPDP_PORT_BUF_CTL1_LN0_B, \
|
||||
_XELPDP_PORT_BUF_CTL1_LN0_USBC1, \
|
||||
_XELPDP_PORT_BUF_CTL1_LN0_USBC2) \
|
||||
+ 0x34)
|
||||
#define XE3PLPD_PORT_BUF_CTL5(port) _XE3PLPD_PORT_BUF_CTL5(__xe2lpd_port_idx(port))
|
||||
#define XE3PLPD_MACCLK_RESET_0 REG_BIT(11)
|
||||
#define XE3PLPD_MACCLK_RATE_MASK REG_GENMASK(4, 0)
|
||||
#define XE3PLPD_MACCLK_RATE_DEF REG_FIELD_PREP(XE3PLPD_MACCLK_RATE_MASK, 0x1F)
|
||||
|
||||
#endif /* __INTEL_LT_PHY_REGS_H__ */
|
||||
|
|
|
|||
|
|
@ -290,6 +290,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
|
|||
i915-display/intel_hti.o \
|
||||
i915-display/intel_link_bw.o \
|
||||
i915-display/intel_lspcon.o \
|
||||
i915-display/intel_lt_phy.o \
|
||||
i915-display/intel_modeset_lock.o \
|
||||
i915-display/intel_modeset_setup.o \
|
||||
i915-display/intel_modeset_verify.o \
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user