Commit 06debd6e authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-next-2021-03-16' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

Highlights:
- Alderlake S enabling, via topic branch (Aditya, Anusha, Caz, José, Lucas, Matt, Tejas)
- Refactor display code to shrink intel_display.c etc. (Dave)
- Support more gen 9 and Tigerlake PCH combinations (Lyude, Tejas)
- Add eDP MSO support (Jani)

Display:
- Refactor to support multiple PSR instances (Gwan-gyeong)
- Link training debug logging updates (Sean)
- Updates to eDP fixed mode handling (Jani)
- Disable PSR2 on JSL/EHL (Edmund)
- Support DDR5 and LPDDR5 for bandwidth computation (Clint, José)
- Update VBT DP max link rate table (Shawn)
- Disable the QSES check for HDCP2.2 over MST (Juston)
- PSR updates, refactoring, selective fetch (José, Gwan-gyeong)
- Display init sequence refactoring (Lucas)
- Limit LSPCON to gen 9 and 10 platforms (Ankit)
- Fix DDI lane polarity per VBT info (Uma)
- Fix HDMI vswing programming location in mode set (Ville)
- Various display improvements and refactorings and cleanups (Ville)
- Clean up DDI clock routing and readout (Ville)
- Workaround async flip + VT-d corruption on HSW/BDW (Ville)
- SAGV watermark fixes and cleanups (Ville)
- Silence pipe tracepoint WARNs (Ville)

Other:
- Remove require_force_probe protection from RKL, may need to be revisited (Tejas)
- Detect loss of MMIO access (Matt)
- GVT display improvements
- drm/i915: Disable runtime power management during shutdown (Imre)
- Perf/OA updates (Umesh)
- Remove references to struct drm_device.pdev, via topic branch (Thomas)
- Backmerge (Jani)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87v99rnk1g.fsf@intel.com
parents 51c3b916 2b25fb31
......@@ -551,6 +551,7 @@ static const struct pci_device_id intel_early_ids[] __initconst = {
INTEL_EHL_IDS(&gen11_early_ops),
INTEL_TGL_12_IDS(&gen11_early_ops),
INTEL_RKL_IDS(&gen11_early_ops),
INTEL_ADLS_IDS(&gen11_early_ops),
};
struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0);
......
......@@ -223,7 +223,9 @@ i915-y += \
display/intel_sprite.o \
display/intel_tc.o \
display/intel_vga.o \
display/i9xx_plane.o
display/i9xx_plane.o \
display/skl_scaler.o \
display/skl_universal_plane.o
i915-$(CONFIG_ACPI) += \
display/intel_acpi.o \
display/intel_opregion.o
......@@ -241,6 +243,7 @@ i915-y += \
display/icl_dsi.o \
display/intel_crt.o \
display/intel_ddi.o \
display/intel_ddi_buf_trans.o \
display/intel_dp.o \
display/intel_dp_aux.o \
display/intel_dp_aux_backlight.o \
......
......@@ -770,10 +770,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
int num_formats;
int ret, zpos;
if (INTEL_GEN(dev_priv) >= 9)
return skl_universal_plane_create(dev_priv, pipe,
PLANE_PRIMARY);
plane = intel_plane_alloc();
if (IS_ERR(plane))
return plane;
......@@ -924,3 +920,122 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
return ERR_PTR(ret);
}
static int i9xx_format_to_fourcc(int format)
{
switch (format) {
case DISPPLANE_8BPP:
return DRM_FORMAT_C8;
case DISPPLANE_BGRA555:
return DRM_FORMAT_ARGB1555;
case DISPPLANE_BGRX555:
return DRM_FORMAT_XRGB1555;
case DISPPLANE_BGRX565:
return DRM_FORMAT_RGB565;
default:
case DISPPLANE_BGRX888:
return DRM_FORMAT_XRGB8888;
case DISPPLANE_RGBX888:
return DRM_FORMAT_XBGR8888;
case DISPPLANE_BGRA888:
return DRM_FORMAT_ARGB8888;
case DISPPLANE_RGBA888:
return DRM_FORMAT_ABGR8888;
case DISPPLANE_BGRX101010:
return DRM_FORMAT_XRGB2101010;
case DISPPLANE_RGBX101010:
return DRM_FORMAT_XBGR2101010;
case DISPPLANE_BGRA101010:
return DRM_FORMAT_ARGB2101010;
case DISPPLANE_RGBA101010:
return DRM_FORMAT_ABGR2101010;
case DISPPLANE_RGBX161616:
return DRM_FORMAT_XBGR16161616F;
}
}
void
i9xx_get_initial_plane_config(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_plane *plane = to_intel_plane(crtc->base.primary);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
enum pipe pipe;
u32 val, base, offset;
int fourcc, pixel_format;
unsigned int aligned_height;
struct drm_framebuffer *fb;
struct intel_framebuffer *intel_fb;
if (!plane->get_hw_state(plane, &pipe))
return;
drm_WARN_ON(dev, pipe != crtc->pipe);
intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
if (!intel_fb) {
drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
return;
}
fb = &intel_fb->base;
fb->dev = dev;
val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
if (INTEL_GEN(dev_priv) >= 4) {
if (val & DISPPLANE_TILED) {
plane_config->tiling = I915_TILING_X;
fb->modifier = I915_FORMAT_MOD_X_TILED;
}
if (val & DISPPLANE_ROTATE_180)
plane_config->rotation = DRM_MODE_ROTATE_180;
}
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B &&
val & DISPPLANE_MIRROR)
plane_config->rotation |= DRM_MODE_REFLECT_X;
pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
fourcc = i9xx_format_to_fourcc(pixel_format);
fb->format = drm_format_info(fourcc);
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
offset = intel_de_read(dev_priv, DSPOFFSET(i9xx_plane));
base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & 0xfffff000;
} else if (INTEL_GEN(dev_priv) >= 4) {
if (plane_config->tiling)
offset = intel_de_read(dev_priv,
DSPTILEOFF(i9xx_plane));
else
offset = intel_de_read(dev_priv,
DSPLINOFF(i9xx_plane));
base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & 0xfffff000;
} else {
base = intel_de_read(dev_priv, DSPADDR(i9xx_plane));
}
plane_config->base = base;
val = intel_de_read(dev_priv, PIPESRC(pipe));
fb->width = ((val >> 16) & 0xfff) + 1;
fb->height = ((val >> 0) & 0xfff) + 1;
val = intel_de_read(dev_priv, DSPSTRIDE(i9xx_plane));
fb->pitches[0] = val & 0xffffffc0;
aligned_height = intel_fb_align_height(fb, 0, fb->height);
plane_config->size = fb->pitches[0] * aligned_height;
drm_dbg_kms(&dev_priv->drm,
"%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
crtc->base.name, plane->base.name, fb->width, fb->height,
fb->format->cpp[0] * 8, base, fb->pitches[0],
plane_config->size);
plane_config->fb = intel_fb;
}
......@@ -10,6 +10,8 @@
enum pipe;
struct drm_i915_private;
struct intel_crtc;
struct intel_initial_plane_config;
struct intel_plane;
struct intel_plane_state;
......@@ -21,4 +23,6 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state);
struct intel_plane *
intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe);
void i9xx_get_initial_plane_config(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config);
#endif
......@@ -35,6 +35,8 @@
#include "intel_dsi.h"
#include "intel_panel.h"
#include "intel_vdsc.h"
#include "skl_scaler.h"
#include "skl_universal_plane.h"
static int header_credits_available(struct drm_i915_private *dev_priv,
enum transcoder dsi_trans)
......@@ -653,6 +655,24 @@ static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
mutex_unlock(&dev_priv->dpll.lock);
}
static bool gen11_dsi_is_clock_enabled(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
bool clock_enabled = false;
enum phy phy;
u32 tmp;
tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys) {
if (!(tmp & ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)))
clock_enabled = true;
}
return clock_enabled;
}
static void gen11_dsi_map_pll(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
......@@ -1488,14 +1508,10 @@ static void gen11_dsi_get_cmd_mode_config(struct intel_dsi *intel_dsi,
static void gen11_dsi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
/* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */
pipe_config->port_clock = intel_dpll_get_freq(i915,
pipe_config->shared_dpll,
&pipe_config->dpll_hw_state);
intel_ddi_get_clock(encoder, pipe_config, icl_ddi_combo_get_pll(encoder));
pipe_config->hw.adjusted_mode.crtc_clock = intel_dsi->pclk;
if (intel_dsi->dual_link)
......@@ -1940,6 +1956,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
encoder->pipe_mask = ~0;
encoder->power_domain = POWER_DOMAIN_PORT_DSI;
encoder->get_power_domains = gen11_dsi_get_power_domains;
encoder->disable_clock = gen11_dsi_gate_clocks;
encoder->is_clock_enabled = gen11_dsi_is_clock_enabled;
/* register DSI connector with DRM subsystem */
drm_connector_init(dev, connector, &gen11_dsi_connector_funcs,
......
......@@ -40,7 +40,7 @@
#include "intel_global_state.h"
#include "intel_hdcp.h"
#include "intel_psr.h"
#include "intel_sprite.h"
#include "skl_universal_plane.h"
/**
* intel_digital_connector_atomic_get_property - hook for connector->atomic_get_property.
......
......@@ -1630,16 +1630,36 @@ static const u8 rkl_pch_tgp_ddc_pin_map[] = {
[RKL_DDC_BUS_DDI_E] = GMBUS_PIN_10_TC2_ICP,
};
static const u8 adls_ddc_pin_map[] = {
[ICL_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT,
[ADLS_DDC_BUS_PORT_TC1] = GMBUS_PIN_9_TC1_ICP,
[ADLS_DDC_BUS_PORT_TC2] = GMBUS_PIN_10_TC2_ICP,
[ADLS_DDC_BUS_PORT_TC3] = GMBUS_PIN_11_TC3_ICP,
[ADLS_DDC_BUS_PORT_TC4] = GMBUS_PIN_12_TC4_ICP,
};
static const u8 gen9bc_tgp_ddc_pin_map[] = {
[DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT,
[DDC_BUS_DDI_C] = GMBUS_PIN_9_TC1_ICP,
[DDC_BUS_DDI_D] = GMBUS_PIN_10_TC2_ICP,
};
static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin)
{
const u8 *ddc_pin_map;
int n_entries;
if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) {
if (HAS_PCH_ADP(dev_priv)) {
ddc_pin_map = adls_ddc_pin_map;
n_entries = ARRAY_SIZE(adls_ddc_pin_map);
} else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) {
return vbt_pin;
} else if (IS_ROCKETLAKE(dev_priv) && INTEL_PCH_TYPE(dev_priv) == PCH_TGP) {
ddc_pin_map = rkl_pch_tgp_ddc_pin_map;
n_entries = ARRAY_SIZE(rkl_pch_tgp_ddc_pin_map);
} else if (HAS_PCH_TGP(dev_priv) && IS_GEN9_BC(dev_priv)) {
ddc_pin_map = gen9bc_tgp_ddc_pin_map;
n_entries = ARRAY_SIZE(gen9bc_tgp_ddc_pin_map);
} else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) {
ddc_pin_map = icp_ddc_pin_map;
n_entries = ARRAY_SIZE(icp_ddc_pin_map);
......@@ -1708,8 +1728,26 @@ static enum port dvo_port_to_port(struct drm_i915_private *dev_priv,
[PORT_TC1] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 },
[PORT_TC2] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
};
/*
* Alderlake S ports used in the driver are PORT_A, PORT_D, PORT_E,
* PORT_F and PORT_G, we need to map that to correct VBT sections.
*/
static const int adls_port_mapping[][3] = {
[PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1 },
[PORT_B] = { -1 },
[PORT_C] = { -1 },
[PORT_TC1] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1 },
[PORT_TC2] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1 },
[PORT_TC3] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1 },
[PORT_TC4] = { DVO_PORT_HDMIE, DVO_PORT_DPE, -1 },
};
if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
if (IS_ALDERLAKE_S(dev_priv))
return __dvo_port_to_port(ARRAY_SIZE(adls_port_mapping),
ARRAY_SIZE(adls_port_mapping[0]),
adls_port_mapping,
dvo_port);
else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
return __dvo_port_to_port(ARRAY_SIZE(rkl_port_mapping),
ARRAY_SIZE(rkl_port_mapping[0]),
rkl_port_mapping,
......@@ -1721,6 +1759,44 @@ static enum port dvo_port_to_port(struct drm_i915_private *dev_priv,
dvo_port);
}
static int parse_bdb_230_dp_max_link_rate(const int vbt_max_link_rate)
{
switch (vbt_max_link_rate) {
default:
case BDB_230_VBT_DP_MAX_LINK_RATE_DEF:
return 0;
case BDB_230_VBT_DP_MAX_LINK_RATE_UHBR20:
return 2000000;
case BDB_230_VBT_DP_MAX_LINK_RATE_UHBR13P5:
return 1350000;
case BDB_230_VBT_DP_MAX_LINK_RATE_UHBR10:
return 1000000;
case BDB_230_VBT_DP_MAX_LINK_RATE_HBR3:
return 810000;
case BDB_230_VBT_DP_MAX_LINK_RATE_HBR2:
return 540000;
case BDB_230_VBT_DP_MAX_LINK_RATE_HBR:
return 270000;
case BDB_230_VBT_DP_MAX_LINK_RATE_LBR:
return 162000;
}
}
static int parse_bdb_216_dp_max_link_rate(const int vbt_max_link_rate)
{
switch (vbt_max_link_rate) {
default:
case BDB_216_VBT_DP_MAX_LINK_RATE_HBR3:
return 810000;
case BDB_216_VBT_DP_MAX_LINK_RATE_HBR2:
return 540000;
case BDB_216_VBT_DP_MAX_LINK_RATE_HBR:
return 270000;
case BDB_216_VBT_DP_MAX_LINK_RATE_LBR:
return 162000;
}
}
static void parse_ddi_port(struct drm_i915_private *dev_priv,
struct display_device_data *devdata,
u8 bdb_version)
......@@ -1800,7 +1876,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv,
/* The VBT HDMI level shift values match the table we have. */
u8 hdmi_level_shift = child->hdmi_level_shifter_value;
drm_dbg_kms(&dev_priv->drm,
"VBT HDMI level shift for port %c: %d\n",
"Port %c VBT HDMI level shift: %d\n",
port_name(port),
hdmi_level_shift);
info->hdmi_level_shift = hdmi_level_shift;
......@@ -1827,7 +1903,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv,
if (max_tmds_clock)
drm_dbg_kms(&dev_priv->drm,
"VBT HDMI max TMDS clock for port %c: %d kHz\n",
"Port %c VBT HDMI max TMDS clock: %d kHz\n",
port_name(port), max_tmds_clock);
info->max_tmds_clock = max_tmds_clock;
}
......@@ -1836,33 +1912,23 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv,
if (bdb_version >= 196 && child->iboost) {
info->dp_boost_level = translate_iboost(child->dp_iboost_level);
drm_dbg_kms(&dev_priv->drm,
"VBT (e)DP boost level for port %c: %d\n",
"Port %c VBT (e)DP boost level: %d\n",
port_name(port), info->dp_boost_level);
info->hdmi_boost_level = translate_iboost(child->hdmi_iboost_level);
drm_dbg_kms(&dev_priv->drm,
"VBT HDMI boost level for port %c: %d\n",
"Port %c VBT HDMI boost level: %d\n",
port_name(port), info->hdmi_boost_level);
}
/* DP max link rate for CNL+ */
if (bdb_version >= 216) {
switch (child->dp_max_link_rate) {
default:
case VBT_DP_MAX_LINK_RATE_HBR3:
info->dp_max_link_rate = 810000;
break;
case VBT_DP_MAX_LINK_RATE_HBR2:
info->dp_max_link_rate = 540000;
break;
case VBT_DP_MAX_LINK_RATE_HBR:
info->dp_max_link_rate = 270000;
break;
case VBT_DP_MAX_LINK_RATE_LBR:
info->dp_max_link_rate = 162000;
break;
}
if (bdb_version >= 230)
info->dp_max_link_rate = parse_bdb_230_dp_max_link_rate(child->dp_max_link_rate);
else
info->dp_max_link_rate = parse_bdb_216_dp_max_link_rate(child->dp_max_link_rate);
drm_dbg_kms(&dev_priv->drm,
"VBT DP max link rate for port %c: %d\n",
"Port %c VBT DP max link rate: %d\n",
port_name(port), info->dp_max_link_rate);
}
......@@ -2098,7 +2164,7 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
static struct vbt_header *oprom_get_vbt(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
void __iomem *p = NULL, *oprom;
struct vbt_header *vbt;
u16 vbt_size;
......@@ -2645,6 +2711,23 @@ intel_bios_is_lspcon_present(const struct drm_i915_private *i915,
return HAS_LSPCON(i915) && child && child->lspcon;
}
/**
* intel_bios_is_lane_reversal_needed - if lane reversal needed on port
* @i915: i915 device instance
* @port: port to check
*
* Return true if port requires lane reversal
*/
bool
intel_bios_is_lane_reversal_needed(const struct drm_i915_private *i915,
enum port port)
{
const struct child_device_config *child =
i915->vbt.ddi_port_info[port].child;
return child && child->lane_reversal;
}
enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv,
enum port port)
{
......@@ -2661,27 +2744,44 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv,
return aux_ch;
}
/*
* RKL/DG1 VBT uses PHY based mapping. Combo PHYs A,B,C,D
* map to DDI A,B,TC1,TC2 respectively.
*
* ADL-S VBT uses PHY based mapping. Combo PHYs A,B,C,D,E
* map to DDI A,TC1,TC2,TC3,TC4 respectively.
*/
switch (info->alternate_aux_channel) {
case DP_AUX_A:
aux_ch = AUX_CH_A;
break;
case DP_AUX_B:
aux_ch = AUX_CH_B;
if (IS_ALDERLAKE_S(dev_priv))
aux_ch = AUX_CH_USBC1;
else
aux_ch = AUX_CH_B;
break;
case DP_AUX_C:
/*
* RKL/DG1 VBT uses PHY based mapping. Combo PHYs A,B,C,D
* map to DDI A,B,TC1,TC2 respectively.
*/
aux_ch = (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) ?
AUX_CH_USBC1 : AUX_CH_C;
if (IS_ALDERLAKE_S(dev_priv))
aux_ch = AUX_CH_USBC2;
else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
aux_ch = AUX_CH_USBC1;
else
aux_ch = AUX_CH_C;
break;
case DP_AUX_D:
aux_ch = (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) ?
AUX_CH_USBC2 : AUX_CH_D;
if (IS_ALDERLAKE_S(dev_priv))
aux_ch = AUX_CH_USBC3;
else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
aux_ch = AUX_CH_USBC2;
else
aux_ch = AUX_CH_D;
break;
case DP_AUX_E:
aux_ch = AUX_CH_E;
if (IS_ALDERLAKE_S(dev_priv))
aux_ch = AUX_CH_USBC4;
else
aux_ch = AUX_CH_E;
break;
case DP_AUX_F:
aux_ch = AUX_CH_F;
......
......@@ -241,6 +241,8 @@ bool intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915,
enum port port);
bool intel_bios_is_lspcon_present(const struct drm_i915_private *i915,
enum port port);
bool intel_bios_is_lane_reversal_needed(const struct drm_i915_private *i915,
enum port port);
enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
......
......@@ -78,7 +78,17 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
qi->num_points = dram_info->num_qgv_points;
if (IS_GEN(dev_priv, 12))
qi->t_bl = dev_priv->dram_info.type == INTEL_DRAM_DDR4 ? 4 : 16;
switch (dram_info->type) {
case INTEL_DRAM_DDR4:
qi->t_bl = 4;
break;
case INTEL_DRAM_DDR5:
qi->t_bl = 8;
break;
default:
qi->t_bl = 16;
break;
}
else if (IS_GEN(dev_priv, 11))
qi->t_bl = dev_priv->dram_info.type == INTEL_DRAM_DDR4 ? 4 : 8;
......@@ -142,6 +152,12 @@ static const struct intel_sa_info rkl_sa_info = {
.displayrtids = 128,
};
static const struct intel_sa_info adls_sa_info = {
.deburst = 16,
.deprogbwlimit = 38, /* GB/s */
.displayrtids = 256,
};
static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa)
{
struct intel_qgv_info qi = {};
......@@ -251,7 +267,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)
if (!HAS_DISPLAY(dev_priv))
return;
if (IS_ROCKETLAKE(dev_priv))
if (IS_ALDERLAKE_S(dev_priv))
icl_get_bw_info(dev_priv, &adls_sa_info);
else if (IS_ROCKETLAKE(dev_priv))
icl_get_bw_info(dev_priv, &rkl_sa_info);
else if (IS_GEN(dev_priv, 12))
icl_get_bw_info(dev_priv, &tgl_sa_info);
......
......@@ -96,7 +96,7 @@ static void fixed_450mhz_get_cdclk(struct drm_i915_private *dev_priv,
static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
u16 hpllcc = 0;
/*
......@@ -138,7 +138,7 @@ static void i85x_get_cdclk(struct drm_i915_private *dev_priv,
static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc);
......@@ -162,7 +162,7 @@ static void i915gm_get_cdclk(struct drm_i915_private *dev_priv,
static void i945gm_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc);
......@@ -256,7 +256,7 @@ static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
static void g33_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
static const u8 div_3200[] = { 12, 10, 8, 7, 5, 16 };
static const u8 div_4000[] = { 14, 12, 10, 8, 6, 20 };
static const u8 div_4800[] = { 20, 14, 12, 10, 8, 24 };
......@@ -305,7 +305,7 @@ static void g33_get_cdclk(struct drm_i915_private *dev_priv,
static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
u16 gcfgc = 0;
pci_read_config_word(pdev, GCFGC, &gcfgc);
......@@ -339,7 +339,7 @@ static void pnv_get_cdclk(struct drm_i915_private *dev_priv,
static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
static const u8 div_3200[] = { 16, 10, 8 };
static const u8 div_4000[] = { 20, 12, 10 };
static const u8 div_5333[] = { 24, 16, 14 };
......@@ -384,7 +384,7 @@ static void i965gm_get_cdclk(struct drm_i915_private *dev_priv,
static void gm45_get_cdclk(struct drm_i915_private *dev_priv,
struct intel_cdclk_config *cdclk_config)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
unsigned int cdclk_sel;
u16 tmp = 0;
......@@ -2145,10 +2145,10 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
if (IS_ERR(bw_state))
return PTR_ERR(bw_state);
if (cdclk_state->min_cdclk[i] == min_cdclk)
if (cdclk_state->min_cdclk[crtc->pipe] == min_cdclk)
continue;
cdclk_state->min_cdclk[i] = min_cdclk;
cdclk_state->min_cdclk[crtc->pipe] = min_cdclk;
ret = intel_atomic_lock_global_state(&cdclk_state->base);
if (ret)
......@@ -2199,10 +2199,10 @@ static int bxt_compute_min_voltage_level(struct intel_cdclk_state *cdclk_state)
else
min_voltage_level = 0;
if (cdclk_state->min_voltage_level[i] == min_voltage_level)
if (cdclk_state->min_voltage_level[crtc->pipe] == min_voltage_level)
continue;
cdclk_state->min_voltage_level[i] = min_voltage_level;
cdclk_state->min_voltage_level[crtc->pipe] = min_voltage_level;
ret = intel_atomic_lock_global_state(&cdclk_state->base);
if (ret)
......
......@@ -187,10 +187,16 @@ static bool has_phy_misc(struct drm_i915_private *i915, enum phy phy)
* Some platforms only expect PHY_MISC to be programmed for PHY-A and
* PHY-B and may not even have instances of the register for the
* other combo PHY's.
*
* ADL-S technically has three instances of PHY_MISC, but only requires
* that we program it for PHY A.
*/
if (IS_JSL_EHL(i915) ||
IS_ROCKETLAKE(i915) ||
IS_DG1(i915))
if (IS_ALDERLAKE_S(i915))
return phy == PHY_A;
else if (IS_JSL_EHL(i915) ||
IS_ROCKETLAKE(i915) ||
IS_DG1(i915))
return phy < PHY_C;
return true;
......@@ -246,14 +252,21 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy)
* RKL,DG1:
* A(master) -> B(slave)
* C(master) -> D(slave)
* ADL-S:
* A(master) -> B(slave), C(slave)
* D(master) -> E(slave)
*
* We must set the IREFGEN bit for any PHY acting as a master
* to another PHY.
*/
if ((IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) && phy == PHY_C)
if (phy == PHY_A)
return true;
else if (IS_ALDERLAKE_S(dev_priv))
return phy == PHY_D;
else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv))
return phy == PHY_C;
return phy == PHY_A;
return false;
}
static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv,
......
......@@ -38,6 +38,7 @@
#include "intel_crt.h"
#include "intel_ddi.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
#include "intel_fifo_underrun.h"
#include "intel_gmbus.h"
#include "intel_hotplug.h"
......@@ -141,7 +142,7 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
intel_ddi_get_config(encoder, pipe_config);
hsw_ddi_get_config(encoder, pipe_config);
pipe_config->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
DRM_MODE_FLAG_NHSYNC |
......@@ -1075,6 +1076,9 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
crt->base.enable = hsw_enable_crt;
crt->base.disable = hsw_disable_crt;
crt->base.post_disable = hsw_post_disable_crt;
crt->base.enable_clock = hsw_ddi_enable_clock;
crt->base.disable_clock = hsw_ddi_disable_clock;
crt->base.is_clock_enabled = hsw_ddi_is_clock_enabled;
} else {
if (HAS_PCH_SPLIT(dev_priv)) {
crt->base.compute_config = pch_crt_compute_config;
......
This diff is collapsed.
......@@ -40,6 +40,10 @@
#define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE
#define ADLS_CSR_PATH "i915/adls_dmc_ver2_01.bin"
#define ADLS_CSR_VERSION_REQUIRED CSR_VERSION(2, 1)
MODULE_FIRMWARE(ADLS_CSR_PATH);
#define DG1_CSR_PATH "i915/dg1_dmc_ver2_02.bin"
#define DG1_CSR_VERSION_REQUIRED CSR_VERSION(2, 2)
MODULE_FIRMWARE(DG1_CSR_PATH);
......@@ -640,7 +644,7 @@ static void csr_load_work_fn(struct work_struct *work)
dev_priv = container_of(work, typeof(*dev_priv), csr.work);
csr = &dev_priv->csr;
request_firmware(&fw, dev_priv->csr.fw_path, &dev_priv->drm.pdev->dev);
request_firmware(&fw, dev_priv->csr.fw_path, dev_priv->drm.dev);
parse_csr_fw(dev_priv, fw);
if (dev_priv->csr.dmc_payload) {
......@@ -689,7 +693,11 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
*/
intel_csr_runtime_pm_get(dev_priv);
if (IS_DG1(dev_priv)) {
if (IS_ALDERLAKE_S(dev_priv)) {
csr->fw_path = ADLS_CSR_PATH;
csr->required_version = ADLS_CSR_VERSION_REQUIRED;
csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
} else if (IS_DG1(dev_priv)) {
csr->fw_path = DG1_CSR_PATH;
csr->required_version = DG1_CSR_VERSION_REQUIRED;
csr->max_fw_size = GEN12_CSR_MAX_FW_SIZE;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -17,6 +17,7 @@ struct intel_crtc_state;
struct intel_dp;
struct intel_dpll_hw_state;
struct intel_encoder;
struct intel_shared_dpll;
enum transcoder;
i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
......@@ -27,8 +28,22 @@ void intel_ddi_fdi_post_disable(struct intel_atomic_state *state,
struct intel_encoder *intel_encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state);
void hsw_fdi_link_train(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_get_clock(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct intel_shared_dpll *pll);
void hsw_ddi_enable_clock(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void hsw_ddi_disable_clock(struct intel_encoder *encoder);
bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder);
void hsw_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder);
void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
enum port port);
void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port);
bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
......@@ -40,8 +55,6 @@ void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state);
void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config);
void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
bool state);
void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
......@@ -53,6 +66,6 @@ u32 ddi_signal_levels(struct intel_dp *intel_dp,
int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
enum transcoder cpu_transcoder,
bool enable, u32 hdcp_mask);
void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder);
void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder);
#endif /* __INTEL_DDI_H__ */
This diff is collapsed.
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2020 Intel Corporation
*/
#ifndef _INTEL_DDI_BUF_TRANS_H_
#define _INTEL_DDI_BUF_TRANS_H_
#include <linux/types.h>
struct drm_i915_private;
struct intel_encoder;
struct intel_crtc_state;
struct ddi_buf_trans {
u32 trans1; /* balance leg enable, de-emph level */
u32 trans2; /* vref sel, vswing */
u8 i_boost; /* SKL: I_boost; valid: 0x0, 0x1, 0x3, 0x7 */
};
struct bxt_ddi_buf_trans {
u8 margin; /* swing value */
u8 scale; /* scale value */
u8 enable; /* scale enable */
u8 deemphasis;
};
struct cnl_ddi_buf_trans {
u8 dw2_swing_sel;
u8 dw7_n_scalar;
u8 dw4_cursor_coeff;
u8 dw4_post_cursor_2;
u8 dw4_post_cursor_1;
};
struct icl_mg_phy_ddi_buf_trans {
u32 cri_txdeemph_override_11_6;
u32 cri_txdeemph_override_5_0;
u32 cri_txdeemph_override_17_12;
};
struct tgl_dkl_phy_ddi_buf_trans {
u32 dkl_vswing_control;
u32 dkl_preshoot_control;
u32 dkl_de_emphasis_control;
};
bool is_hobl_buf_trans(const struct cnl_ddi_buf_trans *table);
int intel_ddi_hdmi_num_entries(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *default_entry);
const struct ddi_buf_trans *
intel_ddi_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries);
const struct ddi_buf_trans *
intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv,
int *n_entries);
const struct ddi_buf_trans *
intel_ddi_get_buf_trans_hdmi(struct intel_encoder *encoder,
int *n_entries);
const struct ddi_buf_trans *
intel_ddi_get_buf_trans_dp(struct intel_encoder *encoder, int *n_entries);
const struct bxt_ddi_buf_trans *
bxt_get_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
const struct cnl_ddi_buf_trans *
tgl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
const struct tgl_dkl_phy_ddi_buf_trans *
tgl_get_dkl_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
const struct cnl_ddi_buf_trans *
jsl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
const struct cnl_ddi_buf_trans *
ehl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
const struct cnl_ddi_buf_trans *
icl_get_combo_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
const struct icl_mg_phy_ddi_buf_trans *
icl_get_mg_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
const struct cnl_ddi_buf_trans *
cnl_get_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries);
#endif
......@@ -52,6 +52,7 @@ struct intel_crtc_state;
struct intel_digital_port;
struct intel_dp;
struct intel_encoder;
struct intel_initial_plane_config;
struct intel_load_detect_pipe;
struct intel_plane;
struct intel_plane_state;
......@@ -352,11 +353,6 @@ enum phy_fia {
for_each_cpu_transcoder(__dev_priv, __t) \
for_each_if ((__mask) & BIT(__t))
#define for_each_universal_plane(__dev_priv, __pipe, __p) \
for ((__p) = 0; \
(__p) < RUNTIME_INFO(__dev_priv)->num_sprites[(__pipe)] + 1; \
(__p)++)
#define for_each_sprite(__dev_priv, __p, __s) \
for ((__s) = 0; \
(__s) < RUNTIME_INFO(__dev_priv)->num_sprites[(__p)]; \
......@@ -417,10 +413,19 @@ enum phy_fia {
for_each_if((encoder_mask) & \
drm_encoder_mask(&intel_encoder->base))
#define for_each_intel_encoder_mask_with_psr(dev, intel_encoder, encoder_mask) \
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
for_each_if(((encoder_mask) & drm_encoder_mask(&(intel_encoder)->base)) && \
intel_encoder_can_psr(intel_encoder))
#define for_each_intel_dp(dev, intel_encoder) \
for_each_intel_encoder(dev, intel_encoder) \
for_each_if(intel_encoder_is_dp(intel_encoder))
#define for_each_intel_encoder_with_psr(dev, intel_encoder) \
for_each_intel_encoder((dev), (intel_encoder)) \
for_each_if(intel_encoder_can_psr(intel_encoder))
#define for_each_intel_connector_iter(intel_connector, iter) \
while ((intel_connector = to_intel_connector(drm_connector_list_iter_next(iter))))
......@@ -507,8 +512,6 @@ void intel_link_compute_m_n(u16 bpp, int nlanes,
int pixel_clock, int link_clock,
struct intel_link_m_n *m_n,
bool constant_n, bool fec_enable);
bool is_ccs_modifier(u64 modifier);
int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane);
void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv);
u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
u32 pixel_format, u64 modifier);
......@@ -586,9 +589,6 @@ void intel_cleanup_plane_fb(struct drm_plane *plane,
void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
enum pipe pipe);
int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
const struct dpll *dpll);
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
int lpt_get_iclkip(struct drm_i915_private *dev_priv);
bool intel_fuzzy_clock_check(int clock1, int clock2);
......@@ -613,25 +613,8 @@ enum intel_display_power_domain
intel_legacy_aux_to_power_domain(enum aux_ch aux_ch);
void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
struct intel_crtc_state *crtc_state);
u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state);
u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set);
void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
int id, int set, enum drm_scaling_filter filter);
void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state);
u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state);
u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state);
u32 skl_plane_stride(const struct intel_plane_state *plane_state,
int plane);
int skl_check_plane_surface(struct intel_plane_state *plane_state);
int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
int *x, int *y, u32 *offset);
int skl_format_to_fourcc(int format, bool rgb_order, bool alpha);
int bdw_get_pipemisc_bpp(struct intel_crtc *crtc);
unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state);
......@@ -653,12 +636,21 @@ void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
struct intel_encoder *
intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state);
unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
int color_plane);
void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
const struct drm_framebuffer *fb,
int color_plane);
u32 intel_plane_adjust_aligned_offset(int *x, int *y,
const struct intel_plane_state *state,
int color_plane,
u32 old_offset, u32 new_offset);
unsigned int intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane);
unsigned int intel_tile_height(const struct drm_framebuffer *fb, int color_plane);
void intel_display_driver_register(struct drm_i915_private *i915);
void intel_display_driver_unregister(struct drm_i915_private *i915);
/* modesetting */
void intel_modeset_init_hw(struct drm_i915_private *i915);
......
......@@ -249,12 +249,11 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
"sink internal error",
};
struct drm_connector *connector = m->private;
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_dp *intel_dp =
intel_attached_dp(to_intel_connector(connector));
int ret;
if (!CAN_PSR(dev_priv)) {
if (!CAN_PSR(intel_dp)) {
seq_puts(m, "PSR Unsupported\n");
return -ENODEV;
}
......@@ -280,12 +279,13 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
DEFINE_SHOW_ATTRIBUTE(i915_psr_sink_status);
static void
psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
{
u32 val, status_val;
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
const char *status = "unknown";
u32 val, status_val;
if (dev_priv->psr.psr2_enabled) {
if (intel_dp->psr.psr2_enabled) {
static const char * const live_status[] = {
"IDLE",
"CAPTURE",
......@@ -300,7 +300,7 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
"TG_ON"
};
val = intel_de_read(dev_priv,
EDP_PSR2_STATUS(dev_priv->psr.transcoder));
EDP_PSR2_STATUS(intel_dp->psr.transcoder));
status_val = (val & EDP_PSR2_STATUS_STATE_MASK) >>
EDP_PSR2_STATUS_STATE_SHIFT;
if (status_val < ARRAY_SIZE(live_status))
......@@ -317,7 +317,7 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
"SRDENT_ON",
};
val = intel_de_read(dev_priv,
EDP_PSR_STATUS(dev_priv->psr.transcoder));
EDP_PSR_STATUS(intel_dp->psr.transcoder));
status_val = (val & EDP_PSR_STATUS_STATE_MASK) >>
EDP_PSR_STATUS_STATE_SHIFT;
if (status_val < ARRAY_SIZE(live_status))
......@@ -327,21 +327,18 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
}
static int i915_edp_psr_status(struct seq_file *m, void *data)
static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct i915_psr *psr = &dev_priv->psr;
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct intel_psr *psr = &intel_dp->psr;
intel_wakeref_t wakeref;
const char *status;
bool enabled;
u32 val;
if (!HAS_PSR(dev_priv))
return -ENODEV;
seq_printf(m, "Sink support: %s", yesno(psr->sink_support));
if (psr->dp)
seq_printf(m, " [0x%02x]", psr->dp->psr_dpcd[0]);
if (psr->sink_support)
seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
seq_puts(m, "\n");
if (!psr->sink_support)
......@@ -365,16 +362,16 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
if (psr->psr2_enabled) {
val = intel_de_read(dev_priv,
EDP_PSR2_CTL(dev_priv->psr.transcoder));
EDP_PSR2_CTL(intel_dp->psr.transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
val = intel_de_read(dev_priv,
EDP_PSR_CTL(dev_priv->psr.transcoder));
EDP_PSR_CTL(intel_dp->psr.transcoder));
enabled = val & EDP_PSR_ENABLE;
}
seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
enableddisabled(enabled), val);
psr_source_status(dev_priv, m);
psr_source_status(intel_dp, m);
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
psr->busy_frontbuffer_bits);
......@@ -383,7 +380,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
*/
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
val = intel_de_read(dev_priv,
EDP_PSR_PERF_CNT(dev_priv->psr.transcoder));
EDP_PSR_PERF_CNT(intel_dp->psr.transcoder));
val &= EDP_PSR_PERF_CNT_MASK;
seq_printf(m, "Performance counter: %u\n", val);
}
......@@ -404,7 +401,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
*/
for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) {
val = intel_de_read(dev_priv,
PSR2_SU_STATUS(dev_priv->psr.transcoder, frame));
PSR2_SU_STATUS(intel_dp->psr.transcoder, frame));
su_frames_val[frame / 3] = val;
}
......@@ -430,23 +427,50 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
return 0;
}
static int i915_edp_psr_status(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_dp *intel_dp = NULL;
struct intel_encoder *encoder;
if (!HAS_PSR(dev_priv))
return -ENODEV;
/* Find the first EDP which supports PSR */
for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
intel_dp = enc_to_intel_dp(encoder);
break;
}
if (!intel_dp)
return -ENODEV;
return intel_psr_status(m, intel_dp);
}
static int
i915_edp_psr_debug_set(void *data, u64 val)
{
struct drm_i915_private *dev_priv = data;
struct intel_encoder *encoder;
intel_wakeref_t wakeref;
int ret;
int ret = -ENODEV;
if (!CAN_PSR(dev_priv))
return -ENODEV;
if (!HAS_PSR(dev_priv))
return ret;
drm_dbg_kms(&dev_priv->drm, "Setting PSR debug to %llx\n", val);
for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
drm_dbg_kms(&dev_priv->drm, "Setting PSR debug to %llx\n", val);
ret = intel_psr_debug_set(dev_priv, val);
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
// TODO: split to each transcoder's PSR debug state
ret = intel_psr_debug_set(intel_dp, val);
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
}
return ret;
}
......@@ -455,12 +479,20 @@ static int
i915_edp_psr_debug_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
struct intel_encoder *encoder;
if (!CAN_PSR(dev_priv))
if (!HAS_PSR(dev_priv))
return -ENODEV;
*val = READ_ONCE(dev_priv->psr.debug);
return 0;
for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
// TODO: split to each transcoder's PSR debug state
*val = READ_ONCE(intel_dp->psr.debug);
return 0;
}
return -ENODEV;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
......@@ -1062,8 +1094,8 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name,
pll->info->id);
seq_printf(m, " crtc_mask: 0x%08x, active: 0x%x, on: %s\n",
pll->state.crtc_mask, pll->active_mask, yesno(pll->on));
seq_printf(m, " pipe_mask: 0x%x, active: 0x%x, on: %s\n",
pll->state.pipe_mask, pll->active_mask, yesno(pll->on));
seq_printf(m, " tracked hardware state:\n");
seq_printf(m, " dpll: 0x%08x\n", pll->state.hw_state.dpll);
seq_printf(m, " dpll_md: 0x%08x\n",
......@@ -1229,9 +1261,6 @@ static void drrs_status_per_crtc(struct seq_file *m,
/* disable_drrs() will make drrs->dp NULL */
if (!drrs->dp) {
seq_puts(m, "Idleness DRRS: Disabled\n");
if (dev_priv->psr.enabled)
seq_puts(m,
"\tAs PSR is enabled, DRRS is not enabled\n");
mutex_unlock(&drrs->mutex);
return;
}
......@@ -2165,19 +2194,40 @@ DEFINE_SHOW_ATTRIBUTE(i915_panel);
static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_connector *intel_connector = to_intel_connector(connector);
int ret;
if (connector->status != connector_status_connected)
return -ENODEV;
ret = drm_modeset_lock_single_interruptible(&i915->drm.mode_config.connection_mutex);
if (ret)
return ret;
if (!connector->encoder || connector->status != connector_status_connected) {
ret = -ENODEV;
goto out;
}
seq_printf(m, "%s:%d HDCP version: ", connector->name,
connector->base.id);
intel_hdcp_info(m, intel_connector);
return 0;
out:
drm_modeset_unlock(&i915->drm.mode_config.connection_mutex);
return ret;
}
DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability);
static int i915_psr_status_show(struct seq_file *m, void *data)
{
struct drm_connector *connector = m->private;
struct intel_dp *intel_dp =
intel_attached_dp(to_intel_connector(connector));
return intel_psr_status(m, intel_dp);
}
DEFINE_SHOW_ATTRIBUTE(i915_psr_status);
#define LPSP_CAPABLE(COND) (COND ? seq_puts(m, "LPSP: capable\n") : \
seq_puts(m, "LPSP: incapable\n"))
......@@ -2353,6 +2403,12 @@ int intel_connector_debugfs_add(struct drm_connector *connector)
connector, &i915_psr_sink_status_fops);
}
if (HAS_PSR(dev_priv) &&
connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
debugfs_create_file("i915_psr_status", 0444, root,
connector, &i915_psr_status_fops);
}
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) {
......
......@@ -41,6 +41,14 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_DDI_G_LANES,
POWER_DOMAIN_PORT_DDI_H_LANES,
POWER_DOMAIN_PORT_DDI_I_LANES,
POWER_DOMAIN_PORT_DDI_LANES_TC1 = POWER_DOMAIN_PORT_DDI_D_LANES, /* tgl+ */
POWER_DOMAIN_PORT_DDI_LANES_TC2,
POWER_DOMAIN_PORT_DDI_LANES_TC3,
POWER_DOMAIN_PORT_DDI_LANES_TC4,
POWER_DOMAIN_PORT_DDI_LANES_TC5,
POWER_DOMAIN_PORT_DDI_LANES_TC6,
POWER_DOMAIN_PORT_DDI_A_IO,
POWER_DOMAIN_PORT_DDI_B_IO,
POWER_DOMAIN_PORT_DDI_C_IO,
......@@ -50,6 +58,14 @@ enum intel_display_power_domain {
POWER_DOMAIN_PORT_DDI_G_IO,
POWER_DOMAIN_PORT_DDI_H_IO,
POWER_DOMAIN_PORT_DDI_I_IO,
POWER_DOMAIN_PORT_DDI_IO_TC1 = POWER_DOMAIN_PORT_DDI_D_IO, /* tgl+ */
POWER_DOMAIN_PORT_DDI_IO_TC2,
POWER_DOMAIN_PORT_DDI_IO_TC3,
POWER_DOMAIN_PORT_DDI_IO_TC4,
POWER_DOMAIN_PORT_DDI_IO_TC5,
POWER_DOMAIN_PORT_DDI_IO_TC6,
POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_PORT_OTHER,
......@@ -64,6 +80,14 @@ enum intel_display_power_domain {
POWER_DOMAIN_AUX_G,
POWER_DOMAIN_AUX_H,
POWER_DOMAIN_AUX_I,
POWER_DOMAIN_AUX_USBC1 = POWER_DOMAIN_AUX_D, /* tgl+ */
POWER_DOMAIN_AUX_USBC2,
POWER_DOMAIN_AUX_USBC3,
POWER_DOMAIN_AUX_USBC4,
POWER_DOMAIN_AUX_USBC5,
POWER_DOMAIN_AUX_USBC6,
POWER_DOMAIN_AUX_IO_A,
POWER_DOMAIN_AUX_C_TBT,
POWER_DOMAIN_AUX_D_TBT,
......@@ -72,6 +96,14 @@ enum intel_display_power_domain {
POWER_DOMAIN_AUX_G_TBT,
POWER_DOMAIN_AUX_H_TBT,
POWER_DOMAIN_AUX_I_TBT,
POWER_DOMAIN_AUX_TBT1 = POWER_DOMAIN_AUX_D_TBT, /* tgl+ */
POWER_DOMAIN_AUX_TBT2,
POWER_DOMAIN_AUX_TBT3,
POWER_DOMAIN_AUX_TBT4,
POWER_DOMAIN_AUX_TBT5,
POWER_DOMAIN_AUX_TBT6,
POWER_DOMAIN_GMBUS,
POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
......
......@@ -37,6 +37,7 @@
#include <drm/drm_dp_mst_helper.h>
#include <drm/drm_encoder.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h>
#include <drm/drm_vblank.h>
......@@ -219,6 +220,16 @@ struct intel_encoder {
* encoders have been disabled and suspended.
*/
void (*shutdown)(struct intel_encoder *encoder);
/*
* Enable/disable the clock to the port.
*/
void (*enable_clock)(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void (*disable_clock)(struct intel_encoder *encoder);
/*
* Returns whether the port clock is enabled or not.
*/
bool (*is_clock_enabled)(struct intel_encoder *encoder);
enum hpd_pin hpd_pin;
enum intel_display_power_domain power_domain;
/* for communication with audio component; protected by av_mutex */
......@@ -714,9 +725,9 @@ struct intel_pipe_wm {
struct skl_wm_level {
u16 min_ddb_alloc;
u16 plane_res_b;
u8 plane_res_l;
bool plane_en;
u16 blocks;
u8 lines;
bool enable;
bool ignore_lines;
bool can_sagv;
};
......@@ -725,7 +736,10 @@ struct skl_plane_wm {
struct skl_wm_level wm[8];
struct skl_wm_level uv_wm[8];
struct skl_wm_level trans_wm;
struct skl_wm_level sagv_wm0;
struct {
struct skl_wm_level wm0;
struct skl_wm_level trans_wm;
} sagv;
bool is_planar;
};
......@@ -1159,6 +1173,13 @@ struct intel_crtc_state {
u8 pipeline_full;
u16 flipline, vmin, vmax;
} vrr;
/* Stream Splitter for eDP MSO */
struct {
bool enable;
u8 link_count;
u8 pixel_overlap;
} splitter;
};
enum intel_pipe_crc_source {
......@@ -1414,6 +1435,44 @@ struct intel_pps {
struct edp_power_seq pps_delays;
};
struct intel_psr {
/* Mutex for PSR state of the transcoder */
struct mutex lock;
#define I915_PSR_DEBUG_MODE_MASK 0x0f
#define I915_PSR_DEBUG_DEFAULT 0x00
#define I915_PSR_DEBUG_DISABLE 0x01
#define I915_PSR_DEBUG_ENABLE 0x02
#define I915_PSR_DEBUG_FORCE_PSR1 0x03
#define I915_PSR_DEBUG_ENABLE_SEL_FETCH 0x4
#define I915_PSR_DEBUG_IRQ 0x10
u32 debug;
bool sink_support;
bool source_support;
bool enabled;
enum pipe pipe;
enum transcoder transcoder;
bool active;
struct work_struct work;
unsigned int busy_frontbuffer_bits;
bool sink_psr2_support;
bool link_standby;
bool colorimetry_support;
bool psr2_enabled;
bool psr2_sel_fetch_enabled;
u8 sink_sync_latency;
ktime_t last_entry_attempt;
ktime_t last_exit;
bool sink_not_reliable;
bool irq_aux_error;
u16 su_x_granularity;
bool dc3co_enabled;
u32 dc3co_exit_delay;
struct delayed_work dc3co_work;
struct drm_dp_vsc_sdp vsc;
};
struct intel_dp {
i915_reg_t output_reg;
u32 DP;
......@@ -1448,6 +1507,8 @@ struct intel_dp {
int max_link_lane_count;
/* Max rate for the current link */
int max_link_rate;
int mso_link_count;
int mso_pixel_overlap;
/* sink or branch descriptor */
struct drm_dp_desc desc;
struct drm_dp_aux aux;
......@@ -1516,6 +1577,8 @@ struct intel_dp {
bool hobl_active;
struct intel_dp_pcon_frl frl;
struct intel_psr psr;
};
enum lspcon_vendor {
......@@ -1752,6 +1815,17 @@ dp_to_i915(struct intel_dp *intel_dp)
return to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
}
#define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \
(intel_dp)->psr.source_support)
static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
{
if (!intel_encoder_is_dp(encoder))
return false;
return CAN_PSR(enc_to_intel_dp(encoder));
}
static inline struct intel_digital_port *
hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
{
......@@ -1893,4 +1967,39 @@ static inline u32 intel_fdi_link_freq(struct drm_i915_private *dev_priv,
return dev_priv->fdi_pll_freq;
}
static inline bool is_ccs_modifier(u64 modifier)
{
return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ||
modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
modifier == I915_FORMAT_MOD_Yf_TILED_CCS;
}
static inline bool is_ccs_plane(const struct drm_framebuffer *fb, int plane)
{
if (!is_ccs_modifier(fb->modifier))
return false;
return plane >= fb->format->num_planes / 2;
}
static inline bool is_gen12_ccs_modifier(u64 modifier)
{
return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ||
modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
}
static inline bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane)
{
return is_gen12_ccs_modifier(fb->modifier) && is_ccs_plane(fb, plane);
}
static inline bool is_gen12_ccs_cc_plane(const struct drm_framebuffer *fb, int plane)
{
return fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC &&
plane == 2;
}
#endif /* __INTEL_DISPLAY_TYPES_H__ */
......@@ -50,6 +50,7 @@
#include "intel_dp_aux.h"
#include "intel_dp_link_training.h"
#include "intel_dp_mst.h"
#include "intel_dpll.h"
#include "intel_dpio_phy.h"
#include "intel_fifo_underrun.h"
#include "intel_hdcp.h"
......@@ -788,10 +789,10 @@ intel_dp_mode_valid(struct drm_connector *connector,
return MODE_H_ILLEGAL;
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
if (mode->hdisplay > fixed_mode->hdisplay)
if (mode->hdisplay != fixed_mode->hdisplay)
return MODE_PANEL;
if (mode->vdisplay > fixed_mode->vdisplay)
if (mode->vdisplay != fixed_mode->vdisplay)
return MODE_PANEL;
target_clock = fixed_mode->clock;
......@@ -1663,12 +1664,10 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp,
const struct drm_connector_state *conn_state,
struct drm_dp_vsc_sdp *vsc)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
vsc->sdp_type = DP_SDP_VSC;
if (dev_priv->psr.psr2_enabled) {
if (dev_priv->psr.colorimetry_support &&
if (intel_dp->psr.psr2_enabled) {
if (intel_dp->psr.colorimetry_support &&
intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
/* [PSR2, +Colorimetry] */
intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
......@@ -1724,6 +1723,7 @@ intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
{
struct intel_connector *intel_connector = intel_dp->attached_connector;
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
int pixel_clock;
if (pipe_config->vrr.enable)
return;
......@@ -1742,10 +1742,18 @@ intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
return;
pipe_config->has_drrs = true;
intel_link_compute_m_n(output_bpp, pipe_config->lane_count,
intel_connector->panel.downclock_mode->clock,
pixel_clock = intel_connector->panel.downclock_mode->clock;
if (pipe_config->splitter.enable)
pixel_clock /= pipe_config->splitter.link_count;
intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
pipe_config->port_clock, &pipe_config->dp_m2_n2,
constant_n, pipe_config->fec_enable);
/* FIXME: abstract this better */
if (pipe_config->splitter.enable)
pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count;
}
int
......@@ -1820,6 +1828,26 @@ intel_dp_compute_config(struct intel_encoder *encoder,
output_bpp = intel_dp_output_bpp(pipe_config->output_format,
pipe_config->pipe_bpp);
if (intel_dp->mso_link_count) {
int n = intel_dp->mso_link_count;
int overlap = intel_dp->mso_pixel_overlap;
pipe_config->splitter.enable = true;
pipe_config->splitter.link_count = n;
pipe_config->splitter.pixel_overlap = overlap;
drm_dbg_kms(&dev_priv->drm, "MSO link count %d, pixel overlap %d\n",
n, overlap);
adjusted_mode->crtc_hdisplay = adjusted_mode->crtc_hdisplay / n + overlap;
adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hblank_start / n + overlap;
adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_end / n + overlap;
adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hsync_start / n + overlap;
adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_end / n + overlap;
adjusted_mode->crtc_htotal = adjusted_mode->crtc_htotal / n + overlap;
adjusted_mode->crtc_clock /= n;
}
intel_link_compute_m_n(output_bpp,
pipe_config->lane_count,
adjusted_mode->crtc_clock,
......@@ -1827,6 +1855,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
&pipe_config->dp_m_n,
constant_n, pipe_config->fec_enable);
/* FIXME: abstract this better */
if (pipe_config->splitter.enable)
pipe_config->dp_m_n.gmch_m *= pipe_config->splitter.link_count;
if (!HAS_DDI(dev_priv))
intel_dp_set_clock(encoder, pipe_config);
......@@ -2359,7 +2391,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
return false;
}
if (CAN_PSR(i915) && intel_dp_is_edp(intel_dp)) {
if (CAN_PSR(intel_dp)) {
drm_dbg_kms(&i915->drm, "Forcing full modeset to compute PSR state\n");
crtc_state->uapi.mode_changed = true;
return false;
......@@ -2650,7 +2682,7 @@ void intel_dp_check_frl_training(struct intel_dp *intel_dp)
if (intel_dp_pcon_start_frl_training(intel_dp) < 0) {
int ret, mode;
drm_dbg(&dev_priv->drm, "Couldnt set FRL mode, continuing with TMDS mode\n");
drm_dbg(&dev_priv->drm, "Couldn't set FRL mode, continuing with TMDS mode\n");
ret = drm_dp_pcon_reset_frl_config(&intel_dp->aux);
mode = drm_dp_pcon_hdmi_link_mode(&intel_dp->aux, NULL);
......@@ -3517,6 +3549,64 @@ static void intel_dp_get_dsc_sink_cap(struct intel_dp *intel_dp)
}
}
static void intel_edp_mso_mode_fixup(struct intel_connector *connector,
struct drm_display_mode *mode)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int n = intel_dp->mso_link_count;
int overlap = intel_dp->mso_pixel_overlap;
if (!mode || !n)
return;
mode->hdisplay = (mode->hdisplay - overlap) * n;
mode->hsync_start = (mode->hsync_start - overlap) * n;
mode->hsync_end = (mode->hsync_end - overlap) * n;
mode->htotal = (mode->htotal - overlap) * n;
mode->clock *= n;
drm_mode_set_name(mode);
drm_dbg_kms(&i915->drm,
"[CONNECTOR:%d:%s] using generated MSO mode: ",
connector->base.base.id, connector->base.name);
drm_mode_debug_printmodeline(mode);
}
static void intel_edp_mso_init(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 mso;
if (intel_dp->edp_dpcd[0] < DP_EDP_14)
return;
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso) != 1) {
drm_err(&i915->drm, "Failed to read MSO cap\n");
return;
}
/* Valid configurations are SST or MSO 2x1, 2x2, 4x1 */
mso &= DP_EDP_MSO_NUMBER_OF_LINKS_MASK;
if (mso % 2 || mso > drm_dp_max_lane_count(intel_dp->dpcd)) {
drm_err(&i915->drm, "Invalid MSO link count cap %u\n", mso);
mso = 0;
}
if (mso) {
drm_dbg_kms(&i915->drm, "Sink MSO %ux%u configuration\n",
mso, drm_dp_max_lane_count(intel_dp->dpcd) / mso);
if (!HAS_MSO(i915)) {
drm_err(&i915->drm, "No source MSO support, disabling\n");
mso = 0;
}
}
intel_dp->mso_link_count = mso;
intel_dp->mso_pixel_overlap = 0; /* FIXME: read from DisplayID v2.0 */
}
static bool
intel_edp_init_dpcd(struct intel_dp *intel_dp)
{
......@@ -3600,6 +3690,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
*/
intel_edp_init_source_oui(intel_dp, true);
intel_edp_mso_init(intel_dp);
return true;
}
......@@ -5548,19 +5640,18 @@ static int intel_dp_get_modes(struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct edid *edid;
int num_modes = 0;
edid = intel_connector->detect_edid;
if (edid) {
int ret = intel_connector_update_modes(connector, edid);
num_modes = intel_connector_update_modes(connector, edid);
if (intel_vrr_is_capable(connector))
drm_connector_set_vrr_capable_property(connector,
true);
if (ret)
return ret;
}
/* if eDP has no EDID, fall back to fixed mode */
/* Also add fixed mode, which may or may not be present in EDID */
if (intel_dp_is_edp(intel_attached_dp(intel_connector)) &&
intel_connector->panel.fixed_mode) {
struct drm_display_mode *mode;
......@@ -5569,10 +5660,13 @@ static int intel_dp_get_modes(struct drm_connector *connector)
intel_connector->panel.fixed_mode);
if (mode) {
drm_mode_probed_add(connector, mode);
return 1;
num_modes++;
}
}
if (num_modes)
return num_modes;
if (!edid) {
struct intel_dp *intel_dp = intel_attached_dp(intel_connector);
struct drm_display_mode *mode;
......@@ -5582,11 +5676,11 @@ static int intel_dp_get_modes(struct drm_connector *connector)
intel_dp->downstream_ports);
if (mode) {
drm_mode_probed_add(connector, mode);
return 1;
num_modes++;
}
}
return 0;
return num_modes;
}
static int
......@@ -6459,6 +6553,10 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (fixed_mode)
downclock_mode = intel_dp_drrs_init(intel_connector, fixed_mode);
/* multiply the mode clock and horizontal timings for MSO */
intel_edp_mso_mode_fixup(intel_connector, fixed_mode);
intel_edp_mso_mode_fixup(intel_connector, downclock_mode);
/* fallback to VBT if available for eDP */
if (!fixed_mode)
fixed_mode = intel_panel_vbt_fixed_mode(intel_connector);
......@@ -6641,6 +6739,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
intel_dp->frl.is_trained = false;
intel_dp->frl.trained_rate_gbps = 0;
intel_psr_init(intel_dp);
return true;
fail:
......
......@@ -698,30 +698,6 @@ intel_dp_mst_hdcp_stream_encryption(struct intel_connector *connector,
return 0;
}
static bool intel_dp_mst_get_qses_status(struct intel_digital_port *dig_port,
struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct drm_dp_query_stream_enc_status_ack_reply reply;
struct intel_dp *intel_dp = &dig_port->dp;
int ret;
ret = drm_dp_send_query_stream_enc_status(&intel_dp->mst_mgr,
connector->port, &reply);
if (ret) {
drm_dbg_kms(&i915->drm,
"[%s:%d] failed QSES ret=%d\n",
connector->base.name, connector->base.base.id, ret);
return false;
}
drm_dbg_kms(&i915->drm, "[%s:%d] QSES stream auth: %d stream enc: %d\n",
connector->base.name, connector->base.base.id,
reply.auth_completed, reply.encryption_enabled);
return reply.auth_completed && reply.encryption_enabled;
}
static int
intel_dp_mst_hdcp2_stream_encryption(struct intel_connector *connector,
bool enable)
......@@ -757,11 +733,6 @@ intel_dp_mst_hdcp2_stream_encryption(struct intel_connector *connector,
return 0;
}
/*
* DP v2.0 I.3.3 ignore the stream signature L' in QSES reply msg reply.
* I.3.5 MST source device may use a QSES msg to query downstream status
* for a particular stream.
*/
static
int intel_dp_mst_hdcp2_check_link(struct intel_digital_port *dig_port,
struct intel_connector *connector)
......@@ -781,7 +752,7 @@ int intel_dp_mst_hdcp2_check_link(struct intel_digital_port *dig_port,
return ret;
}
return intel_dp_mst_get_qses_status(dig_port, connector) ? 0 : -EINVAL;
return 0;
}
static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim = {
......
......@@ -26,12 +26,13 @@
#include "intel_dp_link_training.h"
static void
intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
intel_dp_dump_link_status(struct drm_device *drm,
const u8 link_status[DP_LINK_STATUS_SIZE])
{
DRM_DEBUG_KMS("ln0_1:0x%x ln2_3:0x%x align:0x%x sink:0x%x adj_req0_1:0x%x adj_req2_3:0x%x",
link_status[0], link_status[1], link_status[2],
link_status[3], link_status[4], link_status[5]);
drm_dbg_kms(drm,
"ln0_1:0x%x ln2_3:0x%x align:0x%x sink:0x%x adj_req0_1:0x%x adj_req2_3:0x%x\n",
link_status[0], link_status[1], link_status[2],
link_status[3], link_status[4], link_status[5]);
}
static void intel_dp_reset_lttpr_count(struct intel_dp *intel_dp)
......@@ -642,7 +643,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
/* Make sure clock is still ok */
if (!drm_dp_clock_recovery_ok(link_status,
crtc_state->lane_count)) {
intel_dp_dump_link_status(link_status);
intel_dp_dump_link_status(&i915->drm, link_status);
drm_dbg_kms(&i915->drm,
"Clock recovery check failed, cannot "
"continue channel equalization\n");
......@@ -669,7 +670,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
/* Try 5 times, else fail and try at lower BW */
if (tries == 5) {
intel_dp_dump_link_status(link_status);
intel_dp_dump_link_status(&i915->drm, link_status);
drm_dbg_kms(&i915->drm,
"Channel equalization failed 5 times\n");
}
......@@ -731,7 +732,7 @@ intel_dp_link_train_phy(struct intel_dp *intel_dp,
out:
drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
"[CONNECTOR:%d:%s] Link Training %s at link rate = %d, lane count = %d, at %s",
"[CONNECTOR:%d:%s] Link Training %s at link rate = %d, lane count = %d, at %s\n",
intel_connector->base.base.id,
intel_connector->base.name,
ret ? "passed" : "failed",
......
......@@ -39,6 +39,7 @@
#include "intel_dp_mst.h"
#include "intel_dpio_phy.h"
#include "intel_hdcp.h"
#include "skl_scaler.h"
static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
......@@ -590,7 +591,7 @@ static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder,
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
struct intel_digital_port *dig_port = intel_mst->primary;
intel_ddi_get_config(&dig_port->base, pipe_config);
dig_port->base.get_config(&dig_port->base, pipe_config);
}
static bool intel_dp_mst_initial_fastset_check(struct intel_encoder *encoder,
......
This diff is collapsed.
......@@ -10,6 +10,7 @@ struct dpll;
struct drm_i915_private;
struct intel_crtc;
struct intel_crtc_state;
enum pipe;
void intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv);
int vlv_calc_dpll_params(int refclk, struct dpll *clock);
......@@ -20,4 +21,21 @@ void vlv_compute_dpll(struct intel_crtc *crtc,
void chv_compute_dpll(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config);
int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
const struct dpll *dpll);
void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
void i9xx_enable_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *crtc_state);
void vlv_enable_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
void chv_enable_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe);
void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe);
void i9xx_disable_pll(const struct intel_crtc_state *crtc_state);
void vlv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
void chv_prepare_pll(struct intel_crtc *crtc,
const struct intel_crtc_state *pipe_config);
#endif
......@@ -176,7 +176,7 @@ void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state)
return;
mutex_lock(&dev_priv->dpll.lock);
drm_WARN_ON(&dev_priv->drm, !pll->state.crtc_mask);
drm_WARN_ON(&dev_priv->drm, !pll->state.pipe_mask);
if (!pll->active_mask) {
drm_dbg(&dev_priv->drm, "setting up %s\n", pll->info->name);
drm_WARN_ON(&dev_priv->drm, pll->on);
......@@ -198,7 +198,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state)
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
unsigned int crtc_mask = drm_crtc_mask(&crtc->base);
unsigned int pipe_mask = BIT(crtc->pipe);
unsigned int old_mask;
if (drm_WARN_ON(&dev_priv->drm, pll == NULL))
......@@ -207,16 +207,16 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state)
mutex_lock(&dev_priv->dpll.lock);
old_mask = pll->active_mask;
if (drm_WARN_ON(&dev_priv->drm, !(pll->state.crtc_mask & crtc_mask)) ||
drm_WARN_ON(&dev_priv->drm, pll->active_mask & crtc_mask))
if (drm_WARN_ON(&dev_priv->drm, !(pll->state.pipe_mask & pipe_mask)) ||
drm_WARN_ON(&dev_priv->drm, pll->active_mask & pipe_mask))
goto out;
pll->active_mask |= crtc_mask;
pll->active_mask |= pipe_mask;
drm_dbg_kms(&dev_priv->drm,
"enable %s (active %x, on? %d) for crtc %d\n",
"enable %s (active 0x%x, on? %d) for [CRTC:%d:%s]\n",
pll->info->name, pll->active_mask, pll->on,
crtc->base.base.id);
crtc->base.base.id, crtc->base.name);
if (old_mask) {
drm_WARN_ON(&dev_priv->drm, !pll->on);
......@@ -244,7 +244,7 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state)
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_shared_dpll *pll = crtc_state->shared_dpll;
unsigned int crtc_mask = drm_crtc_mask(&crtc->base);
unsigned int pipe_mask = BIT(crtc->pipe);
/* PCH only available on ILK+ */
if (INTEL_GEN(dev_priv) < 5)
......@@ -254,18 +254,20 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state)
return;
mutex_lock(&dev_priv->dpll.lock);
if (drm_WARN_ON(&dev_priv->drm, !(pll->active_mask & crtc_mask)))
if (drm_WARN(&dev_priv->drm, !(pll->active_mask & pipe_mask),
"%s not used by [CRTC:%d:%s]\n", pll->info->name,
crtc->base.base.id, crtc->base.name))
goto out;
drm_dbg_kms(&dev_priv->drm,
"disable %s (active %x, on? %d) for crtc %d\n",
"disable %s (active 0x%x, on? %d) for [CRTC:%d:%s]\n",
pll->info->name, pll->active_mask, pll->on,
crtc->base.base.id);
crtc->base.base.id, crtc->base.name);
assert_shared_dpll_enabled(dev_priv, pll);
drm_WARN_ON(&dev_priv->drm, !pll->on);
pll->active_mask &= ~crtc_mask;
pll->active_mask &= ~pipe_mask;
if (pll->active_mask)
goto out;
......@@ -296,7 +298,7 @@ intel_find_shared_dpll(struct intel_atomic_state *state,
pll = &dev_priv->dpll.shared_dplls[i];
/* Only want to check enabled timings first */
if (shared_dpll[i].crtc_mask == 0) {
if (shared_dpll[i].pipe_mask == 0) {
if (!unused_pll)
unused_pll = pll;
continue;
......@@ -306,10 +308,10 @@ intel_find_shared_dpll(struct intel_atomic_state *state,
&shared_dpll[i].hw_state,
sizeof(*pll_state)) == 0) {
drm_dbg_kms(&dev_priv->drm,
"[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
"[CRTC:%d:%s] sharing existing %s (pipe mask 0x%x, active 0x%x)\n",
crtc->base.base.id, crtc->base.name,
pll->info->name,
shared_dpll[i].crtc_mask,
shared_dpll[i].pipe_mask,
pll->active_mask);
return pll;
}
......@@ -338,13 +340,13 @@ intel_reference_shared_dpll(struct intel_atomic_state *state,
shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
if (shared_dpll[id].crtc_mask == 0)
if (shared_dpll[id].pipe_mask == 0)
shared_dpll[id].hw_state = *pll_state;
drm_dbg(&i915->drm, "using %s for pipe %c\n", pll->info->name,
pipe_name(crtc->pipe));
shared_dpll[id].crtc_mask |= 1 << crtc->pipe;
shared_dpll[id].pipe_mask |= BIT(crtc->pipe);
}
static void intel_unreference_shared_dpll(struct intel_atomic_state *state,
......@@ -354,7 +356,7 @@ static void intel_unreference_shared_dpll(struct intel_atomic_state *state,
struct intel_shared_dpll_state *shared_dpll;
shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
shared_dpll[pll->info->id].crtc_mask &= ~(1 << crtc->pipe);
shared_dpll[pll->info->id].pipe_mask &= ~BIT(crtc->pipe);
}
static void intel_put_dpll(struct intel_atomic_state *state,
......@@ -3559,7 +3561,13 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state,
icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state);
if (IS_DG1(dev_priv)) {
if (IS_ALDERLAKE_S(dev_priv)) {
dpll_mask =
BIT(DPLL_ID_DG1_DPLL3) |
BIT(DPLL_ID_DG1_DPLL2) |
BIT(DPLL_ID_ICL_DPLL1) |
BIT(DPLL_ID_ICL_DPLL0);
} else if (IS_DG1(dev_priv)) {
if (port == PORT_D || port == PORT_E) {
dpll_mask =
BIT(DPLL_ID_DG1_DPLL2) |
......@@ -3865,7 +3873,10 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
if (!(val & PLL_ENABLE))
goto out;
if (IS_DG1(dev_priv)) {
if (IS_ALDERLAKE_S(dev_priv)) {
hw_state->cfgcr0 = intel_de_read(dev_priv, ADLS_DPLL_CFGCR0(id));
hw_state->cfgcr1 = intel_de_read(dev_priv, ADLS_DPLL_CFGCR1(id));
} else if (IS_DG1(dev_priv)) {
hw_state->cfgcr0 = intel_de_read(dev_priv, DG1_DPLL_CFGCR0(id));
hw_state->cfgcr1 = intel_de_read(dev_priv, DG1_DPLL_CFGCR1(id));
} else if (IS_ROCKETLAKE(dev_priv)) {
......@@ -3921,7 +3932,10 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv,
const enum intel_dpll_id id = pll->info->id;
i915_reg_t cfgcr0_reg, cfgcr1_reg;
if (IS_DG1(dev_priv)) {
if (IS_ALDERLAKE_S(dev_priv)) {
cfgcr0_reg = ADLS_DPLL_CFGCR0(id);
cfgcr1_reg = ADLS_DPLL_CFGCR1(id);
} else if (IS_DG1(dev_priv)) {
cfgcr0_reg = DG1_DPLL_CFGCR0(id);
cfgcr1_reg = DG1_DPLL_CFGCR1(id);
} else if (IS_ROCKETLAKE(dev_priv)) {
......@@ -4384,6 +4398,22 @@ static const struct intel_dpll_mgr dg1_pll_mgr = {
.dump_hw_state = icl_dump_hw_state,
};
static const struct dpll_info adls_plls[] = {
{ "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 },
{ "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 },
{ "DPLL 2", &combo_pll_funcs, DPLL_ID_DG1_DPLL2, 0 },
{ "DPLL 3", &combo_pll_funcs, DPLL_ID_DG1_DPLL3, 0 },
{ },
};
static const struct intel_dpll_mgr adls_pll_mgr = {
.dpll_info = adls_plls,
.get_dplls = icl_get_dplls,
.put_dplls = icl_put_dplls,
.update_ref_clks = icl_update_dpll_ref_clks,
.dump_hw_state = icl_dump_hw_state,
};
/**
* intel_shared_dpll_init - Initialize shared DPLLs
* @dev: drm device
......@@ -4397,7 +4427,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
const struct dpll_info *dpll_info;
int i;
if (IS_DG1(dev_priv))
if (IS_ALDERLAKE_S(dev_priv))
dpll_mgr = &adls_pll_mgr;
else if (IS_DG1(dev_priv))
dpll_mgr = &dg1_pll_mgr;
else if (IS_ROCKETLAKE(dev_priv))
dpll_mgr = &rkl_pll_mgr;
......@@ -4567,27 +4599,30 @@ static void readout_dpll_hw_state(struct drm_i915_private *i915,
POWER_DOMAIN_DPLL_DC_OFF);
}
pll->state.crtc_mask = 0;
pll->state.pipe_mask = 0;
for_each_intel_crtc(&i915->drm, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
if (crtc_state->hw.active && crtc_state->shared_dpll == pll)
pll->state.crtc_mask |= 1 << crtc->pipe;
pll->state.pipe_mask |= BIT(crtc->pipe);
}
pll->active_mask = pll->state.crtc_mask;
pll->active_mask = pll->state.pipe_mask;
drm_dbg_kms(&i915->drm,
"%s hw state readout: crtc_mask 0x%08x, on %i\n",
pll->info->name, pll->state.crtc_mask, pll->on);
"%s hw state readout: pipe_mask 0x%x, on %i\n",
pll->info->name, pll->state.pipe_mask, pll->on);
}
void intel_dpll_readout_hw_state(struct drm_i915_private *i915)
void intel_dpll_update_ref_clks(struct drm_i915_private *i915)
{
int i;
if (i915->dpll.mgr && i915->dpll.mgr->update_ref_clks)
i915->dpll.mgr->update_ref_clks(i915);
}
void intel_dpll_readout_hw_state(struct drm_i915_private *i915)
{
int i;
for (i = 0; i < i915->dpll.num_shared_dpll; i++)
readout_dpll_hw_state(i915, &i915->dpll.shared_dplls[i]);
......
......@@ -241,9 +241,9 @@ struct intel_dpll_hw_state {
*/
struct intel_shared_dpll_state {
/**
* @crtc_mask: mask of CRTC using this DPLL, active or not
* @pipe_mask: mask of pipes using this DPLL, active or not
*/
unsigned crtc_mask;
u8 pipe_mask;
/**
* @hw_state: hardware configuration for the DPLL stored in
......@@ -351,9 +351,9 @@ struct intel_shared_dpll {
struct intel_shared_dpll_state state;
/**
* @active_mask: mask of active CRTCs (i.e. DPMS on) using this DPLL
* @active_mask: mask of active pipes (i.e. DPMS on) using this DPLL
*/
unsigned active_mask;
u8 active_mask;
/**
* @on: is the PLL actually active? Disabled during modeset
......@@ -410,6 +410,7 @@ void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_shared_dpll_swap_state(struct intel_atomic_state *state);
void intel_shared_dpll_init(struct drm_device *dev);
void intel_dpll_update_ref_clks(struct drm_i915_private *dev_priv);
void intel_dpll_readout_hw_state(struct drm_i915_private *dev_priv);
void intel_dpll_sanitize_state(struct drm_i915_private *dev_priv);
......
......@@ -425,7 +425,7 @@ static void i2c_acpi_find_adapter(struct intel_dsi *intel_dsi,
const u16 slave_addr)
{
struct drm_device *drm_dev = intel_dsi->base.base.dev;
struct device *dev = &drm_dev->pdev->dev;
struct device *dev = drm_dev->dev;
struct acpi_device *acpi_dev;
struct list_head resource_list;
struct i2c_adapter_lookup lookup;
......
......@@ -167,7 +167,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
struct intel_framebuffer *intel_fb = ifbdev->fb;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
const struct i915_ggtt_view view = {
.type = I915_GGTT_VIEW_NORMAL,
......
......@@ -3,6 +3,8 @@
* Copyright © 2020 Intel Corporation
*/
#include "intel_atomic.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_display_types.h"
#include "intel_fdi.h"
......@@ -550,6 +552,142 @@ static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,
drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");
}
/* Starting with Haswell, different DDI ports can work in FDI mode for
* connection to the PCH-located connectors. For this, it is necessary to train
* both the DDI port and PCH receiver for the desired DDI buffer settings.
*
* The recommended port to work in FDI mode is DDI E, which we use here. Also,
* please note that when FDI mode is active on DDI E, it shares 2 lines with
* DDI A (which is used for eDP)
*/
void hsw_fdi_link_train(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 temp, i, rx_ctl_val;
int n_entries;
intel_ddi_get_buf_trans_fdi(dev_priv, &n_entries);
intel_prepare_dp_ddi_buffers(encoder, crtc_state);
/* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
* mode set "sequence for CRT port" document:
* - TP1 to TP2 time with the default value
* - FDI delay to 90h
*
* WaFDIAutoLinkSetTimingOverrride:hsw
*/
intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A),
FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2) | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
/* Enable the PCH Receiver FDI PLL */
rx_ctl_val = dev_priv->fdi_rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |
FDI_RX_PLL_ENABLE |
FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);
intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
udelay(220);
/* Switch from Rawclk to PCDclk */
rx_ctl_val |= FDI_PCDCLK;
intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
/* Configure Port Clock Select */
drm_WARN_ON(&dev_priv->drm, crtc_state->shared_dpll->info->id != DPLL_ID_SPLL);
intel_ddi_enable_clock(encoder, crtc_state);
/* Start the training iterating through available voltages and emphasis,
* testing each value twice. */
for (i = 0; i < n_entries * 2; i++) {
/* Configure DP_TP_CTL with auto-training */
intel_de_write(dev_priv, DP_TP_CTL(PORT_E),
DP_TP_CTL_FDI_AUTOTRAIN |
DP_TP_CTL_ENHANCED_FRAME_ENABLE |
DP_TP_CTL_LINK_TRAIN_PAT1 |
DP_TP_CTL_ENABLE);
/* Configure and enable DDI_BUF_CTL for DDI E with next voltage.
* DDI E does not support port reversal, the functionality is
* achieved on the PCH side in FDI_RX_CTL, so no need to set the
* port reversal bit */
intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E),
DDI_BUF_CTL_ENABLE | ((crtc_state->fdi_lanes - 1) << 1) | DDI_BUF_TRANS_SELECT(i / 2));
intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
udelay(600);
/* Program PCH FDI Receiver TU */
intel_de_write(dev_priv, FDI_RX_TUSIZE1(PIPE_A), TU_SIZE(64));
/* Enable PCH FDI Receiver with auto-training */
rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO;
intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
/* Wait for FDI receiver lane calibration */
udelay(30);
/* Unset FDI_RX_MISC pwrdn lanes */
temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), temp);
intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));
/* Wait for FDI auto training time */
udelay(5);
temp = intel_de_read(dev_priv, DP_TP_STATUS(PORT_E));
if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {
drm_dbg_kms(&dev_priv->drm,
"FDI link training done on step %d\n", i);
break;
}
/*
* Leave things enabled even if we failed to train FDI.
* Results in less fireworks from the state checker.
*/
if (i == n_entries * 2 - 1) {
drm_err(&dev_priv->drm, "FDI link training failed!\n");
break;
}
rx_ctl_val &= ~FDI_RX_ENABLE;
intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);
intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));
temp = intel_de_read(dev_priv, DDI_BUF_CTL(PORT_E));
temp &= ~DDI_BUF_CTL_ENABLE;
intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E), temp);
intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));
/* Disable DP_TP_CTL and FDI_RX_CTL and retry */
temp = intel_de_read(dev_priv, DP_TP_CTL(PORT_E));
temp &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
intel_wait_ddi_buf_idle(dev_priv, PORT_E);
/* Reset FDI_RX_MISC pwrdn lanes */
temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
temp |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A), temp);
intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));
}
/* Enable normal pixel sending for FDI */
intel_de_write(dev_priv, DP_TP_CTL(PORT_E),
DP_TP_CTL_FDI_AUTOTRAIN |
DP_TP_CTL_LINK_TRAIN_NORMAL |
DP_TP_CTL_ENHANCED_FRAME_ENABLE |
DP_TP_CTL_ENABLE);
}
void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
......
......@@ -9,6 +9,7 @@
struct drm_i915_private;
struct intel_crtc;
struct intel_crtc_state;
struct intel_encoder;
#define I915_DISPLAY_CONFIG_RETRY 1
int ilk_fdi_compute_config(struct intel_crtc *intel_crtc,
......@@ -18,5 +19,7 @@ void ilk_fdi_disable(struct intel_crtc *crtc);
void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc);
void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state);
void intel_fdi_init_hook(struct drm_i915_private *dev_priv);
void hsw_fdi_link_train(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
#endif
......@@ -224,6 +224,8 @@ static void frontbuffer_release(struct kref *ref)
struct drm_i915_gem_object *obj = front->obj;
struct i915_vma *vma;
drm_WARN_ON(obj->base.dev, atomic_read(&front->bits));
spin_lock(&obj->vma.lock);
for_each_ggtt_vma(vma, obj) {
i915_vma_clear_scanout(vma);
......
......@@ -840,7 +840,7 @@ static const struct i2c_lock_operations gmbus_lock_ops = {
*/
int intel_gmbus_setup(struct drm_i915_private *dev_priv)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
struct intel_gmbus *bus;
unsigned int pin;
int ret;
......
This diff is collapsed.
......@@ -80,6 +80,7 @@ static struct platform_device *
lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = &dev_priv->drm;
struct pci_dev *pdev = to_pci_dev(dev->dev);
struct platform_device_info pinfo = {};
struct resource *rsc;
struct platform_device *platdev;
......@@ -99,9 +100,9 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
rsc[0].flags = IORESOURCE_IRQ;
rsc[0].name = "hdmi-lpe-audio-irq";
rsc[1].start = pci_resource_start(dev->pdev, 0) +
rsc[1].start = pci_resource_start(pdev, 0) +
I915_HDMI_LPE_AUDIO_BASE;
rsc[1].end = pci_resource_start(dev->pdev, 0) +
rsc[1].end = pci_resource_start(pdev, 0) +
I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1;
rsc[1].flags = IORESOURCE_MEM;
rsc[1].name = "hdmi-lpe-audio-mmio";
......
......@@ -247,7 +247,7 @@ static int swsci(struct drm_i915_private *dev_priv,
u32 function, u32 parm, u32 *parm_out)
{
struct opregion_swsci *swsci = dev_priv->opregion.swsci;
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
u32 main_function, sub_function, scic;
u16 swsci_val;
u32 dslp;
......@@ -807,7 +807,7 @@ static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv)
if (!name || !*name)
return -ENOENT;
ret = request_firmware(&fw, name, &dev_priv->drm.pdev->dev);
ret = request_firmware(&fw, name, dev_priv->drm.dev);
if (ret) {
drm_err(&dev_priv->drm,
"Requesting VBT firmware \"%s\" failed (%d)\n",
......@@ -840,7 +840,7 @@ static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv)
int intel_opregion_setup(struct drm_i915_private *dev_priv)
{
struct intel_opregion *opregion = &dev_priv->opregion;
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
u32 asls, mboxes;
char buf[sizeof(OPREGION_SIGNATURE)];
int err = 0;
......
......@@ -203,7 +203,7 @@ struct intel_overlay {
static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv,
bool enable)
{
struct pci_dev *pdev = dev_priv->drm.pdev;
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
u8 val;
/* WA_OVERLAY_CLKGATE:alm */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment