# Conflicts:
#	drivers/gpu/drm/i915/display/intel_dp_mst.c
#	drivers/gpu/drm/i915/display/intel_dsb.c
This commit is contained in:
Stephen Rothwell 2024-12-20 12:14:03 +11:00
commit e069bb813f
161 changed files with 5498 additions and 4443 deletions

View File

@ -390,3 +390,26 @@ void drm_print_regset32(struct drm_printer *p, struct debugfs_regset32 *regset)
}
}
EXPORT_SYMBOL(drm_print_regset32);
/**
* drm_print_hex_dump - print a hex dump to a &drm_printer stream
* @p: The &drm_printer
* @prefix: Prefix for each line, may be NULL for no prefix
* @buf: Buffer to dump
* @len: Length of buffer
*
* Print hex dump to &drm_printer, with 16 space-separated hex bytes per line,
* optionally with a prefix on each line. No separator is added after prefix.
*/
void drm_print_hex_dump(struct drm_printer *p, const char *prefix,
const u8 *buf, size_t len)
{
int i;
for (i = 0; i < len; i += 16) {
int bytes_per_line = min(16, len - i);
drm_printf(p, "%s%*ph\n", prefix ?: "", bytes_per_line, buf + i);
}
}
EXPORT_SYMBOL(drm_print_hex_dump);

View File

@ -30,11 +30,11 @@ i915-y += \
i915_params.o \
i915_pci.o \
i915_scatterlist.o \
i915_suspend.o \
i915_switcheroo.o \
i915_sysfs.o \
i915_utils.o \
intel_clock_gating.o \
intel_cpu_info.o \
intel_device_info.o \
intel_memory_region.o \
intel_pcode.o \
@ -43,6 +43,7 @@ i915-y += \
intel_sbi.o \
intel_step.o \
intel_uncore.o \
intel_uncore_trace.o \
intel_wakeref.o \
vlv_sideband.o \
vlv_suspend.o
@ -220,6 +221,7 @@ i915-$(CONFIG_HWMON) += \
i915-y += \
display/hsw_ips.o \
display/i9xx_plane.o \
display/i9xx_display_sr.o \
display/i9xx_wm.o \
display/intel_alpm.o \
display/intel_atomic.o \
@ -236,6 +238,7 @@ i915-y += \
display/intel_crtc_state_dump.o \
display/intel_cursor.o \
display/intel_display.o \
display/intel_display_conversion.o \
display/intel_display_driver.o \
display/intel_display_irq.o \
display/intel_display_params.o \

View File

@ -26,7 +26,6 @@
*
*/
#include "i915_drv.h"
#include "intel_display_types.h"
#include "intel_dvo_dev.h"

View File

@ -8,6 +8,7 @@
#include <linux/string_helpers.h>
#include "g4x_dp.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_audio.h"
#include "intel_backlight.h"
@ -55,8 +56,8 @@ const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
return IS_CHERRYVIEW(i915) ? &chv_dpll[0] : &vlv_dpll[0];
}
void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
static void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
const struct dpll *divisor = NULL;
@ -1223,6 +1224,25 @@ static bool ilk_digital_port_connected(struct intel_encoder *encoder)
return intel_de_read(display, DEISR) & bit;
}
static int g4x_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
int ret;
if (HAS_PCH_SPLIT(i915) && encoder->port != PORT_A)
crtc_state->has_pch_encoder = true;
ret = intel_dp_compute_config(encoder, crtc_state, conn_state);
if (ret)
return ret;
g4x_dp_set_clock(encoder, crtc_state);
return 0;
}
static void g4x_dp_suspend_complete(struct intel_encoder *encoder)
{
/*
@ -1307,7 +1327,7 @@ bool g4x_dp_init(struct drm_i915_private *dev_priv,
intel_encoder_link_check_init(intel_encoder, intel_dp_link_check);
intel_encoder->hotplug = intel_dp_hotplug;
intel_encoder->compute_config = intel_dp_compute_config;
intel_encoder->compute_config = g4x_dp_compute_config;
intel_encoder->get_hw_state = intel_dp_get_hw_state;
intel_encoder->get_config = intel_dp_get_config;
intel_encoder->sync_state = intel_dp_sync_state;

View File

@ -19,8 +19,6 @@ struct intel_encoder;
#ifdef I915
const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config);
bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
i915_reg_t dp_reg, enum port port,
enum pipe *pipe);
@ -31,10 +29,6 @@ static inline const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
{
return NULL;
}
static inline void g4x_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
}
static inline bool g4x_dp_port_enabled(struct drm_i915_private *dev_priv,
i915_reg_t dp_reg, int port,
enum pipe *pipe)

View File

@ -6,6 +6,7 @@
*/
#include "g4x_hdmi.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"

View File

@ -185,10 +185,12 @@ void hsw_ips_post_update(struct intel_atomic_state *state,
/* IPS only exists on ULT machines and is tied to pipe A. */
bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
{
return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A;
struct intel_display *display = to_intel_display(crtc);
return HAS_IPS(display) && crtc->pipe == PIPE_A;
}
bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
static bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@ -218,6 +220,20 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
return true;
}
int hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
if (!IS_BROADWELL(i915))
return 0;
if (!hsw_crtc_state_ips_capable(crtc_state))
return 0;
/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
return DIV_ROUND_UP(crtc_state->pixel_rate * 100, 95);
}
int hsw_ips_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{

View File

@ -19,7 +19,7 @@ bool hsw_ips_pre_update(struct intel_atomic_state *state,
void hsw_ips_post_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
bool hsw_crtc_supports_ips(struct intel_crtc *crtc);
bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state);
int hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state);
int hsw_ips_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void hsw_ips_get_config(struct intel_crtc_state *crtc_state);
@ -42,9 +42,9 @@ static inline bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
{
return false;
}
static inline bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
static inline int hsw_ips_min_cdclk(const struct intel_crtc_state *crtc_state)
{
return false;
return 0;
}
static inline int hsw_ips_compute_config(struct intel_atomic_state *state,
struct intel_crtc *crtc)

View File

@ -0,0 +1,97 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2024 Intel Corporation
*/
#include <drm/drm_device.h>
#include "i915_reg.h"
#include "i9xx_display_sr.h"
#include "i9xx_wm_regs.h"
#include "intel_de.h"
#include "intel_gmbus.h"
#include "intel_pci_config.h"
static void i9xx_display_save_swf(struct intel_display *display)
{
int i;
/* Scratch space */
if (DISPLAY_VER(display) == 2 && display->platform.mobile) {
for (i = 0; i < 7; i++) {
display->restore.saveSWF0[i] = intel_de_read(display, SWF0(display, i));
display->restore.saveSWF1[i] = intel_de_read(display, SWF1(display, i));
}
for (i = 0; i < 3; i++)
display->restore.saveSWF3[i] = intel_de_read(display, SWF3(display, i));
} else if (DISPLAY_VER(display) == 2) {
for (i = 0; i < 7; i++)
display->restore.saveSWF1[i] = intel_de_read(display, SWF1(display, i));
} else if (HAS_GMCH(display)) {
for (i = 0; i < 16; i++) {
display->restore.saveSWF0[i] = intel_de_read(display, SWF0(display, i));
display->restore.saveSWF1[i] = intel_de_read(display, SWF1(display, i));
}
for (i = 0; i < 3; i++)
display->restore.saveSWF3[i] = intel_de_read(display, SWF3(display, i));
}
}
static void i9xx_display_restore_swf(struct intel_display *display)
{
int i;
/* Scratch space */
if (DISPLAY_VER(display) == 2 && display->platform.mobile) {
for (i = 0; i < 7; i++) {
intel_de_write(display, SWF0(display, i), display->restore.saveSWF0[i]);
intel_de_write(display, SWF1(display, i), display->restore.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
intel_de_write(display, SWF3(display, i), display->restore.saveSWF3[i]);
} else if (DISPLAY_VER(display) == 2) {
for (i = 0; i < 7; i++)
intel_de_write(display, SWF1(display, i), display->restore.saveSWF1[i]);
} else if (HAS_GMCH(display)) {
for (i = 0; i < 16; i++) {
intel_de_write(display, SWF0(display, i), display->restore.saveSWF0[i]);
intel_de_write(display, SWF1(display, i), display->restore.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
intel_de_write(display, SWF3(display, i), display->restore.saveSWF3[i]);
}
}
void i9xx_display_sr_save(struct intel_display *display)
{
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
if (!HAS_DISPLAY(display))
return;
/* Display arbitration control */
if (DISPLAY_VER(display) <= 4)
display->restore.saveDSPARB = intel_de_read(display, DSPARB(display));
if (DISPLAY_VER(display) == 4)
pci_read_config_word(pdev, GCDGMBUS, &display->restore.saveGCDGMBUS);
i9xx_display_save_swf(display);
}
void i9xx_display_sr_restore(struct intel_display *display)
{
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
if (!HAS_DISPLAY(display))
return;
i9xx_display_restore_swf(display);
if (DISPLAY_VER(display) == 4)
pci_write_config_word(pdev, GCDGMBUS, display->restore.saveGCDGMBUS);
/* Display arbitration */
if (DISPLAY_VER(display) <= 4)
intel_de_write(display, DSPARB(display), display->restore.saveDSPARB);
}

View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2024 Intel Corporation
*/
#ifndef __I9XX_DISPLAY_SR_H__
#define __I9XX_DISPLAY_SR_H__
struct intel_display;
void i9xx_display_sr_save(struct intel_display *display);
void i9xx_display_sr_restore(struct intel_display *display);
#endif

View File

@ -8,6 +8,7 @@
#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "i9xx_plane.h"
#include "i9xx_plane_regs.h"

View File

@ -6,6 +6,7 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "i9xx_wm.h"
#include "i9xx_wm_regs.h"
#include "intel_atomic.h"
#include "intel_bo.h"
#include "intel_display.h"

View File

@ -0,0 +1,257 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2024 Intel Corporation */
#ifndef __I9XX_WM_REGS_H__
#define __I9XX_WM_REGS_H__
#include "intel_display_reg_defs.h"
#define DSPARB(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70030)
#define DSPARB_CSTART_MASK (0x7f << 7)
#define DSPARB_CSTART_SHIFT 7
#define DSPARB_BSTART_MASK (0x7f)
#define DSPARB_BSTART_SHIFT 0
#define DSPARB_BEND_SHIFT 9 /* on 855 */
#define DSPARB_AEND_SHIFT 0
#define DSPARB_SPRITEA_SHIFT_VLV 0
#define DSPARB_SPRITEA_MASK_VLV (0xff << 0)
#define DSPARB_SPRITEB_SHIFT_VLV 8
#define DSPARB_SPRITEB_MASK_VLV (0xff << 8)
#define DSPARB_SPRITEC_SHIFT_VLV 16
#define DSPARB_SPRITEC_MASK_VLV (0xff << 16)
#define DSPARB_SPRITED_SHIFT_VLV 24
#define DSPARB_SPRITED_MASK_VLV (0xff << 24)
#define DSPARB2 _MMIO(VLV_DISPLAY_BASE + 0x70060) /* vlv/chv */
#define DSPARB_SPRITEA_HI_SHIFT_VLV 0
#define DSPARB_SPRITEA_HI_MASK_VLV (0x1 << 0)
#define DSPARB_SPRITEB_HI_SHIFT_VLV 4
#define DSPARB_SPRITEB_HI_MASK_VLV (0x1 << 4)
#define DSPARB_SPRITEC_HI_SHIFT_VLV 8
#define DSPARB_SPRITEC_HI_MASK_VLV (0x1 << 8)
#define DSPARB_SPRITED_HI_SHIFT_VLV 12
#define DSPARB_SPRITED_HI_MASK_VLV (0x1 << 12)
#define DSPARB_SPRITEE_HI_SHIFT_VLV 16
#define DSPARB_SPRITEE_HI_MASK_VLV (0x1 << 16)
#define DSPARB_SPRITEF_HI_SHIFT_VLV 20
#define DSPARB_SPRITEF_HI_MASK_VLV (0x1 << 20)
#define DSPARB3 _MMIO(VLV_DISPLAY_BASE + 0x7006c) /* chv */
#define DSPARB_SPRITEE_SHIFT_VLV 0
#define DSPARB_SPRITEE_MASK_VLV (0xff << 0)
#define DSPARB_SPRITEF_SHIFT_VLV 8
#define DSPARB_SPRITEF_MASK_VLV (0xff << 8)
/* pnv/gen4/g4x/vlv/chv */
#define DSPFW1(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70034)
#define DSPFW_SR_SHIFT 23
#define DSPFW_SR_MASK (0x1ff << 23)
#define DSPFW_CURSORB_SHIFT 16
#define DSPFW_CURSORB_MASK (0x3f << 16)
#define DSPFW_PLANEB_SHIFT 8
#define DSPFW_PLANEB_MASK (0x7f << 8)
#define DSPFW_PLANEB_MASK_VLV (0xff << 8) /* vlv/chv */
#define DSPFW_PLANEA_SHIFT 0
#define DSPFW_PLANEA_MASK (0x7f << 0)
#define DSPFW_PLANEA_MASK_VLV (0xff << 0) /* vlv/chv */
#define DSPFW2(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x70038)
#define DSPFW_FBC_SR_EN (1 << 31) /* g4x */
#define DSPFW_FBC_SR_SHIFT 28
#define DSPFW_FBC_SR_MASK (0x7 << 28) /* g4x */
#define DSPFW_FBC_HPLL_SR_SHIFT 24
#define DSPFW_FBC_HPLL_SR_MASK (0xf << 24) /* g4x */
#define DSPFW_SPRITEB_SHIFT (16)
#define DSPFW_SPRITEB_MASK (0x7f << 16) /* g4x */
#define DSPFW_SPRITEB_MASK_VLV (0xff << 16) /* vlv/chv */
#define DSPFW_CURSORA_SHIFT 8
#define DSPFW_CURSORA_MASK (0x3f << 8)
#define DSPFW_PLANEC_OLD_SHIFT 0
#define DSPFW_PLANEC_OLD_MASK (0x7f << 0) /* pre-gen4 sprite C */
#define DSPFW_SPRITEA_SHIFT 0
#define DSPFW_SPRITEA_MASK (0x7f << 0) /* g4x */
#define DSPFW_SPRITEA_MASK_VLV (0xff << 0) /* vlv/chv */
#define DSPFW3(dev_priv) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x7003c)
#define DSPFW_HPLL_SR_EN (1 << 31)
#define PINEVIEW_SELF_REFRESH_EN (1 << 30)
#define DSPFW_CURSOR_SR_SHIFT 24
#define DSPFW_CURSOR_SR_MASK (0x3f << 24)
#define DSPFW_HPLL_CURSOR_SHIFT 16
#define DSPFW_HPLL_CURSOR_MASK (0x3f << 16)
#define DSPFW_HPLL_SR_SHIFT 0
#define DSPFW_HPLL_SR_MASK (0x1ff << 0)
/* vlv/chv */
#define DSPFW4 _MMIO(VLV_DISPLAY_BASE + 0x70070)
#define DSPFW_SPRITEB_WM1_SHIFT 16
#define DSPFW_SPRITEB_WM1_MASK (0xff << 16)
#define DSPFW_CURSORA_WM1_SHIFT 8
#define DSPFW_CURSORA_WM1_MASK (0x3f << 8)
#define DSPFW_SPRITEA_WM1_SHIFT 0
#define DSPFW_SPRITEA_WM1_MASK (0xff << 0)
#define DSPFW5 _MMIO(VLV_DISPLAY_BASE + 0x70074)
#define DSPFW_PLANEB_WM1_SHIFT 24
#define DSPFW_PLANEB_WM1_MASK (0xff << 24)
#define DSPFW_PLANEA_WM1_SHIFT 16
#define DSPFW_PLANEA_WM1_MASK (0xff << 16)
#define DSPFW_CURSORB_WM1_SHIFT 8
#define DSPFW_CURSORB_WM1_MASK (0x3f << 8)
#define DSPFW_CURSOR_SR_WM1_SHIFT 0
#define DSPFW_CURSOR_SR_WM1_MASK (0x3f << 0)
#define DSPFW6 _MMIO(VLV_DISPLAY_BASE + 0x70078)
#define DSPFW_SR_WM1_SHIFT 0
#define DSPFW_SR_WM1_MASK (0x1ff << 0)
#define DSPFW7 _MMIO(VLV_DISPLAY_BASE + 0x7007c)
#define DSPFW7_CHV _MMIO(VLV_DISPLAY_BASE + 0x700b4) /* wtf #1? */
#define DSPFW_SPRITED_WM1_SHIFT 24
#define DSPFW_SPRITED_WM1_MASK (0xff << 24)
#define DSPFW_SPRITED_SHIFT 16
#define DSPFW_SPRITED_MASK_VLV (0xff << 16)
#define DSPFW_SPRITEC_WM1_SHIFT 8
#define DSPFW_SPRITEC_WM1_MASK (0xff << 8)
#define DSPFW_SPRITEC_SHIFT 0
#define DSPFW_SPRITEC_MASK_VLV (0xff << 0)
#define DSPFW8_CHV _MMIO(VLV_DISPLAY_BASE + 0x700b8)
#define DSPFW_SPRITEF_WM1_SHIFT 24
#define DSPFW_SPRITEF_WM1_MASK (0xff << 24)
#define DSPFW_SPRITEF_SHIFT 16
#define DSPFW_SPRITEF_MASK_VLV (0xff << 16)
#define DSPFW_SPRITEE_WM1_SHIFT 8
#define DSPFW_SPRITEE_WM1_MASK (0xff << 8)
#define DSPFW_SPRITEE_SHIFT 0
#define DSPFW_SPRITEE_MASK_VLV (0xff << 0)
#define DSPFW9_CHV _MMIO(VLV_DISPLAY_BASE + 0x7007c) /* wtf #2? */
#define DSPFW_PLANEC_WM1_SHIFT 24
#define DSPFW_PLANEC_WM1_MASK (0xff << 24)
#define DSPFW_PLANEC_SHIFT 16
#define DSPFW_PLANEC_MASK_VLV (0xff << 16)
#define DSPFW_CURSORC_WM1_SHIFT 8
#define DSPFW_CURSORC_WM1_MASK (0x3f << 16)
#define DSPFW_CURSORC_SHIFT 0
#define DSPFW_CURSORC_MASK (0x3f << 0)
/* vlv/chv high order bits */
#define DSPHOWM _MMIO(VLV_DISPLAY_BASE + 0x70064)
#define DSPFW_SR_HI_SHIFT 24
#define DSPFW_SR_HI_MASK (3 << 24) /* 2 bits for chv, 1 for vlv */
#define DSPFW_SPRITEF_HI_SHIFT 23
#define DSPFW_SPRITEF_HI_MASK (1 << 23)
#define DSPFW_SPRITEE_HI_SHIFT 22
#define DSPFW_SPRITEE_HI_MASK (1 << 22)
#define DSPFW_PLANEC_HI_SHIFT 21
#define DSPFW_PLANEC_HI_MASK (1 << 21)
#define DSPFW_SPRITED_HI_SHIFT 20
#define DSPFW_SPRITED_HI_MASK (1 << 20)
#define DSPFW_SPRITEC_HI_SHIFT 16
#define DSPFW_SPRITEC_HI_MASK (1 << 16)
#define DSPFW_PLANEB_HI_SHIFT 12
#define DSPFW_PLANEB_HI_MASK (1 << 12)
#define DSPFW_SPRITEB_HI_SHIFT 8
#define DSPFW_SPRITEB_HI_MASK (1 << 8)
#define DSPFW_SPRITEA_HI_SHIFT 4
#define DSPFW_SPRITEA_HI_MASK (1 << 4)
#define DSPFW_PLANEA_HI_SHIFT 0
#define DSPFW_PLANEA_HI_MASK (1 << 0)
#define DSPHOWM1 _MMIO(VLV_DISPLAY_BASE + 0x70068)
#define DSPFW_SR_WM1_HI_SHIFT 24
#define DSPFW_SR_WM1_HI_MASK (3 << 24) /* 2 bits for chv, 1 for vlv */
#define DSPFW_SPRITEF_WM1_HI_SHIFT 23
#define DSPFW_SPRITEF_WM1_HI_MASK (1 << 23)
#define DSPFW_SPRITEE_WM1_HI_SHIFT 22
#define DSPFW_SPRITEE_WM1_HI_MASK (1 << 22)
#define DSPFW_PLANEC_WM1_HI_SHIFT 21
#define DSPFW_PLANEC_WM1_HI_MASK (1 << 21)
#define DSPFW_SPRITED_WM1_HI_SHIFT 20
#define DSPFW_SPRITED_WM1_HI_MASK (1 << 20)
#define DSPFW_SPRITEC_WM1_HI_SHIFT 16
#define DSPFW_SPRITEC_WM1_HI_MASK (1 << 16)
#define DSPFW_PLANEB_WM1_HI_SHIFT 12
#define DSPFW_PLANEB_WM1_HI_MASK (1 << 12)
#define DSPFW_SPRITEB_WM1_HI_SHIFT 8
#define DSPFW_SPRITEB_WM1_HI_MASK (1 << 8)
#define DSPFW_SPRITEA_WM1_HI_SHIFT 4
#define DSPFW_SPRITEA_WM1_HI_MASK (1 << 4)
#define DSPFW_PLANEA_WM1_HI_SHIFT 0
#define DSPFW_PLANEA_WM1_HI_MASK (1 << 0)
/* drain latency register values*/
#define VLV_DDL(pipe) _MMIO(VLV_DISPLAY_BASE + 0x70050 + 4 * (pipe))
#define DDL_CURSOR_SHIFT 24
#define DDL_SPRITE_SHIFT(sprite) (8 + 8 * (sprite))
#define DDL_PLANE_SHIFT 0
#define DDL_PRECISION_HIGH (1 << 7)
#define DDL_PRECISION_LOW (0 << 7)
#define DRAIN_LATENCY_MASK 0x7f
/* FIFO watermark sizes etc */
#define G4X_FIFO_LINE_SIZE 64
#define I915_FIFO_LINE_SIZE 64
#define I830_FIFO_LINE_SIZE 32
#define VALLEYVIEW_FIFO_SIZE 255
#define G4X_FIFO_SIZE 127
#define I965_FIFO_SIZE 512
#define I945_FIFO_SIZE 127
#define I915_FIFO_SIZE 95
#define I855GM_FIFO_SIZE 127 /* In cachelines */
#define I830_FIFO_SIZE 95
#define VALLEYVIEW_MAX_WM 0xff
#define G4X_MAX_WM 0x3f
#define I915_MAX_WM 0x3f
#define PINEVIEW_DISPLAY_FIFO 512 /* in 64byte unit */
#define PINEVIEW_FIFO_LINE_SIZE 64
#define PINEVIEW_MAX_WM 0x1ff
#define PINEVIEW_DFT_WM 0x3f
#define PINEVIEW_DFT_HPLLOFF_WM 0
#define PINEVIEW_GUARD_WM 10
#define PINEVIEW_CURSOR_FIFO 64
#define PINEVIEW_CURSOR_MAX_WM 0x3f
#define PINEVIEW_CURSOR_DFT_WM 0
#define PINEVIEW_CURSOR_GUARD_WM 5
#define VALLEYVIEW_CURSOR_MAX_WM 64
#define I965_CURSOR_FIFO 64
#define I965_CURSOR_MAX_WM 32
#define I965_CURSOR_DFT_WM 8
/* define the Watermark register on Ironlake */
#define _WM0_PIPEA_ILK 0x45100
#define _WM0_PIPEB_ILK 0x45104
#define _WM0_PIPEC_IVB 0x45200
#define WM0_PIPE_ILK(pipe) _MMIO_BASE_PIPE3(0, (pipe), _WM0_PIPEA_ILK, \
_WM0_PIPEB_ILK, _WM0_PIPEC_IVB)
#define WM0_PIPE_PRIMARY_MASK REG_GENMASK(31, 16)
#define WM0_PIPE_SPRITE_MASK REG_GENMASK(15, 8)
#define WM0_PIPE_CURSOR_MASK REG_GENMASK(7, 0)
#define WM0_PIPE_PRIMARY(x) REG_FIELD_PREP(WM0_PIPE_PRIMARY_MASK, (x))
#define WM0_PIPE_SPRITE(x) REG_FIELD_PREP(WM0_PIPE_SPRITE_MASK, (x))
#define WM0_PIPE_CURSOR(x) REG_FIELD_PREP(WM0_PIPE_CURSOR_MASK, (x))
#define WM1_LP_ILK _MMIO(0x45108)
#define WM2_LP_ILK _MMIO(0x4510c)
#define WM3_LP_ILK _MMIO(0x45110)
#define WM_LP_ENABLE REG_BIT(31)
#define WM_LP_LATENCY_MASK REG_GENMASK(30, 24)
#define WM_LP_FBC_MASK_BDW REG_GENMASK(23, 19)
#define WM_LP_FBC_MASK_ILK REG_GENMASK(23, 20)
#define WM_LP_PRIMARY_MASK REG_GENMASK(18, 8)
#define WM_LP_CURSOR_MASK REG_GENMASK(7, 0)
#define WM_LP_LATENCY(x) REG_FIELD_PREP(WM_LP_LATENCY_MASK, (x))
#define WM_LP_FBC_BDW(x) REG_FIELD_PREP(WM_LP_FBC_MASK_BDW, (x))
#define WM_LP_FBC_ILK(x) REG_FIELD_PREP(WM_LP_FBC_MASK_ILK, (x))
#define WM_LP_PRIMARY(x) REG_FIELD_PREP(WM_LP_PRIMARY_MASK, (x))
#define WM_LP_CURSOR(x) REG_FIELD_PREP(WM_LP_CURSOR_MASK, (x))
#define WM1S_LP_ILK _MMIO(0x45120)
#define WM2S_LP_IVB _MMIO(0x45124)
#define WM3S_LP_IVB _MMIO(0x45128)
#define WM_LP_SPRITE_ENABLE REG_BIT(31) /* ilk/snb WM1S only */
#define WM_LP_SPRITE_MASK REG_GENMASK(10, 0)
#define WM_LP_SPRITE(x) REG_FIELD_PREP(WM_LP_SPRITE_MASK, (x))
#define WM_MISC _MMIO(0x45260)
#define WM_MISC_DATA_PARTITION_5_6 (1 << 0)
#define WM_DBG _MMIO(0x45280)
#define WM_DBG_DISALLOW_MULTIPLE_LP (1 << 0)
#define WM_DBG_DISALLOW_MAXFIFO (1 << 1)
#define WM_DBG_DISALLOW_SPRITE (1 << 2)
#endif /* __I9XX_WM_REGS_H__ */

View File

@ -31,6 +31,7 @@
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "icl_dsi.h"
#include "icl_dsi_regs.h"
@ -1602,7 +1603,9 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
/* FIXME: split only when necessary */
if (crtc_state->dsc.slice_count > 1)
crtc_state->dsc.dsc_split = true;
crtc_state->dsc.num_streams = 2;
else
crtc_state->dsc.num_streams = 1;
/* FIXME: initialize from VBT */
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;

View File

@ -9,8 +9,9 @@
#include <linux/acpi.h>
#include <acpi/video.h>
#include "i915_drv.h"
#include "i915_utils.h"
#include "intel_acpi.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */

View File

@ -40,6 +40,7 @@
#include <drm/drm_gem.h>
#include <drm/drm_gem_atomic_helper.h>
#include "i915_drv.h"
#include "i915_config.h"
#include "i9xx_plane_regs.h"
#include "intel_atomic_plane.h"
@ -207,17 +208,6 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
fb->format->cpp[color_plane];
}
static bool
use_min_ddb(const struct intel_crtc_state *crtc_state,
struct intel_plane *plane)
{
struct drm_i915_private *i915 = to_i915(plane->base.dev);
return DISPLAY_VER(i915) >= 13 &&
crtc_state->uapi.async_flip &&
plane->async_flip;
}
static unsigned int
intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
@ -225,8 +215,8 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
{
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
const struct drm_framebuffer *fb = plane_state->hw.fb;
int width, height;
unsigned int rel_data_rate;
int width, height;
if (plane->id == PLANE_CURSOR)
return 0;
@ -234,14 +224,6 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
if (!plane_state->uapi.visible)
return 0;
/*
* We calculate extra ddb based on ratio plane rate/total data rate
* in case, in some cases we should not allocate extra ddb for the plane,
* so do not count its data rate, if this is the case.
*/
if (use_min_ddb(crtc_state, plane))
return 0;
/*
* Src coordinates are already rotated by 270 degrees for
* the 90/270 degree plane rotation cases (to match the
@ -256,7 +238,11 @@ intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state,
height /= 2;
}
rel_data_rate = width * height * fb->format->cpp[color_plane];
rel_data_rate =
skl_plane_relative_data_rate(crtc_state, plane, width, height,
fb->format->cpp[color_plane]);
if (!rel_data_rate)
return 0;
return intel_adjusted_rate(&plane_state->uapi.src,
&plane_state->uapi.dst,

View File

@ -681,12 +681,11 @@ static void ibx_audio_codec_enable(struct intel_encoder *encoder,
void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc_state);
enum transcoder trans = crtc_state->cpu_transcoder;
if (HAS_DP20(i915))
intel_de_rmw(i915, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT,
if (HAS_DP20(display))
intel_de_rmw(display, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT,
crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0);
}
@ -981,6 +980,53 @@ static void glk_force_audio_cdclk(struct drm_i915_private *i915,
drm_modeset_acquire_fini(&ctx);
}
int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *dev_priv = to_i915(display->drm);
int min_cdclk = 0;
if (!crtc_state->has_audio)
return 0;
/* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz,
* audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else
* there may be audio corruption or screen corruption." This cdclk
* restriction for GLK is 316.8 MHz.
*/
if (intel_crtc_has_dp_encoder(crtc_state) &&
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) {
if (DISPLAY_VER(display) == 10) {
/* Display WA #1145: glk */
min_cdclk = max(min_cdclk, 316800);
} else if (DISPLAY_VER(display) == 9 || IS_BROADWELL(dev_priv)) {
/* Display WA #1144: skl,bxt */
min_cdclk = max(min_cdclk, 432000);
}
}
/*
* According to BSpec, "The CD clock frequency must be at least twice
* the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
*/
if (DISPLAY_VER(display) >= 9)
min_cdclk = max(min_cdclk, 2 * 96000);
/*
* "For DP audio configuration, cdclk frequency shall be set to
* meet the following requirements:
* DP Link Frequency(MHz) | Cdclk frequency(MHz)
* 270 | 320 or higher
* 162 | 200 or higher"
*/
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_crtc_has_dp_encoder(crtc_state))
min_cdclk = max(min_cdclk, crtc_state->port_clock);
return min_cdclk;
}
static unsigned long i915_audio_component_get_power(struct device *kdev)
{
struct intel_display *display = to_intel_display(kdev);

View File

@ -27,6 +27,7 @@ void intel_audio_codec_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state);
void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
int intel_audio_min_cdclk(const struct intel_crtc_state *crtc_state);
void intel_audio_init(struct drm_i915_private *dev_priv);
void intel_audio_register(struct drm_i915_private *i915);
void intel_audio_deinit(struct drm_i915_private *dev_priv);

View File

@ -10,6 +10,7 @@
#include <acpi/video.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_backlight.h"
#include "intel_backlight_regs.h"

View File

@ -1402,12 +1402,21 @@ parse_power_conservation_features(struct intel_display *display,
panel_type);
}
static void vbt_edp_to_pps_delays(struct intel_pps_delays *pps,
const struct edp_power_seq *edp_pps)
{
pps->power_up = edp_pps->t1_t3;
pps->backlight_on = edp_pps->t8;
pps->backlight_off = edp_pps->t9;
pps->power_down = edp_pps->t10;
pps->power_cycle = edp_pps->t11_t12;
}
static void
parse_edp(struct intel_display *display,
struct intel_panel *panel)
{
const struct bdb_edp *edp;
const struct edp_power_seq *edp_pps;
const struct edp_fast_link_params *edp_link_params;
int panel_type = panel->vbt.panel_type;
@ -1428,10 +1437,10 @@ parse_edp(struct intel_display *display,
}
/* Get the eDP sequencing and link info */
edp_pps = &edp->power_seqs[panel_type];
edp_link_params = &edp->fast_link_params[panel_type];
panel->vbt.edp.pps = *edp_pps;
vbt_edp_to_pps_delays(&panel->vbt.edp.pps,
&edp->power_seqs[panel_type]);
if (display->vbt.version >= 224) {
panel->vbt.edp.rate =

View File

@ -50,14 +50,6 @@ enum intel_backlight_type {
INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE,
};
struct edp_power_seq {
u16 t1_t3;
u16 t8;
u16 t9;
u16 t10;
u16 t11_t12;
} __packed;
/*
* MIPI Sequence Block definitions
*

View File

@ -1256,7 +1256,7 @@ int intel_bw_min_cdclk(struct drm_i915_private *i915,
min_cdclk = intel_bw_dbuf_min_cdclk(i915, bw_state);
for_each_pipe(i915, pipe)
min_cdclk = max(bw_state->min_cdclk[pipe], min_cdclk);
min_cdclk = max(min_cdclk, bw_state->min_cdclk[pipe]);
return min_cdclk;
}

View File

@ -29,6 +29,7 @@
#include "soc/intel_dram.h"
#include "hsw_ips.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
@ -37,7 +38,6 @@
#include "intel_cdclk.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_dp.h"
#include "intel_display_types.h"
#include "intel_mchbar_regs.h"
#include "intel_pci_config.h"
@ -46,6 +46,7 @@
#include "intel_vdsc.h"
#include "skl_watermark.h"
#include "skl_watermark_regs.h"
#include "vlv_dsi.h"
#include "vlv_sideband.h"
/**
@ -2761,23 +2762,34 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
"Post changing CDCLK to");
}
/* pixels per CDCLK */
static int intel_cdclk_ppc(struct intel_display *display, bool double_wide)
{
return DISPLAY_VER(display) >= 10 || double_wide ? 2 : 1;
}
/* max pixel rate as % of CDCLK (not accounting for PPC) */
static int intel_cdclk_guardband(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
if (DISPLAY_VER(display) >= 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return 100;
else if (IS_CHERRYVIEW(dev_priv))
return 95;
else
return 90;
}
static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *dev_priv = to_i915(display->drm);
int ppc = intel_cdclk_ppc(display, crtc_state->double_wide);
int guardband = intel_cdclk_guardband(display);
int pixel_rate = crtc_state->pixel_rate;
if (DISPLAY_VER(display) >= 10)
return DIV_ROUND_UP(pixel_rate, 2);
else if (DISPLAY_VER(display) == 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return pixel_rate;
else if (IS_CHERRYVIEW(dev_priv))
return DIV_ROUND_UP(pixel_rate * 100, 95);
else if (crtc_state->double_wide)
return DIV_ROUND_UP(pixel_rate * 100, 90 * 2);
else
return DIV_ROUND_UP(pixel_rate * 100, 90);
return DIV_ROUND_UP(pixel_rate * 100, guardband * ppc);
}
static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
@ -2788,127 +2800,24 @@ static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
int min_cdclk = 0;
for_each_intel_plane_on_crtc(display->drm, crtc, plane)
min_cdclk = max(crtc_state->min_cdclk[plane->id], min_cdclk);
return min_cdclk;
}
static int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_display *display = to_intel_display(crtc);
int num_vdsc_instances = intel_dsc_get_num_vdsc_instances(crtc_state);
int min_cdclk = 0;
/*
* When we decide to use only one VDSC engine, since
* each VDSC operates with 1 ppc throughput, pixel clock
* cannot be higher than the VDSC clock (cdclk)
* If there 2 VDSC engines, then pixel clock can't be higher than
* VDSC clock(cdclk) * 2 and so on.
*/
min_cdclk = max_t(int, min_cdclk,
DIV_ROUND_UP(crtc_state->pixel_rate, num_vdsc_instances));
if (crtc_state->joiner_pipes) {
int pixel_clock = intel_dp_mode_to_fec_clock(crtc_state->hw.adjusted_mode.clock);
/*
* According to Bigjoiner bw check:
* compressed_bpp <= PPC * CDCLK * Big joiner Interface bits / Pixel clock
*
* We have already computed compressed_bpp, so now compute the min CDCLK that
* is required to support this compressed_bpp.
*
* => CDCLK >= compressed_bpp * Pixel clock / (PPC * Bigjoiner Interface bits)
*
* Since PPC = 2 with bigjoiner
* => CDCLK >= compressed_bpp * Pixel clock / 2 * Bigjoiner Interface bits
*/
int bigjoiner_interface_bits = DISPLAY_VER(display) >= 14 ? 36 : 24;
int min_cdclk_bj =
(fxp_q4_to_int_roundup(crtc_state->dsc.compressed_bpp_x16) *
pixel_clock) / (2 * bigjoiner_interface_bits);
min_cdclk = max(min_cdclk, min_cdclk_bj);
}
min_cdclk = max(min_cdclk, crtc_state->min_cdclk[plane->id]);
return min_cdclk;
}
int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
struct drm_i915_private *dev_priv = to_i915(display->drm);
int min_cdclk;
if (!crtc_state->hw.enable)
return 0;
min_cdclk = intel_pixel_rate_to_cdclk(crtc_state);
/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
if (IS_BROADWELL(dev_priv) && hsw_crtc_state_ips_capable(crtc_state))
min_cdclk = DIV_ROUND_UP(min_cdclk * 100, 95);
/* BSpec says "Do not use DisplayPort with CDCLK less than 432 MHz,
* audio enabled, port width x4, and link rate HBR2 (5.4 GHz), or else
* there may be audio corruption or screen corruption." This cdclk
* restriction for GLK is 316.8 MHz.
*/
if (intel_crtc_has_dp_encoder(crtc_state) &&
crtc_state->has_audio &&
crtc_state->port_clock >= 540000 &&
crtc_state->lane_count == 4) {
if (DISPLAY_VER(display) == 10) {
/* Display WA #1145: glk */
min_cdclk = max(316800, min_cdclk);
} else if (DISPLAY_VER(display) == 9 || IS_BROADWELL(dev_priv)) {
/* Display WA #1144: skl,bxt */
min_cdclk = max(432000, min_cdclk);
}
}
/*
* According to BSpec, "The CD clock frequency must be at least twice
* the frequency of the Azalia BCLK." and BCLK is 96 MHz by default.
*/
if (crtc_state->has_audio && DISPLAY_VER(display) >= 9)
min_cdclk = max(2 * 96000, min_cdclk);
/*
* "For DP audio configuration, cdclk frequency shall be set to
* meet the following requirements:
* DP Link Frequency(MHz) | Cdclk frequency(MHz)
* 270 | 320 or higher
* 162 | 200 or higher"
*/
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_crtc_has_dp_encoder(crtc_state) && crtc_state->has_audio)
min_cdclk = max(crtc_state->port_clock, min_cdclk);
/*
* On Valleyview some DSI panels lose (v|h)sync when the clock is lower
* than 320000KHz.
*/
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) &&
IS_VALLEYVIEW(dev_priv))
min_cdclk = max(320000, min_cdclk);
/*
* On Geminilake once the CDCLK gets as low as 79200
* picture gets unstable, despite that values are
* correct for DSI PLL and DE PLL.
*/
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) &&
IS_GEMINILAKE(dev_priv))
min_cdclk = max(158400, min_cdclk);
/* Account for additional needs from the planes */
min_cdclk = max(intel_planes_min_cdclk(crtc_state), min_cdclk);
if (crtc_state->dsc.compression_enable)
min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, hsw_ips_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, intel_audio_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, vlv_dsi_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, intel_planes_min_cdclk(crtc_state));
min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state));
return min_cdclk;
}
@ -2960,7 +2869,7 @@ static int intel_compute_min_cdclk(struct intel_atomic_state *state)
min_cdclk = max(cdclk_state->force_min_cdclk,
cdclk_state->bw_min_cdclk);
for_each_pipe(display, pipe)
min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk);
min_cdclk = max(min_cdclk, cdclk_state->min_cdclk[pipe]);
/*
* Avoid glk_force_audio_cdclk() causing excessive screen
@ -2972,7 +2881,7 @@ static int intel_compute_min_cdclk(struct intel_atomic_state *state)
*/
if (IS_GEMINILAKE(dev_priv) && cdclk_state->active_pipes &&
!is_power_of_2(cdclk_state->active_pipes))
min_cdclk = max(2 * 96000, min_cdclk);
min_cdclk = max(min_cdclk, 2 * 96000);
if (min_cdclk > display->cdclk.max_cdclk_freq) {
drm_dbg_kms(display->drm,
@ -3028,8 +2937,8 @@ static int bxt_compute_min_voltage_level(struct intel_atomic_state *state)
min_voltage_level = 0;
for_each_pipe(display, pipe)
min_voltage_level = max(cdclk_state->min_voltage_level[pipe],
min_voltage_level);
min_voltage_level = max(min_voltage_level,
cdclk_state->min_voltage_level[pipe]);
return min_voltage_level;
}
@ -3452,20 +3361,11 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
static int intel_compute_max_dotclk(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
int ppc = intel_cdclk_ppc(display, HAS_DOUBLE_WIDE(display));
int guardband = intel_cdclk_guardband(display);
int max_cdclk_freq = display->cdclk.max_cdclk_freq;
if (DISPLAY_VER(display) >= 10)
return 2 * max_cdclk_freq;
else if (DISPLAY_VER(display) == 9 ||
IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return max_cdclk_freq;
else if (IS_CHERRYVIEW(dev_priv))
return max_cdclk_freq*95/100;
else if (DISPLAY_VER(display) < 4)
return 2*max_cdclk_freq*90/100;
else
return max_cdclk_freq*90/100;
return ppc * max_cdclk_freq * guardband / 100;
}
/**

View File

@ -22,6 +22,7 @@
*
*/
#include "i915_drv.h"
#include "i9xx_plane_regs.h"
#include "intel_color.h"
#include "intel_color_regs.h"

View File

@ -3,6 +3,7 @@
* Copyright © 2018 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_combo_phy.h"
#include "intel_combo_phy_regs.h"

View File

@ -38,6 +38,7 @@
#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_crt.h"
#include "intel_crt_regs.h"
#include "intel_crtc.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
@ -55,18 +56,23 @@
#include "intel_pch_refclk.h"
/* Here's the desired hotplug mode */
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_ENABLE | \
ADPA_CRT_HOTPLUG_PERIOD_128 | \
ADPA_CRT_HOTPLUG_WARMUP_10MS | \
ADPA_CRT_HOTPLUG_SAMPLE_4S | \
ADPA_CRT_HOTPLUG_VOLTAGE_50 | \
ADPA_CRT_HOTPLUG_VOLREF_325MV | \
ADPA_CRT_HOTPLUG_ENABLE)
ADPA_CRT_HOTPLUG_VOLREF_325MV)
#define ADPA_HOTPLUG_MASK (ADPA_CRT_HOTPLUG_MONITOR_MASK | \
ADPA_CRT_HOTPLUG_ENABLE | \
ADPA_CRT_HOTPLUG_PERIOD_MASK | \
ADPA_CRT_HOTPLUG_WARMUP_MASK | \
ADPA_CRT_HOTPLUG_SAMPLE_MASK | \
ADPA_CRT_HOTPLUG_VOLTAGE_MASK | \
ADPA_CRT_HOTPLUG_VOLREF_MASK | \
ADPA_CRT_HOTPLUG_FORCE_TRIGGER)
struct intel_crt {
struct intel_encoder base;
/* DPMS state is stored in the connector, which we need in the
* encoder's enable/disable callbacks */
struct intel_connector *connector;
bool force_hotplug_required;
i915_reg_t adpa_reg;
};
@ -91,9 +97,9 @@ bool intel_crt_port_enabled(struct intel_display *display,
/* asserts want to know the pipe even if the port is disabled */
if (HAS_PCH_CPT(dev_priv))
*pipe = (val & ADPA_PIPE_SEL_MASK_CPT) >> ADPA_PIPE_SEL_SHIFT_CPT;
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK_CPT, val);
else
*pipe = (val & ADPA_PIPE_SEL_MASK) >> ADPA_PIPE_SEL_SHIFT;
*pipe = REG_FIELD_GET(ADPA_PIPE_SEL_MASK, val);
return val & ADPA_DAC_ENABLE;
}
@ -141,27 +147,27 @@ static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
}
static void intel_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
struct intel_crtc_state *crtc_state)
{
pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
crtc_state->output_types |= BIT(INTEL_OUTPUT_ANALOG);
pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
crtc_state->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock;
crtc_state->hw.adjusted_mode.crtc_clock = crtc_state->port_clock;
}
static void hsw_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
struct intel_crtc_state *crtc_state)
{
lpt_pch_get_config(pipe_config);
lpt_pch_get_config(crtc_state);
hsw_ddi_get_config(encoder, pipe_config);
hsw_ddi_get_config(encoder, crtc_state);
pipe_config->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_NVSYNC);
pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
crtc_state->hw.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_NVSYNC);
crtc_state->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
}
/* Note: The caller is required to filter out dpms modes not supported by the
@ -244,7 +250,7 @@ static void hsw_disable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
drm_WARN_ON(display->drm, !old_crtc_state->has_pch_encoder);
@ -257,7 +263,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@ -287,7 +293,7 @@ static void hsw_pre_pll_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
drm_WARN_ON(display->drm, !crtc_state->has_pch_encoder);
@ -300,7 +306,7 @@ static void hsw_pre_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
@ -319,7 +325,7 @@ static void hsw_enable_crt(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(state);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
@ -355,8 +361,7 @@ intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
int max_dotclk = display->cdclk.max_dotclk_freq;
enum drm_mode_status status;
int max_clock;
@ -399,48 +404,48 @@ intel_crt_mode_valid(struct drm_connector *connector,
}
static int intel_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
&crtc_state->hw.adjusted_mode;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
return 0;
}
static int pch_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
&crtc_state->hw.adjusted_mode;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
pipe_config->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(pipe_config))
crtc_state->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(crtc_state))
return -EINVAL;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
return 0;
}
static int hsw_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
&crtc_state->hw.adjusted_mode;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
@ -450,30 +455,30 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
adjusted_mode->crtc_hblank_start > 4096)
return -EINVAL;
pipe_config->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(pipe_config))
crtc_state->has_pch_encoder = true;
if (!intel_fdi_compute_pipe_bpp(crtc_state))
return -EINVAL;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
/* LPT FDI RX only supports 8bpc. */
if (HAS_PCH_LPT(dev_priv)) {
/* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */
if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
if (crtc_state->bw_constrained && crtc_state->pipe_bpp < 24) {
drm_dbg_kms(display->drm,
"LPT only supports 24bpp\n");
return -EINVAL;
}
pipe_config->pipe_bpp = 24;
crtc_state->pipe_bpp = 24;
}
/* FDI must always be 2.7 GHz */
pipe_config->port_clock = 135000 * 2;
crtc_state->port_clock = 135000 * 2;
pipe_config->enhanced_framing = true;
crtc_state->enhanced_framing = true;
adjusted_mode->crtc_clock = lpt_iclkip(pipe_config);
adjusted_mode->crtc_clock = lpt_iclkip(crtc_state);
return 0;
}
@ -481,9 +486,8 @@ static int hsw_crt_compute_config(struct intel_encoder *encoder,
static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
u32 adpa;
bool ret;
@ -532,9 +536,8 @@ static bool ilk_crt_detect_hotplug(struct drm_connector *connector)
static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
bool reenable_hpd;
u32 adpa;
bool ret;
@ -588,8 +591,7 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
static bool intel_crt_detect_hotplug(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
u32 stat;
bool ret = false;
int i, tries = 0;
@ -856,7 +858,7 @@ intel_crt_detect(struct drm_connector *connector,
struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *intel_encoder = &crt->base;
struct intel_encoder *encoder = &crt->base;
struct drm_atomic_state *state;
intel_wakeref_t wakeref;
int status;
@ -865,15 +867,14 @@ intel_crt_detect(struct drm_connector *connector,
connector->base.id, connector->name,
force);
if (!intel_display_device_enabled(dev_priv))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return connector->status;
if (display->params.load_detect_test) {
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
goto load_detect;
}
@ -881,8 +882,7 @@ intel_crt_detect(struct drm_connector *connector,
if (dmi_check_system(intel_spurious_crt_detect))
return connector_status_disconnected;
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
if (I915_HAS_HOTPLUG(display)) {
/* We can not rely on the HPD pin always being correctly wired
@ -939,7 +939,7 @@ intel_crt_detect(struct drm_connector *connector,
}
out:
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
return status;
}
@ -947,19 +947,17 @@ intel_crt_detect(struct drm_connector *connector,
static int intel_crt_get_modes(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_crt *crt = intel_attached_crt(to_intel_connector(connector));
struct intel_encoder *intel_encoder = &crt->base;
struct intel_encoder *encoder = &crt->base;
intel_wakeref_t wakeref;
struct i2c_adapter *ddc;
int ret;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return drm_edid_connector_add_modes(connector);
wakeref = intel_display_power_get(dev_priv,
intel_encoder->power_domain);
wakeref = intel_display_power_get(dev_priv, encoder->power_domain);
ret = intel_crt_ddc_get_modes(connector, connector->ddc);
if (ret || !IS_G4X(dev_priv))
@ -970,7 +968,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
ret = intel_crt_ddc_get_modes(connector, ddc);
out:
intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
return ret;
}
@ -984,7 +982,7 @@ void intel_crt_reset(struct drm_encoder *encoder)
u32 adpa;
adpa = intel_de_read(display, crt->adpa_reg);
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
adpa &= ~ADPA_HOTPLUG_MASK;
adpa |= ADPA_HOTPLUG_BITS;
intel_de_write(display, crt->adpa_reg, adpa);
intel_de_posting_read(display, crt->adpa_reg);
@ -1022,9 +1020,8 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
void intel_crt_init(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct drm_connector *connector;
struct intel_connector *connector;
struct intel_crt *crt;
struct intel_connector *intel_connector;
i915_reg_t adpa_reg;
u8 ddc_pin;
u32 adpa;
@ -1047,7 +1044,9 @@ void intel_crt_init(struct intel_display *display)
* it and see what happens.
*/
intel_de_write(display, adpa_reg,
adpa | ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
adpa | ADPA_DAC_ENABLE |
ADPA_HSYNC_CNTL_DISABLE |
ADPA_VSYNC_CNTL_DISABLE);
if ((intel_de_read(display, adpa_reg) & ADPA_DAC_ENABLE) == 0)
return;
intel_de_write(display, adpa_reg, adpa);
@ -1057,17 +1056,15 @@ void intel_crt_init(struct intel_display *display)
if (!crt)
return;
intel_connector = intel_connector_alloc();
if (!intel_connector) {
connector = intel_connector_alloc();
if (!connector) {
kfree(crt);
return;
}
ddc_pin = display->vbt.crt_ddc_pin;
connector = &intel_connector->base;
crt->connector = intel_connector;
drm_connector_init_with_ddc(display->drm, connector,
drm_connector_init_with_ddc(display->drm, &connector->base,
&intel_crt_connector_funcs,
DRM_MODE_CONNECTOR_VGA,
intel_gmbus_get_adapter(display, ddc_pin));
@ -1075,7 +1072,7 @@ void intel_crt_init(struct intel_display *display)
drm_encoder_init(display->drm, &crt->base.base, &intel_crt_enc_funcs,
DRM_MODE_ENCODER_DAC, "CRT");
intel_connector_attach_encoder(intel_connector, &crt->base);
intel_connector_attach_encoder(connector, &crt->base);
crt->base.type = INTEL_OUTPUT_ANALOG;
crt->base.cloneable = BIT(INTEL_OUTPUT_DVO) | BIT(INTEL_OUTPUT_HDMI);
@ -1085,7 +1082,7 @@ void intel_crt_init(struct intel_display *display)
crt->base.pipe_mask = ~0;
if (DISPLAY_VER(display) != 2)
connector->interlace_allowed = true;
connector->base.interlace_allowed = true;
crt->adpa_reg = adpa_reg;
@ -1095,11 +1092,11 @@ void intel_crt_init(struct intel_display *display)
!dmi_check_system(intel_spurious_crt_detect)) {
crt->base.hpd_pin = HPD_CRT;
crt->base.hotplug = intel_encoder_hotplug;
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->polled = DRM_CONNECTOR_POLL_HPD;
} else {
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
}
intel_connector->base.polled = intel_connector->polled;
connector->base.polled = connector->polled;
if (HAS_DDI(display)) {
assert_port_valid(dev_priv, PORT_E);
@ -1132,9 +1129,9 @@ void intel_crt_init(struct intel_display *display)
crt->base.get_hw_state = intel_crt_get_hw_state;
crt->base.enable = intel_enable_crt;
}
intel_connector->get_hw_state = intel_connector_get_hw_state;
connector->get_hw_state = intel_connector_get_hw_state;
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
drm_connector_helper_add(&connector->base, &intel_crt_connector_helper_funcs);
/*
* TODO: find a proper way to discover whether we need to set the the

View File

@ -0,0 +1,50 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2024 Intel Corporation
*/
#ifndef __INTEL_CRT_REGS_H__
#define __INTEL_CRT_REGS_H__
#include "intel_display_reg_defs.h"
#define ADPA _MMIO(0x61100)
#define PCH_ADPA _MMIO(0xe1100)
#define VLV_ADPA _MMIO(VLV_DISPLAY_BASE + 0x61100)
#define ADPA_DAC_ENABLE REG_BIT(31)
#define ADPA_PIPE_SEL_MASK REG_BIT(30)
#define ADPA_PIPE_SEL(pipe) REG_FIELD_PREP(ADPA_PIPE_SEL_MASK, (pipe))
#define ADPA_PIPE_SEL_MASK_CPT REG_GENMASK(30, 29)
#define ADPA_PIPE_SEL_CPT(pipe) REG_FIELD_PREP(ADPA_PIPE_SEL_MASK_CPT, (pipe))
#define ADPA_CRT_HOTPLUG_MONITOR_MASK REG_GENMASK(25, 24)
#define ADPA_CRT_HOTPLUG_MONITOR_NONE REG_FIELD_PREP(ADPA_CRT_HOTPLUG_MONITOR_MASK, 0)
#define ADPA_CRT_HOTPLUG_MONITOR_COLOR REG_FIELD_PREP(ADPA_CRT_HOTPLUG_MONITOR_MASK, 3)
#define ADPA_CRT_HOTPLUG_MONITOR_MONO REG_FIELD_PREP(ADPA_CRT_HOTPLUG_MONITOR_MASK, 2)
#define ADPA_CRT_HOTPLUG_ENABLE REG_BIT(23)
#define ADPA_CRT_HOTPLUG_PERIOD_MASK REG_BIT(22)
#define ADPA_CRT_HOTPLUG_PERIOD_64 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_PERIOD_MASK, 0)
#define ADPA_CRT_HOTPLUG_PERIOD_128 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_PERIOD_MASK, 1)
#define ADPA_CRT_HOTPLUG_WARMUP_MASK REG_BIT(21)
#define ADPA_CRT_HOTPLUG_WARMUP_5MS REG_FIELD_PREP(ADPA_CRT_HOTPLUG_WARMUP_MASK, 0)
#define ADPA_CRT_HOTPLUG_WARMUP_10MS REG_FIELD_PREP(ADPA_CRT_HOTPLUG_WARMUP_MASK, 1)
#define ADPA_CRT_HOTPLUG_SAMPLE_MASK REG_BIT(20)
#define ADPA_CRT_HOTPLUG_SAMPLE_2S REG_FIELD_PREP(ADPA_CRT_HOTPLUG_SAMPLE_MASK, 0)
#define ADPA_CRT_HOTPLUG_SAMPLE_4S REG_FIELD_PREP(ADPA_CRT_HOTPLUG_SAMPLE_MASK, 1)
#define ADPA_CRT_HOTPLUG_VOLTAGE_MASK REG_GENMASK(19, 18)
#define ADPA_CRT_HOTPLUG_VOLTAGE_40 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 0)
#define ADPA_CRT_HOTPLUG_VOLTAGE_50 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 1)
#define ADPA_CRT_HOTPLUG_VOLTAGE_60 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 2)
#define ADPA_CRT_HOTPLUG_VOLTAGE_70 REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLTAGE_MASK, 3)
#define ADPA_CRT_HOTPLUG_VOLREF_MASK REG_BIT(17)
#define ADPA_CRT_HOTPLUG_VOLREF_325MV REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLREF_MASK, 0)
#define ADPA_CRT_HOTPLUG_VOLREF_475MV REG_FIELD_PREP(ADPA_CRT_HOTPLUG_VOLREF_MASK, 1)
#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER REG_BIT(16)
#define ADPA_USE_VGA_HVPOLARITY REG_BIT(15)
#define ADPA_HSYNC_CNTL_DISABLE REG_BIT(11)
#define ADPA_VSYNC_CNTL_DISABLE REG_BIT(10)
#define ADPA_VSYNC_ACTIVE_HIGH REG_BIT(4)
#define ADPA_HSYNC_ACTIVE_HIGH REG_BIT(3)
#define _VGA_MSR_WRITE _MMIO(0x3c2)
#endif /* __INTEL_CRT_REGS_H__ */

View File

@ -12,6 +12,7 @@
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_work.h>
#include "i915_drv.h"
#include "i915_vgpu.h"
#include "i9xx_plane.h"
#include "icl_dsi.h"

View File

@ -50,16 +50,6 @@ intel_dump_infoframe(struct drm_i915_private *i915,
hdmi_infoframe_log(KERN_DEBUG, i915->drm.dev, frame);
}
static void
intel_dump_buffer(const char *prefix, const u8 *buf, size_t len)
{
if (!drm_debug_enabled(DRM_UT_KMS))
return;
print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE,
16, 0, buf, len, false);
}
#define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x
static const char * const output_type_str[] = {
@ -293,8 +283,8 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
drm_dp_as_sdp_log(&p, &pipe_config->infoframes.as_sdp);
if (pipe_config->has_audio)
intel_dump_buffer("ELD: ", pipe_config->eld,
drm_eld_size(pipe_config->eld));
drm_print_hex_dump(&p, "ELD: ", pipe_config->eld,
drm_eld_size(pipe_config->eld));
drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n",
str_yes_no(pipe_config->vrr.enable),

View File

@ -11,6 +11,7 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
@ -619,7 +620,6 @@ static void skl_write_cursor_wm(struct intel_dsb *dsb,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(plane->base.dev);
struct drm_i915_private *i915 = to_i915(plane->base.dev);
enum plane_id plane_id = plane->id;
enum pipe pipe = plane->pipe;
const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
@ -627,14 +627,14 @@ static void skl_write_cursor_wm(struct intel_dsb *dsb,
&crtc_state->wm.skl.plane_ddb[plane_id];
int level;
for (level = 0; level < i915->display.wm.num_levels; level++)
for (level = 0; level < display->wm.num_levels; level++)
intel_de_write_dsb(display, dsb, CUR_WM(pipe, level),
skl_cursor_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
intel_de_write_dsb(display, dsb, CUR_WM_TRANS(pipe),
skl_cursor_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
if (HAS_HW_SAGV_WM(i915)) {
if (HAS_HW_SAGV_WM(display)) {
const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
intel_de_write_dsb(display, dsb, CUR_WM_SAGV(pipe),

View File

@ -5,6 +5,8 @@
#include <linux/log2.h>
#include <linux/math64.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_cx0_phy.h"
#include "intel_cx0_phy_regs.h"
@ -2115,14 +2117,6 @@ static void intel_c10_pll_program(struct intel_display *display,
0, C10_VDR_CTRL_MSGBUS_ACCESS,
MB_WRITE_COMMITTED);
/* Custom width needs to be programmed to 0 for both the phy lanes */
intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH,
C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10,
MB_WRITE_COMMITTED);
intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
0, C10_VDR_CTRL_UPDATE_CFG,
MB_WRITE_COMMITTED);
/* Program the pll values only for the master lane */
for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_PLL(i),
@ -2132,6 +2126,10 @@ static void intel_c10_pll_program(struct intel_display *display,
intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CMN(0), pll_state->cmn, MB_WRITE_COMMITTED);
intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_TX(0), pll_state->tx, MB_WRITE_COMMITTED);
/* Custom width needs to be programmed to 0 for both the phy lanes */
intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH,
C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10,
MB_WRITE_COMMITTED);
intel_cx0_rmw(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1),
0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG,
MB_WRITE_COMMITTED);
@ -2987,7 +2985,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder,
struct intel_display *display = to_intel_display(encoder);
enum phy phy = intel_encoder_to_phy(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
bool lane_reversal = dig_port->lane_reversal;
u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 :
INTEL_CX0_LANE0;
intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder);

View File

@ -9,6 +9,11 @@
#include "i915_reg_defs.h"
#include "intel_display_limits.h"
/* DDI Buffer Control */
#define _DDI_CLK_VALFREQ_A 0x64030
#define _DDI_CLK_VALFREQ_B 0x64130
#define DDI_CLK_VALFREQ(port) _MMIO_PORT(port, _DDI_CLK_VALFREQ_A, _DDI_CLK_VALFREQ_B)
/*
* Wrapper macro to convert from port number to the index used in some of the
* registers. For Display version 20 and above it converts the port number to a

View File

@ -335,10 +335,14 @@ static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
/* DDI_BUF_CTL_ENABLE will be set by intel_ddi_prepare_link_retrain() later */
intel_dp->DP = dig_port->saved_port_bits |
DDI_PORT_WIDTH(crtc_state->lane_count) |
intel_dp->DP = DDI_PORT_WIDTH(crtc_state->lane_count) |
DDI_BUF_TRANS_SELECT(0);
if (dig_port->lane_reversal)
intel_dp->DP |= DDI_BUF_PORT_REVERSAL;
if (dig_port->ddi_a_4_lanes)
intel_dp->DP |= DDI_A_4_LANES;
if (DISPLAY_VER(i915) >= 14) {
if (intel_dp_is_uhbr(crtc_state))
intel_dp->DP |= DDI_BUF_PORT_DATA_40BIT;
@ -455,17 +459,20 @@ static u32 bdw_trans_port_sync_master_select(enum transcoder master_transcoder)
}
static void
intel_ddi_config_transcoder_dp2(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
intel_ddi_config_transcoder_dp2(const struct intel_crtc_state *crtc_state,
bool enable)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(crtc_state);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 val = 0;
if (intel_dp_is_uhbr(crtc_state))
if (!HAS_DP20(display))
return;
if (enable && intel_dp_is_uhbr(crtc_state))
val = TRANS_DP2_128B132B_CHANNEL_CODING;
intel_de_write(i915, TRANS_DP2_CTL(cpu_transcoder), val);
intel_de_write(display, TRANS_DP2_CTL(cpu_transcoder), val);
}
/*
@ -617,9 +624,10 @@ void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
/*
* Same as intel_ddi_enable_transcoder_func(), but it does not set the enable
* bit.
* bit for the DDI function and enables the DP2 configuration. Called for all
* transcoder types.
*/
static void
void
intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
@ -628,12 +636,20 @@ intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 ctl;
intel_ddi_config_transcoder_dp2(crtc_state, true);
ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state);
ctl &= ~TRANS_DDI_FUNC_ENABLE;
intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
ctl);
}
/*
* Disable the DDI function and port syncing.
* For SST, pre-TGL MST, TGL+ MST-slave transcoders: deselect the DDI port,
* SST/MST mode and disable the DP2 configuration. For TGL+ MST-master
* transcoders these are done later in intel_ddi_post_disable_dp().
*/
void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(crtc_state);
@ -670,6 +686,9 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
ctl);
if (intel_dp_mst_is_slave_trans(crtc_state))
intel_ddi_config_transcoder_dp2(crtc_state, false);
if (intel_has_quirk(display, QUIRK_INCREASE_DDI_DISABLED_TIME) &&
intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
drm_dbg_kms(display->drm, "Quirk Increase DDI disabled time\n");
@ -700,15 +719,15 @@ int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
{
struct drm_device *dev = intel_connector->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = to_intel_display(intel_connector);
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
int type = intel_connector->base.connector_type;
enum port port = encoder->port;
enum transcoder cpu_transcoder;
intel_wakeref_t wakeref;
enum pipe pipe = 0;
u32 tmp;
u32 ddi_mode;
bool ret;
wakeref = intel_display_power_get_if_enabled(dev_priv,
@ -716,6 +735,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
if (!wakeref)
return false;
/* Note: This returns false for DP MST primary encoders. */
if (!encoder->get_hw_state(encoder, &pipe)) {
ret = false;
goto out;
@ -726,38 +746,28 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
else
cpu_transcoder = (enum transcoder) pipe;
tmp = intel_de_read(dev_priv,
TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
ddi_mode = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)) &
TRANS_DDI_MODE_SELECT_MASK;
switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
case TRANS_DDI_MODE_SELECT_HDMI:
case TRANS_DDI_MODE_SELECT_DVI:
if (ddi_mode == TRANS_DDI_MODE_SELECT_HDMI ||
ddi_mode == TRANS_DDI_MODE_SELECT_DVI) {
ret = type == DRM_MODE_CONNECTOR_HDMIA;
break;
case TRANS_DDI_MODE_SELECT_DP_SST:
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && !HAS_DP20(display)) {
ret = type == DRM_MODE_CONNECTOR_VGA;
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_SST) {
ret = type == DRM_MODE_CONNECTOR_eDP ||
type == DRM_MODE_CONNECTOR_DisplayPort;
break;
case TRANS_DDI_MODE_SELECT_DP_MST:
/* if the transcoder is in MST state then
* connector isn't connected */
type == DRM_MODE_CONNECTOR_DisplayPort;
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display)) {
/*
* encoder->get_hw_state() should have bailed out on MST. This
* must be SST and non-eDP.
*/
ret = type == DRM_MODE_CONNECTOR_DisplayPort;
} else if (drm_WARN_ON(display->drm, ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST)) {
/* encoder->get_hw_state() should have bailed out on MST. */
ret = false;
break;
case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
if (HAS_DP20(dev_priv))
/* 128b/132b */
ret = false;
else
/* FDI */
ret = type == DRM_MODE_CONNECTOR_VGA;
break;
default:
} else {
ret = false;
break;
}
out:
@ -769,8 +779,8 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
u8 *pipe_mask, bool *is_dp_mst)
{
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(display->drm);
enum port port = encoder->port;
intel_wakeref_t wakeref;
enum pipe p;
@ -815,7 +825,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
mst_pipe_mask = 0;
for_each_pipe(dev_priv, p) {
enum transcoder cpu_transcoder = (enum transcoder)p;
unsigned int port_mask, ddi_select;
u32 port_mask, ddi_select, ddi_mode;
intel_wakeref_t trans_wakeref;
trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
@ -839,9 +849,10 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
if ((tmp & port_mask) != ddi_select)
continue;
if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST ||
(HAS_DP20(dev_priv) &&
(tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B))
ddi_mode = tmp & TRANS_DDI_MODE_SELECT_MASK;
if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST ||
(ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display)))
mst_pipe_mask |= BIT(p);
*pipe_mask |= BIT(p);
@ -2196,8 +2207,8 @@ i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
return DP_TP_CTL(encoder->port);
}
i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
static i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@ -2208,6 +2219,25 @@ i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
return DP_TP_STATUS(encoder->port);
}
void intel_ddi_clear_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
intel_de_write(display, dp_tp_status_reg(encoder, crtc_state),
DP_TP_STATUS_ACT_SENT);
}
void intel_ddi_wait_for_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
if (intel_de_wait_for_set(display, dp_tp_status_reg(encoder, crtc_state),
DP_TP_STATUS_ACT_SENT, 1))
drm_err(display->drm, "Timed out waiting for ACT sent\n");
}
static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
bool enable)
@ -2376,12 +2406,10 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
if (intel_encoder_is_combo(encoder)) {
enum phy phy = intel_encoder_to_phy(encoder);
bool lane_reversal =
dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
intel_combo_phy_power_up_lanes(i915, phy, false,
crtc_state->lane_count,
lane_reversal);
dig_port->lane_reversal);
}
}
@ -2521,7 +2549,7 @@ static void mtl_port_buf_ctl_program(struct intel_encoder *encoder,
else
val |= XELPDP_PORT_BUF_PORT_DATA_10BIT;
if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
if (dig_port->lane_reversal)
val |= XELPDP_PORT_REVERSAL;
intel_de_write(i915, XELPDP_PORT_BUF_CTL1(i915, port), val);
@ -2583,10 +2611,6 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
/*
* 6.b If DP v2.0/128b mode - Configure TRANS_DP2_CTL register settings.
*/
intel_ddi_config_transcoder_dp2(encoder, crtc_state);
/*
* 6.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
* Transport Select
*/
@ -2721,9 +2745,6 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
*/
intel_ddi_enable_transcoder_clock(encoder, crtc_state);
if (HAS_DP20(dev_priv))
intel_ddi_config_transcoder_dp2(encoder, crtc_state);
/*
* 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
* Transport Select
@ -2862,9 +2883,9 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_display *display = to_intel_display(encoder);
if (HAS_DP20(dev_priv))
if (HAS_DP20(display))
intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
crtc_state);
@ -2872,9 +2893,9 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
if (crtc_state->has_panel_replay)
intel_psr_enable_sink(enc_to_intel_dp(encoder), crtc_state);
if (DISPLAY_VER(dev_priv) >= 14)
if (DISPLAY_VER(display) >= 14)
mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
else if (DISPLAY_VER(dev_priv) >= 12)
else if (DISPLAY_VER(display) >= 12)
tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
else
hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
@ -2911,6 +2932,24 @@ static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
crtc_state, conn_state);
}
/*
* Note: Also called from the ->pre_enable of the first active MST stream
* encoder on its primary encoder.
*
* When called from DP MST code:
*
* - conn_state will be NULL
*
* - encoder will be the primary encoder (i.e. mst->primary)
*
* - the main connector associated with this port won't be active or linked to a
* crtc
*
* - crtc_state will be the state of the first stream to be activated on this
* port, and it may not be the same stream that will be deactivated last, but
* each stream should have a state that is identical when it comes to the DP
* link parameteres
*/
static void intel_ddi_pre_enable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
@ -2920,19 +2959,6 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state,
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
/*
* When called from DP MST code:
* - conn_state will be NULL
* - encoder will be the main encoder (ie. mst->primary)
* - the main connector associated with this port
* won't be active or linked to a crtc
* - crtc_state will be the state of the first stream to
* be activated on this port, and it may not be the same
* stream that will be deactivated last, but each stream
* should have a state that is identical when it comes to
* the DP link parameteres
*/
drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder);
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
@ -3088,6 +3114,8 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
intel_dp_sink_set_fec_ready(intel_dp, old_crtc_state, false);
intel_ddi_config_transcoder_dp2(old_crtc_state, false);
/*
* From TGL spec: "If single stream or multi-stream master transcoder:
* Configure Transcoder Clock select to direct no clock to the
@ -3180,6 +3208,11 @@ static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
}
}
/*
* Note: Also called from the ->post_disable of the last active MST stream
* encoder on its primary encoder. See also the comment for
* intel_ddi_pre_enable().
*/
static void intel_ddi_post_disable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
@ -3210,6 +3243,11 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
old_conn_state);
}
/*
* Note: Also called from the ->post_pll_disable of the last active MST stream
* encoder on its primary encoder. See also the comment for
* intel_ddi_pre_enable().
*/
static void intel_ddi_post_pll_disable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
@ -3260,7 +3298,7 @@ static void trans_port_sync_stop_link_train(struct intel_atomic_state *state,
crtc_state);
}
static void intel_enable_ddi_dp(struct intel_atomic_state *state,
static void intel_ddi_enable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
@ -3282,18 +3320,8 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
trans_port_sync_stop_link_train(state, encoder, crtc_state);
}
/* FIXME bad home for this function */
i915_reg_t hsw_chicken_trans_reg(struct drm_i915_private *i915,
enum transcoder cpu_transcoder)
{
return DISPLAY_VER(i915) >= 14 ?
MTL_CHICKEN_TRANS(cpu_transcoder) :
CHICKEN_TRANS(cpu_transcoder);
}
static i915_reg_t
gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
enum port port)
gen9_chicken_trans_reg_by_port(struct intel_display *display, enum port port)
{
static const enum transcoder trans[] = {
[PORT_A] = TRANSCODER_EDP,
@ -3303,19 +3331,20 @@ gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
[PORT_E] = TRANSCODER_A,
};
drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) < 9);
drm_WARN_ON(display->drm, DISPLAY_VER(display) < 9);
if (drm_WARN_ON(&dev_priv->drm, port < PORT_A || port > PORT_E))
if (drm_WARN_ON(display->drm, port < PORT_A || port > PORT_E))
port = PORT_A;
return CHICKEN_TRANS(trans[port]);
return CHICKEN_TRANS(display, trans[port]);
}
static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
static void intel_ddi_enable_hdmi(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_connector *connector = conn_state->connector;
@ -3346,7 +3375,7 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
* the bits affect a specific DDI port rather than
* a specific transcoder.
*/
i915_reg_t reg = gen9_chicken_trans_reg_by_port(dev_priv, port);
i915_reg_t reg = gen9_chicken_trans_reg_by_port(display, port);
u32 val;
val = intel_de_read(dev_priv, reg);
@ -3386,14 +3415,20 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
* is filled with lane count, already set in the crtc_state.
* The same is required to be filled in PORT_BUF_CTL for C10/20 Phy.
*/
buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
buf_ctl = DDI_BUF_CTL_ENABLE;
if (dig_port->lane_reversal)
buf_ctl |= DDI_BUF_PORT_REVERSAL;
if (dig_port->ddi_a_4_lanes)
buf_ctl |= DDI_A_4_LANES;
if (DISPLAY_VER(dev_priv) >= 14) {
u8 lane_count = mtl_get_port_width(crtc_state->lane_count);
u32 port_buf = 0;
port_buf |= XELPDP_PORT_WIDTH(lane_count);
if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
if (dig_port->lane_reversal)
port_buf |= XELPDP_PORT_REVERSAL;
intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(dev_priv, port),
@ -3413,7 +3448,7 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
intel_wait_ddi_buf_active(encoder);
}
static void intel_enable_ddi(struct intel_atomic_state *state,
static void intel_ddi_enable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
@ -3439,15 +3474,15 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
}
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state);
intel_ddi_enable_hdmi(state, encoder, crtc_state, conn_state);
else
intel_enable_ddi_dp(state, encoder, crtc_state, conn_state);
intel_ddi_enable_dp(state, encoder, crtc_state, conn_state);
intel_hdcp_enable(state, encoder, crtc_state, conn_state);
}
static void intel_disable_ddi_dp(struct intel_atomic_state *state,
static void intel_ddi_disable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
@ -3468,7 +3503,7 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state,
false);
}
static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
static void intel_ddi_disable_hdmi(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
@ -3483,7 +3518,7 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
connector->base.id, connector->name);
}
static void intel_disable_ddi(struct intel_atomic_state *state,
static void intel_ddi_disable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
@ -3493,10 +3528,10 @@ static void intel_disable_ddi(struct intel_atomic_state *state,
intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
intel_disable_ddi_hdmi(state, encoder, old_crtc_state,
intel_ddi_disable_hdmi(state, encoder, old_crtc_state,
old_conn_state);
else
intel_disable_ddi_dp(state, encoder, old_crtc_state,
intel_ddi_disable_dp(state, encoder, old_crtc_state,
old_conn_state);
}
@ -3556,6 +3591,11 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
intel_update_active_dpll(state, pipe_crtc, encoder);
}
/*
* Note: Also called from the ->pre_pll_enable of the first active MST stream
* encoder on its primary encoder. See also the comment for
* intel_ddi_pre_enable().
*/
static void
intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
struct intel_encoder *encoder,
@ -3868,29 +3908,136 @@ static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
crtc_state->sync_mode_slaves_mask);
}
static void intel_ddi_read_func_ctl_dvi(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
crtc_state->output_types |= BIT(INTEL_OUTPUT_HDMI);
if (DISPLAY_VER(display) >= 14)
crtc_state->lane_count =
((ddi_func_ctl & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
else
crtc_state->lane_count = 4;
}
static void intel_ddi_read_func_ctl_hdmi(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
crtc_state->has_hdmi_sink = true;
crtc_state->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, crtc_state);
if (crtc_state->infoframes.enable)
crtc_state->has_infoframe = true;
if (ddi_func_ctl & TRANS_DDI_HDMI_SCRAMBLING)
crtc_state->hdmi_scrambling = true;
if (ddi_func_ctl & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
crtc_state->hdmi_high_tmds_clock_ratio = true;
intel_ddi_read_func_ctl_dvi(encoder, crtc_state, ddi_func_ctl);
}
static void intel_ddi_read_func_ctl_fdi(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
crtc_state->output_types |= BIT(INTEL_OUTPUT_ANALOG);
crtc_state->enhanced_framing =
intel_de_read(display, dp_tp_ctl_reg(encoder, crtc_state)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
}
static void intel_ddi_read_func_ctl_dp_sst(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
if (encoder->type == INTEL_OUTPUT_EDP)
crtc_state->output_types |= BIT(INTEL_OUTPUT_EDP);
else
crtc_state->output_types |= BIT(INTEL_OUTPUT_DP);
crtc_state->lane_count =
((ddi_func_ctl & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder, &crtc_state->dp_m_n);
intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder, &crtc_state->dp_m2_n2);
crtc_state->enhanced_framing =
intel_de_read(display, dp_tp_ctl_reg(encoder, crtc_state)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
if (DISPLAY_VER(display) >= 11)
crtc_state->fec_enable =
intel_de_read(display,
dp_tp_ctl_reg(encoder, crtc_state)) & DP_TP_CTL_FEC_ENABLE;
if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
crtc_state->infoframes.enable |=
intel_lspcon_infoframes_enabled(encoder, crtc_state);
else
crtc_state->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, crtc_state);
}
static void intel_ddi_read_func_ctl_dp_mst(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
u32 ddi_func_ctl)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
crtc_state->output_types |= BIT(INTEL_OUTPUT_DP_MST);
crtc_state->lane_count =
((ddi_func_ctl & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
if (DISPLAY_VER(display) >= 12)
crtc_state->mst_master_transcoder =
REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, ddi_func_ctl);
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder, &crtc_state->dp_m_n);
if (DISPLAY_VER(display) >= 11)
crtc_state->fec_enable =
intel_de_read(display,
dp_tp_ctl_reg(encoder, crtc_state)) & DP_TP_CTL_FEC_ENABLE;
crtc_state->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, crtc_state);
}
static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct intel_display *display = to_intel_display(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
u32 temp, flags = 0;
u32 ddi_func_ctl, ddi_mode, flags = 0;
temp = intel_de_read(dev_priv,
TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
if (temp & TRANS_DDI_PHSYNC)
ddi_func_ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
if (ddi_func_ctl & TRANS_DDI_PHSYNC)
flags |= DRM_MODE_FLAG_PHSYNC;
else
flags |= DRM_MODE_FLAG_NHSYNC;
if (temp & TRANS_DDI_PVSYNC)
if (ddi_func_ctl & TRANS_DDI_PVSYNC)
flags |= DRM_MODE_FLAG_PVSYNC;
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->hw.adjusted_mode.flags |= flags;
switch (temp & TRANS_DDI_BPC_MASK) {
switch (ddi_func_ctl & TRANS_DDI_BPC_MASK) {
case TRANS_DDI_BPC_6:
pipe_config->pipe_bpp = 18;
break;
@ -3907,93 +4054,27 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
break;
}
switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
case TRANS_DDI_MODE_SELECT_HDMI:
pipe_config->has_hdmi_sink = true;
ddi_mode = ddi_func_ctl & TRANS_DDI_MODE_SELECT_MASK;
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
if (pipe_config->infoframes.enable)
pipe_config->has_infoframe = true;
if (temp & TRANS_DDI_HDMI_SCRAMBLING)
pipe_config->hdmi_scrambling = true;
if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
pipe_config->hdmi_high_tmds_clock_ratio = true;
fallthrough;
case TRANS_DDI_MODE_SELECT_DVI:
pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
if (DISPLAY_VER(dev_priv) >= 14)
pipe_config->lane_count =
((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
else
pipe_config->lane_count = 4;
break;
case TRANS_DDI_MODE_SELECT_DP_SST:
if (encoder->type == INTEL_OUTPUT_EDP)
pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP);
else
pipe_config->output_types |= BIT(INTEL_OUTPUT_DP);
pipe_config->lane_count =
((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
&pipe_config->dp_m_n);
intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
&pipe_config->dp_m2_n2);
pipe_config->enhanced_framing =
intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
if (DISPLAY_VER(dev_priv) >= 11)
pipe_config->fec_enable =
intel_de_read(dev_priv,
dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
pipe_config->infoframes.enable |=
intel_lspcon_infoframes_enabled(encoder, pipe_config);
else
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
break;
case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
if (!HAS_DP20(dev_priv)) {
/* FDI */
pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
pipe_config->enhanced_framing =
intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
DP_TP_CTL_ENHANCED_FRAME_ENABLE;
break;
}
fallthrough; /* 128b/132b */
case TRANS_DDI_MODE_SELECT_DP_MST:
pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
pipe_config->lane_count =
((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
if (DISPLAY_VER(dev_priv) >= 12)
pipe_config->mst_master_transcoder =
REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
&pipe_config->dp_m_n);
if (DISPLAY_VER(dev_priv) >= 11)
pipe_config->fec_enable =
intel_de_read(dev_priv,
dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
break;
default:
break;
if (ddi_mode == TRANS_DDI_MODE_SELECT_HDMI) {
intel_ddi_read_func_ctl_hdmi(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DVI) {
intel_ddi_read_func_ctl_dvi(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && !HAS_DP20(display)) {
intel_ddi_read_func_ctl_fdi(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_SST) {
intel_ddi_read_func_ctl_dp_sst(encoder, pipe_config, ddi_func_ctl);
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST ||
(ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display))) {
intel_ddi_read_func_ctl_dp_mst(encoder, pipe_config, ddi_func_ctl);
}
}
/*
* Note: Also called from the ->get_config of the MST stream encoders on their
* primary encoder, via the platform specific hooks here. See also the comment
* for intel_ddi_pre_enable().
*/
static void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
@ -4690,7 +4771,7 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
if (dig_port->base.port != PORT_A)
return false;
if (dig_port->saved_port_bits & DDI_A_4_LANES)
if (dig_port->ddi_a_4_lanes)
return false;
/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
@ -4728,7 +4809,7 @@ intel_ddi_max_lanes(struct intel_digital_port *dig_port)
if (intel_ddi_a_force_4_lanes(dig_port)) {
drm_dbg_kms(&dev_priv->drm,
"Forcing DDI_A_4_LANES for port A\n");
dig_port->saved_port_bits |= DDI_A_4_LANES;
dig_port->ddi_a_4_lanes = true;
max_lanes = 4;
}
@ -4907,6 +4988,7 @@ void intel_ddi_init(struct intel_display *display,
bool init_hdmi, init_dp;
enum port port;
enum phy phy;
u32 ddi_buf_ctl;
port = intel_bios_encoder_port(devdata);
if (port == PORT_NONE)
@ -5030,10 +5112,10 @@ void intel_ddi_init(struct intel_display *display,
encoder->compute_output_type = intel_ddi_compute_output_type;
encoder->compute_config = intel_ddi_compute_config;
encoder->compute_config_late = intel_ddi_compute_config_late;
encoder->enable = intel_enable_ddi;
encoder->enable = intel_ddi_enable;
encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
encoder->pre_enable = intel_ddi_pre_enable;
encoder->disable = intel_disable_ddi;
encoder->disable = intel_ddi_disable;
encoder->post_pll_disable = intel_ddi_post_pll_disable;
encoder->post_disable = intel_ddi_post_disable;
encoder->update_pipe = intel_ddi_update_pipe;
@ -5156,17 +5238,12 @@ void intel_ddi_init(struct intel_display *display,
else
encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
if (DISPLAY_VER(dev_priv) >= 11)
dig_port->saved_port_bits =
intel_de_read(dev_priv, DDI_BUF_CTL(port))
& DDI_BUF_PORT_REVERSAL;
else
dig_port->saved_port_bits =
intel_de_read(dev_priv, DDI_BUF_CTL(port))
& (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES);
ddi_buf_ctl = intel_de_read(dev_priv, DDI_BUF_CTL(port));
if (intel_bios_encoder_lane_reversal(devdata))
dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL;
dig_port->lane_reversal = intel_bios_encoder_lane_reversal(devdata) ||
ddi_buf_ctl & DDI_BUF_PORT_REVERSAL;
dig_port->ddi_a_4_lanes = DISPLAY_VER(dev_priv) < 11 && ddi_buf_ctl & DDI_A_4_LANES;
dig_port->dp.output_reg = INVALID_MMIO_REG;
dig_port->max_lanes = intel_ddi_max_lanes(dig_port);

View File

@ -26,10 +26,12 @@ enum transcoder;
i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
i915_reg_t hsw_chicken_trans_reg(struct drm_i915_private *i915,
enum transcoder cpu_transcoder);
void intel_ddi_clear_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_wait_for_act_sent(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_fdi_post_disable(struct intel_atomic_state *state,
struct intel_encoder *intel_encoder,
const struct intel_crtc_state *old_crtc_state,
@ -57,6 +59,8 @@ void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
void intel_ddi_init(struct intel_display *display,
const struct intel_bios_encoder_data *devdata);
bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
void intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state);

View File

@ -1687,18 +1687,24 @@ dg2_get_snps_buf_trans(struct intel_encoder *encoder,
}
static const struct intel_ddi_buf_trans *
mtl_get_cx0_buf_trans(struct intel_encoder *encoder,
mtl_get_c10_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock >= 1000000)
return intel_get_buf_trans(&mtl_c10_trans_dp14, n_entries);
}
static const struct intel_ddi_buf_trans *
mtl_get_c20_buf_trans(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
int *n_entries)
{
if (intel_crtc_has_dp_encoder(crtc_state) && intel_dp_is_uhbr(crtc_state))
return intel_get_buf_trans(&mtl_c20_trans_uhbr, n_entries);
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !(intel_encoder_is_c10phy(encoder)))
else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
return intel_get_buf_trans(&mtl_c20_trans_hdmi, n_entries);
else if (!intel_encoder_is_c10phy(encoder))
return intel_get_buf_trans(&mtl_c20_trans_dp14, n_entries);
else
return intel_get_buf_trans(&mtl_c10_trans_dp14, n_entries);
return intel_get_buf_trans(&mtl_c20_trans_dp14, n_entries);
}
void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
@ -1706,7 +1712,10 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
if (DISPLAY_VER(i915) >= 14) {
encoder->get_buf_trans = mtl_get_cx0_buf_trans;
if (intel_encoder_is_c10phy(encoder))
encoder->get_buf_trans = mtl_get_c10_buf_trans;
else
encoder->get_buf_trans = mtl_get_c20_buf_trans;
} else if (IS_DG2(i915)) {
encoder->get_buf_trans = dg2_get_snps_buf_trans;
} else if (IS_ALDERLAKE_P(i915)) {

View File

@ -6,14 +6,16 @@
#ifndef __INTEL_DE_H__
#define __INTEL_DE_H__
#include "i915_drv.h"
#include "i915_trace.h"
#include "intel_display_conversion.h"
#include "intel_display_core.h"
#include "intel_dmc_wl.h"
#include "intel_dsb.h"
#include "intel_uncore.h"
#include "intel_uncore_trace.h"
static inline struct intel_uncore *__to_uncore(struct intel_display *display)
{
return &to_i915(display->drm)->uncore;
return to_intel_uncore(display->drm);
}
static inline u32
@ -117,6 +119,16 @@ __intel_de_wait_for_register_nowl(struct intel_display *display,
value, timeout);
}
static inline int
__intel_de_wait_for_register_atomic_nowl(struct intel_display *display,
i915_reg_t reg,
u32 mask, u32 value,
unsigned int fast_timeout_us)
{
return __intel_wait_for_register(__to_uncore(display), reg, mask,
value, fast_timeout_us, 0, NULL);
}
static inline int
intel_de_wait(struct intel_display *display, i915_reg_t reg,
u32 mask, u32 value, unsigned int timeout)

View File

@ -511,6 +511,7 @@ void vlv_wait_port_ready(struct intel_display *display,
void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
{
struct intel_display *display = to_intel_display(new_crtc_state);
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
@ -554,8 +555,7 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
if (DISPLAY_VER(dev_priv) == 14)
set |= DP_FEC_BS_JITTER_WA;
intel_de_rmw(dev_priv,
hsw_chicken_trans_reg(dev_priv, cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, cpu_transcoder),
clear, set);
}
@ -591,6 +591,7 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state)
void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state)
{
struct intel_display *display = to_intel_display(old_crtc_state);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
@ -628,7 +629,7 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state)
intel_de_write(dev_priv, TRANSCONF(dev_priv, cpu_transcoder), val);
if (DISPLAY_VER(dev_priv) >= 12)
intel_de_rmw(dev_priv, hsw_chicken_trans_reg(dev_priv, cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, cpu_transcoder),
FECSTALL_DIS_DPTSTREAM_DPTTG, 0);
if ((val & TRANSCONF_ENABLE) == 0)
@ -1744,10 +1745,9 @@ static void hsw_set_linetime_wm(const struct intel_crtc_state *crtc_state)
static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_display *display = to_intel_display(crtc_state);
intel_de_rmw(i915, hsw_chicken_trans_reg(i915, crtc_state->cpu_transcoder),
intel_de_rmw(display, CHICKEN_TRANS(display, crtc_state->cpu_transcoder),
HSW_FRAME_START_DELAY_MASK,
HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1));
}
@ -2371,7 +2371,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
/* GDG double wide on either pipe, otherwise pipe A only */
return DISPLAY_VER(dev_priv) < 4 &&
return HAS_DOUBLE_WIDE(dev_priv) &&
(crtc->pipe == PIPE_A || IS_I915G(dev_priv));
}
@ -3137,9 +3137,14 @@ bdw_get_pipe_misc_output_format(struct intel_crtc *crtc)
tmp = intel_de_read(dev_priv, PIPE_MISC(crtc->pipe));
if (tmp & PIPE_MISC_YUV420_ENABLE) {
/* We support 4:2:0 in full blend mode only */
drm_WARN_ON(&dev_priv->drm,
(tmp & PIPE_MISC_YUV420_MODE_FULL_BLEND) == 0);
/*
* We support 4:2:0 in full blend mode only.
* For xe3_lpd+ this is implied in YUV420 Enable bit.
* Ensure the same for prior platforms in YUV420 Mode bit.
*/
if (DISPLAY_VER(dev_priv) < 30)
drm_WARN_ON(&dev_priv->drm,
(tmp & PIPE_MISC_YUV420_MODE_FULL_BLEND) == 0);
return INTEL_OUTPUT_FORMAT_YCBCR420;
} else if (tmp & PIPE_MISC_OUTPUT_COLORSPACE_YUV) {
@ -3207,7 +3212,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
intel_color_get_config(pipe_config);
if (DISPLAY_VER(dev_priv) < 4)
if (HAS_DOUBLE_WIDE(dev_priv))
pipe_config->double_wide = tmp & TRANSCONF_DOUBLE_WIDE;
intel_get_transcoder_timings(crtc, pipe_config);
@ -3388,8 +3393,8 @@ static void bdw_set_pipe_misc(struct intel_dsb *dsb,
val |= PIPE_MISC_OUTPUT_COLORSPACE_YUV;
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
val |= PIPE_MISC_YUV420_ENABLE |
PIPE_MISC_YUV420_MODE_FULL_BLEND;
val |= DISPLAY_VER(display) >= 30 ? PIPE_MISC_YUV420_ENABLE :
PIPE_MISC_YUV420_ENABLE | PIPE_MISC_YUV420_MODE_FULL_BLEND;
if (DISPLAY_VER(dev_priv) >= 11 && is_hdr_mode(crtc_state))
val |= PIPE_MISC_HDR_MODE_PRECISION;
@ -3746,12 +3751,13 @@ static u8 fixup_ultrajoiner_secondary_pipes(u8 ultrajoiner_primary_pipes,
static void enabled_ultrajoiner_pipes(struct drm_i915_private *i915,
u8 *primary_pipes, u8 *secondary_pipes)
{
struct intel_display *display = &i915->display;
struct intel_crtc *crtc;
*primary_pipes = 0;
*secondary_pipes = 0;
if (!HAS_ULTRAJOINER(i915))
if (!HAS_ULTRAJOINER(display))
return;
for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc,
@ -4111,6 +4117,7 @@ static void intel_joiner_get_config(struct intel_crtc_state *crtc_state)
static bool hsw_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
bool active;
u32 tmp;
@ -4187,7 +4194,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
}
if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) {
tmp = intel_de_read(dev_priv, hsw_chicken_trans_reg(dev_priv, pipe_config->cpu_transcoder));
tmp = intel_de_read(display, CHICKEN_TRANS(display, pipe_config->cpu_transcoder));
pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1;
} else {
@ -4545,6 +4552,7 @@ static int hsw_compute_linetime_wm(struct intel_atomic_state *state,
static int intel_crtc_atomic_check(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
struct intel_display *display = to_intel_display(crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
@ -4581,12 +4589,12 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
return ret;
}
ret = intel_atomic_setup_scalers(dev_priv, crtc, crtc_state);
ret = intel_atomic_setup_scalers(state, crtc);
if (ret)
return ret;
}
if (HAS_IPS(dev_priv)) {
if (HAS_IPS(display)) {
ret = hsw_ips_compute_config(state, crtc);
if (ret)
return ret;
@ -5208,7 +5216,7 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_printer *p, bool fastset,
const struct drm_dp_vsc_sdp *a,
const struct drm_dp_vsc_sdp *b)
{
pipe_config_mismatch(p, fastset, crtc, name, "dp sdp");
pipe_config_mismatch(p, fastset, crtc, name, "dp vsc sdp");
drm_printf(p, "expected:\n");
drm_dp_vsc_sdp_log(p, a);
@ -5217,27 +5225,18 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_printer *p, bool fastset,
}
static void
pipe_config_dp_as_sdp_mismatch(struct drm_i915_private *i915,
bool fastset, const char *name,
pipe_config_dp_as_sdp_mismatch(struct drm_printer *p, bool fastset,
const struct intel_crtc *crtc,
const char *name,
const struct drm_dp_as_sdp *a,
const struct drm_dp_as_sdp *b)
{
struct drm_printer p;
pipe_config_mismatch(p, fastset, crtc, name, "dp as sdp");
if (fastset) {
p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, NULL);
drm_printf(&p, "fastset requirement not met in %s dp sdp\n", name);
} else {
p = drm_err_printer(&i915->drm, NULL);
drm_printf(&p, "mismatch in %s dp sdp\n", name);
}
drm_printf(&p, "expected:\n");
drm_dp_as_sdp_log(&p, a);
drm_printf(&p, "found:\n");
drm_dp_as_sdp_log(&p, b);
drm_printf(p, "expected:\n");
drm_dp_as_sdp_log(p, a);
drm_printf(p, "found:\n");
drm_dp_as_sdp_log(p, b);
}
/* Returns the length up to and including the last differing byte */
@ -5260,26 +5259,13 @@ pipe_config_buffer_mismatch(struct drm_printer *p, bool fastset,
const char *name,
const u8 *a, const u8 *b, size_t len)
{
const char *loglevel;
if (fastset) {
if (!drm_debug_enabled(DRM_UT_KMS))
return;
loglevel = KERN_DEBUG;
} else {
loglevel = KERN_ERR;
}
pipe_config_mismatch(p, fastset, crtc, name, "buffer");
/* only dump up to the last difference */
len = memcmp_diff_len(a, b, len);
print_hex_dump(loglevel, "expected: ", DUMP_PREFIX_NONE,
16, 0, a, len, false);
print_hex_dump(loglevel, "found: ", DUMP_PREFIX_NONE,
16, 0, b, len, false);
drm_print_hex_dump(p, "expected: ", a, len);
drm_print_hex_dump(p, "found: ", b, len);
}
static void
@ -5322,6 +5308,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
const struct intel_crtc_state *pipe_config,
bool fastset)
{
struct intel_display *display = to_intel_display(current_config);
struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct drm_printer p;
@ -5498,7 +5485,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
#define PIPE_CONF_CHECK_DP_AS_SDP(name) do { \
if (!intel_compare_dp_as_sdp(&current_config->infoframes.name, \
&pipe_config->infoframes.name)) { \
pipe_config_dp_as_sdp_mismatch(dev_priv, fastset, __stringify(name), \
pipe_config_dp_as_sdp_mismatch(&p, fastset, crtc, __stringify(name), \
&current_config->infoframes.name, \
&pipe_config->infoframes.name); \
ret = false; \
@ -5562,7 +5549,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(lane_count);
PIPE_CONF_CHECK_X(lane_lat_optim_mask);
if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) {
if (HAS_DOUBLE_BUFFERED_M_N(display)) {
if (!fastset || !pipe_config->update_m_n)
PIPE_CONF_CHECK_M_N(dp_m_n);
} else {
@ -5743,7 +5730,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(dsc.config.nsl_bpg_offset);
PIPE_CONF_CHECK_BOOL(dsc.compression_enable);
PIPE_CONF_CHECK_BOOL(dsc.dsc_split);
PIPE_CONF_CHECK_I(dsc.num_streams);
PIPE_CONF_CHECK_I(dsc.compressed_bpp_x16);
PIPE_CONF_CHECK_BOOL(splitter.enable);
@ -6797,6 +6784,7 @@ static int intel_atomic_check_config_and_link(struct intel_atomic_state *state)
int intel_atomic_check(struct drm_device *dev,
struct drm_atomic_state *_state)
{
struct intel_display *display = to_intel_display(dev);
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_atomic_state *state = to_intel_atomic_state(_state);
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
@ -6804,7 +6792,7 @@ int intel_atomic_check(struct drm_device *dev,
int ret, i;
bool any_ms = false;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return -ENODEV;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
@ -7572,7 +7560,7 @@ static void intel_atomic_dsb_cleanup(struct intel_crtc_state *crtc_state)
static void intel_atomic_cleanup_work(struct work_struct *work)
{
struct intel_atomic_state *state =
container_of(work, struct intel_atomic_state, base.commit_work);
container_of(work, struct intel_atomic_state, cleanup_work);
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc_state *old_crtc_state;
struct intel_crtc *crtc;
@ -7822,6 +7810,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
dev_priv->display.funcs.display->commit_modeset_enables(state);
intel_program_dpkgc_latency(state);
if (state->modeset)
intel_set_cdclk_post_plane_update(state);
@ -7927,8 +7917,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
* schedule point (cond_resched()) here anyway to keep latencies
* down.
*/
INIT_WORK(&state->base.commit_work, intel_atomic_cleanup_work);
queue_work(system_highpri_wq, &state->base.commit_work);
INIT_WORK(&state->cleanup_work, intel_atomic_cleanup_work);
queue_work(dev_priv->display.wq.cleanup, &state->cleanup_work);
}
static void intel_atomic_commit_work(struct work_struct *work)
@ -8166,7 +8156,7 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
intel_lvds_init(dev_priv);
intel_crt_init(display);
dpd_is_edp = intel_dp_is_port_edp(dev_priv, PORT_D);
dpd_is_edp = intel_dp_is_port_edp(display, PORT_D);
if (ilk_has_edp_a(dev_priv))
g4x_dp_init(dev_priv, DP_A, PORT_A);
@ -8212,14 +8202,14 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
* trust the port type the VBT declares as we've seen at least
* HDMI ports that the VBT claim are DP or eDP.
*/
has_edp = intel_dp_is_port_edp(dev_priv, PORT_B);
has_edp = intel_dp_is_port_edp(display, PORT_B);
has_port = intel_bios_is_port_present(display, PORT_B);
if (intel_de_read(dev_priv, VLV_DP_B) & DP_DETECTED || has_port)
has_edp &= g4x_dp_init(dev_priv, VLV_DP_B, PORT_B);
if ((intel_de_read(dev_priv, VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
g4x_hdmi_init(dev_priv, VLV_HDMIB, PORT_B);
has_edp = intel_dp_is_port_edp(dev_priv, PORT_C);
has_edp = intel_dp_is_port_edp(display, PORT_C);
has_port = intel_bios_is_port_present(display, PORT_C);
if (intel_de_read(dev_priv, VLV_DP_C) & DP_DETECTED || has_port)
has_edp &= g4x_dp_init(dev_priv, VLV_DP_C, PORT_C);
@ -8308,11 +8298,12 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv)
static int max_dotclock(struct drm_i915_private *i915)
{
int max_dotclock = i915->display.cdclk.max_dotclk_freq;
struct intel_display *display = &i915->display;
int max_dotclock = display->cdclk.max_dotclk_freq;
if (HAS_ULTRAJOINER(i915))
if (HAS_ULTRAJOINER(display))
max_dotclock *= 4;
else if (HAS_UNCOMPRESSED_JOINER(i915) || HAS_BIGJOINER(i915))
else if (HAS_UNCOMPRESSED_JOINER(display) || HAS_BIGJOINER(display))
max_dotclock *= 2;
return max_dotclock;

View File

@ -238,9 +238,6 @@ enum phy_fia {
for ((__phy) = PHY_A; (__phy) < I915_MAX_PHYS; (__phy)++) \
for_each_if((__phys_mask) & BIT(__phy))
#define for_each_crtc(dev, crtc) \
list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
#define for_each_intel_plane(dev, intel_plane) \
list_for_each_entry(intel_plane, \
&(dev)->mode_config.plane_list, \

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
/* Copyright © 2024 Intel Corporation */
#include "i915_drv.h"
struct intel_display *__i915_to_display(struct drm_i915_private *i915)
{
return &i915->display;
}
struct intel_display *__drm_to_display(struct drm_device *drm)
{
return __i915_to_display(to_i915(drm));
}

View File

@ -8,14 +8,20 @@
#ifndef __INTEL_DISPLAY_CONVERSION__
#define __INTEL_DISPLAY_CONVERSION__
struct drm_device;
struct drm_i915_private;
struct intel_display;
struct intel_display *__i915_to_display(struct drm_i915_private *i915);
struct intel_display *__drm_to_display(struct drm_device *drm);
/*
* Transitional macro to optionally convert struct drm_i915_private * to struct
* intel_display *, also accepting the latter.
*/
#define __to_intel_display(p) \
_Generic(p, \
const struct drm_i915_private *: (&((const struct drm_i915_private *)(p))->display), \
struct drm_i915_private *: (&((struct drm_i915_private *)(p))->display), \
const struct drm_i915_private *: __i915_to_display((struct drm_i915_private *)(p)), \
struct drm_i915_private *: __i915_to_display((struct drm_i915_private *)(p)), \
const struct intel_display *: (p), \
struct intel_display *: (p))

View File

@ -453,7 +453,14 @@ struct intel_display {
} ips;
struct {
bool display_irqs_enabled;
/*
* Most platforms treat the display irq block as an always-on
* power domain. vlv/chv can disable it at runtime and need
* special care to avoid writing any of the display block
* registers outside of the power domain. We defer setting up
* the display irqs in this case to the runtime pm.
*/
bool vlv_display_irqs_enabled;
/* For i915gm/i945gm vblank irq workaround */
u8 vblank_enabled;
@ -505,6 +512,11 @@ struct intel_display {
/* restore state for suspend/resume and display reset */
struct drm_atomic_state *modeset_state;
struct drm_modeset_acquire_ctx reset_ctx;
u32 saveDSPARB;
u32 saveSWF0[16];
u32 saveSWF1[16];
u32 saveSWF3[3];
u16 saveGCDGMBUS;
} restore;
struct {
@ -542,6 +554,9 @@ struct intel_display {
/* unbound hipri wq for page flips/plane updates */
struct workqueue_struct *flip;
/* hipri wq for commit cleanups */
struct workqueue_struct *cleanup;
} wq;
/* Grouping using named structs. Keep sorted. */

View File

@ -11,8 +11,10 @@
#include <drm/drm_fourcc.h>
#include "hsw_ips.h"
#include "i915_drv.h"
#include "i915_irq.h"
#include "i915_reg.h"
#include "i9xx_wm_regs.h"
#include "intel_alpm.h"
#include "intel_bo.h"
#include "intel_crtc.h"
@ -730,11 +732,12 @@ static bool
intel_lpsp_power_well_enabled(struct drm_i915_private *i915,
enum i915_power_well_id power_well_id)
{
struct intel_display *display = &i915->display;
intel_wakeref_t wakeref;
bool is_enabled;
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
is_enabled = intel_display_power_well_is_enabled(i915,
is_enabled = intel_display_power_well_is_enabled(display,
power_well_id);
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
@ -1012,6 +1015,8 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
DP_DSC_YCbCr444)));
seq_printf(m, "DSC_Sink_BPP_Precision: %d\n",
drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd));
seq_printf(m, "DSC_Sink_Max_Slice_Count: %d\n",
drm_dp_dsc_sink_max_slice_count((connector->dp.dsc_dpcd), intel_dp_is_edp(intel_dp)));
seq_printf(m, "Force_DSC_Enable: %s\n",
str_yes_no(intel_dp->force_dsc_en));
if (!intel_dp_is_edp(intel_dp))
@ -1331,7 +1336,7 @@ static ssize_t i915_joiner_write(struct file *file,
{
struct seq_file *m = file->private_data;
struct intel_connector *connector = m->private;
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_display *display = to_intel_display(connector);
int force_joined_pipes = 0;
int ret;
@ -1349,7 +1354,7 @@ static ssize_t i915_joiner_write(struct file *file,
connector->force_joined_pipes = force_joined_pipes;
break;
case 4:
if (HAS_ULTRAJOINER(i915)) {
if (HAS_ULTRAJOINER(display)) {
connector->force_joined_pipes = force_joined_pipes;
break;
}

View File

@ -7,9 +7,10 @@
#include <linux/kernel.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include "intel_display_core.h"
#include "intel_display_debugfs_params.h"
#include "i915_drv.h"
#include "intel_display_params.h"
/* int param */

View File

@ -16,6 +16,7 @@
#include "intel_display_params.h"
#include "intel_display_power.h"
#include "intel_display_reg_defs.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_step.h"
@ -252,6 +253,7 @@ static const struct intel_display_device_info no_display = {};
static const struct platform_desc i830_desc = {
PLATFORM(i830),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
I830_DISPLAY,
@ -270,6 +272,7 @@ static const struct platform_desc i845_desc = {
static const struct platform_desc i85x_desc = {
PLATFORM(i85x),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
I830_DISPLAY,
@ -312,6 +315,7 @@ static const struct platform_desc i915g_desc = {
static const struct platform_desc i915gm_desc = {
PLATFORM(i915gm),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
@ -336,6 +340,7 @@ static const struct platform_desc i945g_desc = {
static const struct platform_desc i945gm_desc = {
PLATFORM(i915gm),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
@ -357,13 +362,21 @@ static const struct platform_desc g33_desc = {
},
};
static const struct platform_desc pnv_desc = {
static const struct intel_display_device_info pnv_display = {
GEN3_DISPLAY,
I9XX_COLORS,
.has_hotplug = 1,
};
static const struct platform_desc pnv_g_desc = {
PLATFORM(pineview),
.info = &(const struct intel_display_device_info) {
GEN3_DISPLAY,
I9XX_COLORS,
.has_hotplug = 1,
},
.info = &pnv_display,
};
static const struct platform_desc pnv_m_desc = {
PLATFORM(pineview),
PLATFORM_GROUP(mobile),
.info = &pnv_display,
};
#define GEN4_DISPLAY \
@ -390,6 +403,7 @@ static const struct platform_desc i965g_desc = {
static const struct platform_desc i965gm_desc = {
PLATFORM(i965gm),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
.has_overlay = 1,
@ -413,6 +427,7 @@ static const struct platform_desc g45_desc = {
static const struct platform_desc gm45_desc = {
PLATFORM(gm45),
PLATFORM_GROUP(g4x),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
GEN4_DISPLAY,
.supports_tv = 1,
@ -443,6 +458,7 @@ static const struct platform_desc ilk_d_desc = {
static const struct platform_desc ilk_m_desc = {
PLATFORM(ironlake),
PLATFORM_GROUP(mobile),
.info = &(const struct intel_display_device_info) {
ILK_DISPLAY,
@ -450,38 +466,54 @@ static const struct platform_desc ilk_m_desc = {
},
};
static const struct platform_desc snb_desc = {
PLATFORM(sandybridge),
.info = &(const struct intel_display_device_info) {
.has_hotplug = 1,
I9XX_PIPE_OFFSETS,
I9XX_CURSOR_OFFSETS,
ILK_COLORS,
static const struct intel_display_device_info snb_display = {
.has_hotplug = 1,
I9XX_PIPE_OFFSETS,
I9XX_CURSOR_OFFSETS,
ILK_COLORS,
.__runtime_defaults.ip.ver = 6,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
},
.__runtime_defaults.ip.ver = 6,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
};
static const struct platform_desc ivb_desc = {
PLATFORM(ivybridge),
.info = &(const struct intel_display_device_info) {
.has_hotplug = 1,
IVB_PIPE_OFFSETS,
IVB_CURSOR_OFFSETS,
IVB_COLORS,
static const struct platform_desc snb_d_desc = {
PLATFORM(sandybridge),
.info = &snb_display,
};
.__runtime_defaults.ip.ver = 7,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
},
static const struct platform_desc snb_m_desc = {
PLATFORM(sandybridge),
PLATFORM_GROUP(mobile),
.info = &snb_display,
};
static const struct intel_display_device_info ivb_display = {
.has_hotplug = 1,
IVB_PIPE_OFFSETS,
IVB_CURSOR_OFFSETS,
IVB_COLORS,
.__runtime_defaults.ip.ver = 7,
.__runtime_defaults.pipe_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C),
.__runtime_defaults.cpu_transcoder_mask =
BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C),
.__runtime_defaults.port_mask = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | BIT(PORT_D), /* DP A, SDVO/HDMI/DP B, HDMI/DP C/D */
.__runtime_defaults.fbc_mask = BIT(INTEL_FBC_A),
};
static const struct platform_desc ivb_d_desc = {
PLATFORM(ivybridge),
.info = &ivb_display,
};
static const struct platform_desc ivb_m_desc = {
PLATFORM(ivybridge),
PLATFORM_GROUP(mobile),
.info = &ivb_display,
};
static const struct platform_desc vlv_desc = {
@ -1011,6 +1043,7 @@ static const enum intel_step dg1_steppings[] = {
static const struct platform_desc dg1_desc = {
PLATFORM(dg1),
PLATFORM_GROUP(dgfx),
.info = &(const struct intel_display_device_info) {
XE_D_DISPLAY,
@ -1238,6 +1271,7 @@ static const enum intel_step dg2_g12_steppings[] = {
static const struct platform_desc dg2_desc = {
PLATFORM(dg2),
PLATFORM_GROUP(dgfx),
.subplatforms = (const struct subplatform_desc[]) {
{
SUBPLATFORM(dg2, g10),
@ -1338,6 +1372,7 @@ static const struct platform_desc lnl_desc = {
static const struct platform_desc bmg_desc = {
PLATFORM(battlemage),
PLATFORM_GROUP(dgfx),
};
static const struct platform_desc ptl_desc = {
@ -1381,11 +1416,14 @@ static const struct {
INTEL_I965GM_IDS(INTEL_DISPLAY_DEVICE, &i965gm_desc),
INTEL_GM45_IDS(INTEL_DISPLAY_DEVICE, &gm45_desc),
INTEL_G45_IDS(INTEL_DISPLAY_DEVICE, &g45_desc),
INTEL_PNV_IDS(INTEL_DISPLAY_DEVICE, &pnv_desc),
INTEL_PNV_G_IDS(INTEL_DISPLAY_DEVICE, &pnv_g_desc),
INTEL_PNV_M_IDS(INTEL_DISPLAY_DEVICE, &pnv_m_desc),
INTEL_ILK_D_IDS(INTEL_DISPLAY_DEVICE, &ilk_d_desc),
INTEL_ILK_M_IDS(INTEL_DISPLAY_DEVICE, &ilk_m_desc),
INTEL_SNB_IDS(INTEL_DISPLAY_DEVICE, &snb_desc),
INTEL_IVB_IDS(INTEL_DISPLAY_DEVICE, &ivb_desc),
INTEL_SNB_D_IDS(INTEL_DISPLAY_DEVICE, &snb_d_desc),
INTEL_SNB_M_IDS(INTEL_DISPLAY_DEVICE, &snb_m_desc),
INTEL_IVB_D_IDS(INTEL_DISPLAY_DEVICE, &ivb_d_desc),
INTEL_IVB_M_IDS(INTEL_DISPLAY_DEVICE, &ivb_m_desc),
INTEL_HSW_IDS(INTEL_DISPLAY_DEVICE, &hsw_desc),
INTEL_VLV_IDS(INTEL_DISPLAY_DEVICE, &vlv_desc),
INTEL_BDW_IDS(INTEL_DISPLAY_DEVICE, &bdw_desc),
@ -1429,9 +1467,9 @@ static const struct {
};
static const struct intel_display_device_info *
probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *ip_ver)
probe_gmdid_display(struct intel_display *display, struct intel_display_ip_ver *ip_ver)
{
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
struct intel_display_ip_ver gmd_id;
void __iomem *addr;
u32 val;
@ -1439,7 +1477,8 @@ probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *
addr = pci_iomap_range(pdev, 0, i915_mmio_reg_offset(GMD_ID_DISPLAY), sizeof(u32));
if (!addr) {
drm_err(&i915->drm, "Cannot map MMIO BAR to read display GMD_ID\n");
drm_err(display->drm,
"Cannot map MMIO BAR to read display GMD_ID\n");
return NULL;
}
@ -1447,7 +1486,7 @@ probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *
pci_iounmap(pdev, addr);
if (val == 0) {
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
drm_dbg_kms(display->drm, "Device doesn't have display\n");
return NULL;
}
@ -1463,7 +1502,8 @@ probe_gmdid_display(struct drm_i915_private *i915, struct intel_display_ip_ver *
}
}
drm_err(&i915->drm, "Unrecognized display IP version %d.%02d; disabling display.\n",
drm_err(display->drm,
"Unrecognized display IP version %d.%02d; disabling display.\n",
gmd_id.ver, gmd_id.rel);
return NULL;
}
@ -1564,10 +1604,9 @@ static void display_platforms_or(struct intel_display_platforms *dst,
bitmap_or(dst->bitmap, dst->bitmap, src->bitmap, display_platforms_num_bits());
}
void intel_display_device_probe(struct drm_i915_private *i915)
struct intel_display *intel_display_device_probe(struct pci_dev *pdev)
{
struct intel_display *display = &i915->display;
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
struct intel_display *display = to_intel_display(pdev);
const struct intel_display_device_info *info;
struct intel_display_ip_ver ip_ver = {};
const struct platform_desc *desc;
@ -1575,55 +1614,56 @@ void intel_display_device_probe(struct drm_i915_private *i915)
enum intel_step step;
/* Add drm device backpointer as early as possible. */
i915->display.drm = &i915->drm;
display->drm = pci_get_drvdata(pdev);
intel_display_params_copy(&i915->display.params);
intel_display_params_copy(&display->params);
if (has_no_display(pdev)) {
drm_dbg_kms(&i915->drm, "Device doesn't have display\n");
drm_dbg_kms(display->drm, "Device doesn't have display\n");
goto no_display;
}
desc = find_platform_desc(pdev);
if (!desc) {
drm_dbg_kms(&i915->drm, "Unknown device ID %04x; disabling display.\n",
drm_dbg_kms(display->drm,
"Unknown device ID %04x; disabling display.\n",
pdev->device);
goto no_display;
}
info = desc->info;
if (!info)
info = probe_gmdid_display(i915, &ip_ver);
info = probe_gmdid_display(display, &ip_ver);
if (!info)
goto no_display;
DISPLAY_INFO(i915) = info;
DISPLAY_INFO(display) = info;
memcpy(DISPLAY_RUNTIME_INFO(i915),
&DISPLAY_INFO(i915)->__runtime_defaults,
sizeof(*DISPLAY_RUNTIME_INFO(i915)));
memcpy(DISPLAY_RUNTIME_INFO(display),
&DISPLAY_INFO(display)->__runtime_defaults,
sizeof(*DISPLAY_RUNTIME_INFO(display)));
drm_WARN_ON(&i915->drm, !desc->name ||
drm_WARN_ON(display->drm, !desc->name ||
!display_platforms_weight(&desc->platforms));
display->platform = desc->platforms;
subdesc = find_subplatform_desc(pdev, desc);
if (subdesc) {
drm_WARN_ON(&i915->drm, !subdesc->name ||
drm_WARN_ON(display->drm, !subdesc->name ||
!display_platforms_weight(&subdesc->platforms));
display_platforms_or(&display->platform, &subdesc->platforms);
/* Ensure platform and subplatform are distinct */
drm_WARN_ON(&i915->drm,
drm_WARN_ON(display->drm,
display_platforms_weight(&display->platform) !=
display_platforms_weight(&desc->platforms) +
display_platforms_weight(&subdesc->platforms));
}
if (ip_ver.ver || ip_ver.rel || ip_ver.step) {
DISPLAY_RUNTIME_INFO(i915)->ip = ip_ver;
DISPLAY_RUNTIME_INFO(display)->ip = ip_ver;
step = STEP_A0 + ip_ver.step;
if (step > STEP_FUTURE) {
drm_dbg_kms(display->drm, "Using future display stepping\n");
@ -1634,29 +1674,32 @@ void intel_display_device_probe(struct drm_i915_private *i915)
subdesc ? &subdesc->step_info : NULL);
}
DISPLAY_RUNTIME_INFO(i915)->step = step;
DISPLAY_RUNTIME_INFO(display)->step = step;
drm_info(&i915->drm, "Found %s%s%s (device ID %04x) display version %u.%02u stepping %s\n",
drm_info(display->drm, "Found %s%s%s (device ID %04x) %s display version %u.%02u stepping %s\n",
desc->name, subdesc ? "/" : "", subdesc ? subdesc->name : "",
pdev->device, DISPLAY_RUNTIME_INFO(i915)->ip.ver,
DISPLAY_RUNTIME_INFO(i915)->ip.rel,
pdev->device, display->platform.dgfx ? "discrete" : "integrated",
DISPLAY_RUNTIME_INFO(display)->ip.ver,
DISPLAY_RUNTIME_INFO(display)->ip.rel,
step != STEP_NONE ? intel_step_name(step) : "N/A");
return;
return display;
no_display:
DISPLAY_INFO(i915) = &no_display;
DISPLAY_INFO(display) = &no_display;
return display;
}
void intel_display_device_remove(struct drm_i915_private *i915)
void intel_display_device_remove(struct intel_display *display)
{
intel_display_params_free(&i915->display.params);
intel_display_params_free(&display->params);
}
static void __intel_display_device_info_runtime_init(struct drm_i915_private *i915)
static void __intel_display_device_info_runtime_init(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(i915);
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_display_runtime_info *display_runtime = DISPLAY_RUNTIME_INFO(display);
enum pipe pipe;
BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->pipe_mask) < I915_MAX_PIPES);
@ -1664,35 +1707,35 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
BUILD_BUG_ON(BITS_PER_TYPE(display_runtime->port_mask) < I915_MAX_PORTS);
/* This covers both ULT and ULX */
if (IS_HASWELL_ULT(i915) || IS_BROADWELL_ULT(i915))
if (display->platform.haswell_ult || display->platform.broadwell_ult)
display_runtime->port_mask &= ~BIT(PORT_D);
if (IS_ICL_WITH_PORT_F(i915))
if (display->platform.icelake_port_f)
display_runtime->port_mask |= BIT(PORT_F);
/* Wa_14011765242: adl-s A0,A1 */
if (IS_ALDERLAKE_S(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_A2))
for_each_pipe(i915, pipe)
if (display->platform.alderlake_s && IS_DISPLAY_STEP(display, STEP_A0, STEP_A2))
for_each_pipe(display, pipe)
display_runtime->num_scalers[pipe] = 0;
else if (DISPLAY_VER(i915) >= 11) {
for_each_pipe(i915, pipe)
else if (DISPLAY_VER(display) >= 11) {
for_each_pipe(display, pipe)
display_runtime->num_scalers[pipe] = 2;
} else if (DISPLAY_VER(i915) >= 9) {
} else if (DISPLAY_VER(display) >= 9) {
display_runtime->num_scalers[PIPE_A] = 2;
display_runtime->num_scalers[PIPE_B] = 2;
display_runtime->num_scalers[PIPE_C] = 1;
}
if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
for_each_pipe(i915, pipe)
if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display))
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 4;
else if (DISPLAY_VER(i915) >= 11)
for_each_pipe(i915, pipe)
else if (DISPLAY_VER(display) >= 11)
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 6;
else if (DISPLAY_VER(i915) == 10)
for_each_pipe(i915, pipe)
else if (DISPLAY_VER(display) == 10)
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 3;
else if (IS_BROXTON(i915)) {
else if (display->platform.broxton) {
/*
* Skylake and Broxton currently don't expose the topmost plane as its
* use is exclusive with the legacy cursor and we only want to expose
@ -1705,23 +1748,23 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
display_runtime->num_sprites[PIPE_A] = 2;
display_runtime->num_sprites[PIPE_B] = 2;
display_runtime->num_sprites[PIPE_C] = 1;
} else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
for_each_pipe(i915, pipe)
} else if (display->platform.valleyview || display->platform.cherryview) {
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 2;
} else if (DISPLAY_VER(i915) >= 5 || IS_G4X(i915)) {
for_each_pipe(i915, pipe)
} else if (DISPLAY_VER(display) >= 5 || display->platform.g4x) {
for_each_pipe(display, pipe)
display_runtime->num_sprites[pipe] = 1;
}
if ((IS_DGFX(i915) || DISPLAY_VER(i915) >= 14) &&
!(intel_de_read(i915, GU_CNTL_PROTECTED) & DEPRESENT)) {
drm_info(&i915->drm, "Display not present, disabling\n");
if ((display->platform.dgfx || DISPLAY_VER(display) >= 14) &&
!(intel_de_read(display, GU_CNTL_PROTECTED) & DEPRESENT)) {
drm_info(display->drm, "Display not present, disabling\n");
goto display_fused_off;
}
if (IS_DISPLAY_VER(i915, 7, 8) && HAS_PCH_SPLIT(i915)) {
u32 fuse_strap = intel_de_read(i915, FUSE_STRAP);
u32 sfuse_strap = intel_de_read(i915, SFUSE_STRAP);
if (IS_DISPLAY_VER(display, 7, 8) && HAS_PCH_SPLIT(i915)) {
u32 fuse_strap = intel_de_read(display, FUSE_STRAP);
u32 sfuse_strap = intel_de_read(display, SFUSE_STRAP);
/*
* SFUSE_STRAP is supposed to have a bit signalling the display
@ -1736,16 +1779,16 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
(HAS_PCH_CPT(i915) &&
!(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
drm_info(&i915->drm,
drm_info(display->drm,
"Display fused off, disabling\n");
goto display_fused_off;
} else if (fuse_strap & IVB_PIPE_C_DISABLE) {
drm_info(&i915->drm, "PipeC fused off\n");
drm_info(display->drm, "PipeC fused off\n");
display_runtime->pipe_mask &= ~BIT(PIPE_C);
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_C);
}
} else if (DISPLAY_VER(i915) >= 9) {
u32 dfsm = intel_de_read(i915, SKL_DFSM);
} else if (DISPLAY_VER(display) >= 9) {
u32 dfsm = intel_de_read(display, SKL_DFSM);
if (dfsm & SKL_DFSM_PIPE_A_DISABLE) {
display_runtime->pipe_mask &= ~BIT(PIPE_A);
@ -1763,7 +1806,7 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
display_runtime->fbc_mask &= ~BIT(INTEL_FBC_C);
}
if (DISPLAY_VER(i915) >= 12 &&
if (DISPLAY_VER(display) >= 12 &&
(dfsm & TGL_DFSM_PIPE_D_DISABLE)) {
display_runtime->pipe_mask &= ~BIT(PIPE_D);
display_runtime->cpu_transcoder_mask &= ~BIT(TRANSCODER_D);
@ -1776,15 +1819,15 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE)
display_runtime->has_hdcp = 0;
if (IS_DG2(i915) || DISPLAY_VER(i915) < 13) {
if (display->platform.dg2 || DISPLAY_VER(display) < 13) {
if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE)
display_runtime->fbc_mask = 0;
}
if (DISPLAY_VER(i915) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
if (DISPLAY_VER(display) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
display_runtime->has_dmc = 0;
if (IS_DISPLAY_VER(i915, 10, 12) &&
if (IS_DISPLAY_VER(display, 10, 12) &&
(dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE))
display_runtime->has_dsc = 0;
@ -1793,8 +1836,8 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
display_runtime->has_dbuf_overlap_detection = false;
}
if (DISPLAY_VER(i915) >= 20) {
u32 cap = intel_de_read(i915, XE2LPD_DE_CAP);
if (DISPLAY_VER(display) >= 20) {
u32 cap = intel_de_read(display, XE2LPD_DE_CAP);
if (REG_FIELD_GET(XE2LPD_DE_CAP_DSC_MASK, cap) ==
XE2LPD_DE_CAP_DSC_REMOVED)
@ -1802,18 +1845,19 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
if (REG_FIELD_GET(XE2LPD_DE_CAP_SCALER_MASK, cap) ==
XE2LPD_DE_CAP_SCALER_SINGLE) {
for_each_pipe(i915, pipe)
for_each_pipe(display, pipe)
if (display_runtime->num_scalers[pipe])
display_runtime->num_scalers[pipe] = 1;
}
}
if (DISPLAY_VER(i915) >= 30)
if (DISPLAY_VER(display) >= 30)
display_runtime->edp_typec_support =
intel_de_read(display, PICA_PHY_CONFIG_CONTROL) & EDP_ON_TYPEC;
display_runtime->rawclk_freq = intel_read_rawclk(display);
drm_dbg_kms(&i915->drm, "rawclk rate: %d kHz\n", display_runtime->rawclk_freq);
drm_dbg_kms(display->drm, "rawclk rate: %d kHz\n",
display_runtime->rawclk_freq);
return;
@ -1821,21 +1865,21 @@ static void __intel_display_device_info_runtime_init(struct drm_i915_private *i9
memset(display_runtime, 0, sizeof(*display_runtime));
}
void intel_display_device_info_runtime_init(struct drm_i915_private *i915)
void intel_display_device_info_runtime_init(struct intel_display *display)
{
if (HAS_DISPLAY(i915))
__intel_display_device_info_runtime_init(i915);
if (HAS_DISPLAY(display))
__intel_display_device_info_runtime_init(display);
/* Display may have been disabled by runtime init */
if (!HAS_DISPLAY(i915)) {
i915->drm.driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
i915->display.info.__device_info = &no_display;
if (!HAS_DISPLAY(display)) {
display->drm->driver_features &= ~(DRIVER_MODESET | DRIVER_ATOMIC);
display->info.__device_info = &no_display;
}
/* Disable nuclear pageflip by default on pre-g4x */
if (!i915->display.params.nuclear_pageflip &&
DISPLAY_VER(i915) < 5 && !IS_G4X(i915))
i915->drm.driver_features &= ~DRIVER_ATOMIC;
if (!display->params.nuclear_pageflip &&
DISPLAY_VER(display) < 5 && !display->platform.g4x)
display->drm->driver_features &= ~DRIVER_ATOMIC;
}
void intel_display_device_info_print(const struct intel_display_device_info *info,
@ -1872,10 +1916,8 @@ void intel_display_device_info_print(const struct intel_display_device_info *inf
* Disabling display means taking over the display hardware, putting it to
* sleep, and preventing connectors from being connected via any means.
*/
bool intel_display_device_enabled(struct drm_i915_private *i915)
bool intel_display_device_enabled(struct intel_display *display)
{
struct intel_display *display = &i915->display;
/* Only valid when HAS_DISPLAY() is true */
drm_WARN_ON(display->drm, !HAS_DISPLAY(display));

View File

@ -12,8 +12,9 @@
#include "intel_display_conversion.h"
#include "intel_display_limits.h"
struct drm_i915_private;
struct drm_printer;
struct intel_display;
struct pci_dev;
/*
* Display platforms and subplatforms. Keep platforms in display version based
@ -21,6 +22,10 @@ struct drm_printer;
* platform.
*/
#define INTEL_DISPLAY_PLATFORMS(func) \
/* Platform group aliases */ \
func(g4x) /* g45 and gm45 */ \
func(mobile) /* mobile platforms */ \
func(dgfx) /* discrete graphics */ \
/* Display ver 2 */ \
func(i830) \
func(i845g) \
@ -38,7 +43,6 @@ struct drm_printer;
func(i965gm) \
func(g45) \
func(gm45) \
func(g4x) /* group alias for g45 and gm45 */ \
/* Display ver 5 */ \
func(ironlake) \
/* Display ver 6 */ \
@ -136,61 +140,64 @@ struct intel_display_platforms {
func(overlay_needs_physical); \
func(supports_tv);
#define HAS_4TILE(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_ASYNC_FLIPS(i915) (DISPLAY_VER(i915) >= 5)
#define HAS_BIGJOINER(i915) (DISPLAY_VER(i915) >= 11 && HAS_DSC(i915))
#define HAS_CDCLK_CRAWL(i915) (DISPLAY_INFO(i915)->has_cdclk_crawl)
#define HAS_CDCLK_SQUASH(i915) (DISPLAY_INFO(i915)->has_cdclk_squash)
#define HAS_CUR_FBC(i915) (!HAS_GMCH(i915) && IS_DISPLAY_VER(i915, 7, 13))
#define HAS_D12_PLANE_MINIMIZATION(i915) (IS_ROCKETLAKE(i915) || IS_ALDERLAKE_S(i915))
#define HAS_DBUF_OVERLAP_DETECTION(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dbuf_overlap_detection)
#define HAS_DDI(i915) (DISPLAY_INFO(i915)->has_ddi)
#define HAS_DISPLAY(i915) (DISPLAY_RUNTIME_INFO(i915)->pipe_mask != 0)
#define HAS_DMC(i915) (DISPLAY_RUNTIME_INFO(i915)->has_dmc)
#define HAS_DOUBLE_BUFFERED_M_N(i915) (DISPLAY_VER(i915) >= 9 || IS_BROADWELL(i915))
#define HAS_DP_MST(i915) (DISPLAY_INFO(i915)->has_dp_mst)
#define HAS_DP20(i915) (IS_DG2(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_DPT(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_DSB(i915) (DISPLAY_INFO(i915)->has_dsb)
#define HAS_DSC(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dsc)
#define HAS_DSC_MST(__i915) (DISPLAY_VER(__i915) >= 12 && HAS_DSC(__i915))
#define HAS_FBC(i915) (DISPLAY_RUNTIME_INFO(i915)->fbc_mask != 0)
#define HAS_FPGA_DBG_UNCLAIMED(i915) (DISPLAY_INFO(i915)->has_fpga_dbg)
#define HAS_FW_BLC(i915) (DISPLAY_VER(i915) >= 3)
#define HAS_GMBUS_IRQ(i915) (DISPLAY_VER(i915) >= 4)
#define HAS_GMBUS_BURST_READ(i915) (DISPLAY_VER(i915) >= 10 || IS_KABYLAKE(i915))
#define HAS_GMCH(i915) (DISPLAY_INFO(i915)->has_gmch)
#define HAS_HW_SAGV_WM(i915) (DISPLAY_VER(i915) >= 13 && !IS_DGFX(i915))
#define HAS_IPC(i915) (DISPLAY_INFO(i915)->has_ipc)
#define HAS_IPS(i915) (IS_HASWELL_ULT(i915) || IS_BROADWELL(i915))
#define HAS_LRR(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_LSPCON(i915) (IS_DISPLAY_VER(i915, 9, 10))
#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915) || DISPLAY_VER(i915) >= 14)
#define HAS_MSO(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_OVERLAY(i915) (DISPLAY_INFO(i915)->has_overlay)
#define HAS_PSR(i915) (DISPLAY_INFO(i915)->has_psr)
#define HAS_PSR_HW_TRACKING(i915) (DISPLAY_INFO(i915)->has_psr_hw_tracking)
#define HAS_PSR2_SEL_FETCH(i915) (DISPLAY_VER(i915) >= 12)
#define HAS_SAGV(i915) (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915) && !IS_GEMINILAKE(i915))
#define HAS_TRANSCODER(i915, trans) ((DISPLAY_RUNTIME_INFO(i915)->cpu_transcoder_mask & \
BIT(trans)) != 0)
#define HAS_UNCOMPRESSED_JOINER(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_ULTRAJOINER(i915) ((DISPLAY_VER(i915) >= 20 || \
(IS_DGFX(i915) && DISPLAY_VER(i915) == 14)) && \
HAS_DSC(i915))
#define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11)
#define HAS_AS_SDP(i915) (DISPLAY_VER(i915) >= 13)
#define HAS_CMRR(i915) (DISPLAY_VER(i915) >= 20)
#define INTEL_NUM_PIPES(i915) (hweight8(DISPLAY_RUNTIME_INFO(i915)->pipe_mask))
#define I915_HAS_HOTPLUG(i915) (DISPLAY_INFO(i915)->has_hotplug)
#define OVERLAY_NEEDS_PHYSICAL(i915) (DISPLAY_INFO(i915)->overlay_needs_physical)
#define SUPPORTS_TV(i915) (DISPLAY_INFO(i915)->supports_tv)
#define HAS_4TILE(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14)
#define HAS_ASYNC_FLIPS(__display) (DISPLAY_VER(__display) >= 5)
#define HAS_BIGJOINER(__display) (DISPLAY_VER(__display) >= 11 && HAS_DSC(__display))
#define HAS_CDCLK_CRAWL(__display) (DISPLAY_INFO(__display)->has_cdclk_crawl)
#define HAS_CDCLK_SQUASH(__display) (DISPLAY_INFO(__display)->has_cdclk_squash)
#define HAS_CUR_FBC(__display) (!HAS_GMCH(__display) && IS_DISPLAY_VER(__display, 7, 13))
#define HAS_D12_PLANE_MINIMIZATION(__display) ((__display)->platform.rocketlake || (__display)->platform.alderlake_s)
#define HAS_DBUF_OVERLAP_DETECTION(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dbuf_overlap_detection)
#define HAS_DDI(__display) (DISPLAY_INFO(__display)->has_ddi)
#define HAS_DISPLAY(__display) (DISPLAY_RUNTIME_INFO(__display)->pipe_mask != 0)
#define HAS_DMC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dmc)
#define HAS_DMC_WAKELOCK(__display) (DISPLAY_VER(__display) >= 20)
#define HAS_DOUBLE_BUFFERED_M_N(__display) (DISPLAY_VER(__display) >= 9 || (__display)->platform.broadwell)
#define HAS_DOUBLE_WIDE(__display) (DISPLAY_VER(__display) < 4)
#define HAS_DP_MST(__display) (DISPLAY_INFO(__display)->has_dp_mst)
#define HAS_DP20(__display) ((__display)->platform.dg2 || DISPLAY_VER(__display) >= 14)
#define HAS_DPT(__display) (DISPLAY_VER(__display) >= 13)
#define HAS_DSB(__display) (DISPLAY_INFO(__display)->has_dsb)
#define HAS_DSC(__display) (DISPLAY_RUNTIME_INFO(__display)->has_dsc)
#define HAS_DSC_MST(__display) (DISPLAY_VER(__display) >= 12 && HAS_DSC(__display))
#define HAS_FBC(__display) (DISPLAY_RUNTIME_INFO(__display)->fbc_mask != 0)
#define HAS_FPGA_DBG_UNCLAIMED(__display) (DISPLAY_INFO(__display)->has_fpga_dbg)
#define HAS_FW_BLC(__display) (DISPLAY_VER(__display) >= 3)
#define HAS_GMBUS_IRQ(__display) (DISPLAY_VER(__display) >= 4)
#define HAS_GMBUS_BURST_READ(__display) (DISPLAY_VER(__display) >= 10 || (__display)->platform.kabylake)
#define HAS_GMCH(__display) (DISPLAY_INFO(__display)->has_gmch)
#define HAS_HW_SAGV_WM(__display) (DISPLAY_VER(__display) >= 13 && !(__display)->platform.dgfx)
#define HAS_IPC(__display) (DISPLAY_INFO(__display)->has_ipc)
#define HAS_IPS(__display) ((__display)->platform.haswell_ult || (__display)->platform.broadwell)
#define HAS_LRR(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_LSPCON(__display) (IS_DISPLAY_VER(__display, 9, 10))
#define HAS_MBUS_JOINING(__display) ((__display)->platform.alderlake_p || DISPLAY_VER(__display) >= 14)
#define HAS_MSO(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_OVERLAY(__display) (DISPLAY_INFO(__display)->has_overlay)
#define HAS_PSR(__display) (DISPLAY_INFO(__display)->has_psr)
#define HAS_PSR_HW_TRACKING(__display) (DISPLAY_INFO(__display)->has_psr_hw_tracking)
#define HAS_PSR2_SEL_FETCH(__display) (DISPLAY_VER(__display) >= 12)
#define HAS_SAGV(__display) (DISPLAY_VER(__display) >= 9 && \
!(__display)->platform.broxton && !(__display)->platform.geminilake)
#define HAS_TRANSCODER(__display, trans) ((DISPLAY_RUNTIME_INFO(__display)->cpu_transcoder_mask & \
BIT(trans)) != 0)
#define HAS_UNCOMPRESSED_JOINER(__display) (DISPLAY_VER(__display) >= 13)
#define HAS_ULTRAJOINER(__display) ((DISPLAY_VER(__display) >= 20 || \
((__display)->platform.dgfx && DISPLAY_VER(__display) == 14)) && \
HAS_DSC(__display))
#define HAS_VRR(__display) (DISPLAY_VER(__display) >= 11)
#define HAS_AS_SDP(__display) (DISPLAY_VER(__display) >= 13)
#define HAS_CMRR(__display) (DISPLAY_VER(__display) >= 20)
#define INTEL_NUM_PIPES(__display) (hweight8(DISPLAY_RUNTIME_INFO(__display)->pipe_mask))
#define I915_HAS_HOTPLUG(__display) (DISPLAY_INFO(__display)->has_hotplug)
#define OVERLAY_NEEDS_PHYSICAL(__display) (DISPLAY_INFO(__display)->overlay_needs_physical)
#define SUPPORTS_TV(__display) (DISPLAY_INFO(__display)->supports_tv)
/* Check that device has a display IP version within the specific range. */
#define IS_DISPLAY_VERx100(__i915, from, until) ( \
#define IS_DISPLAY_VERx100(__display, from, until) ( \
BUILD_BUG_ON_ZERO((from) < 200) + \
(DISPLAY_VERx100(__i915) >= (from) && \
DISPLAY_VERx100(__i915) <= (until)))
(DISPLAY_VERx100(__display) >= (from) && \
DISPLAY_VERx100(__display) <= (until)))
/*
* Check if a device has a specific IP version as well as a stepping within the
@ -201,30 +208,30 @@ struct intel_display_platforms {
* hardware fix is present and the software workaround is no longer necessary.
* E.g.,
*
* IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_A0, STEP_B2)
* IS_DISPLAY_VERx100_STEP(i915, 1400, STEP_C0, STEP_FOREVER)
* IS_DISPLAY_VERx100_STEP(display, 1400, STEP_A0, STEP_B2)
* IS_DISPLAY_VERx100_STEP(display, 1400, STEP_C0, STEP_FOREVER)
*
* "STEP_FOREVER" can be passed as "until" for workarounds that have no upper
* stepping bound for the specified IP version.
*/
#define IS_DISPLAY_VERx100_STEP(__i915, ipver, from, until) \
(IS_DISPLAY_VERx100((__i915), (ipver), (ipver)) && \
IS_DISPLAY_STEP((__i915), (from), (until)))
#define IS_DISPLAY_VERx100_STEP(__display, ipver, from, until) \
(IS_DISPLAY_VERx100((__display), (ipver), (ipver)) && \
IS_DISPLAY_STEP((__display), (from), (until)))
#define DISPLAY_INFO(i915) (__to_intel_display(i915)->info.__device_info)
#define DISPLAY_RUNTIME_INFO(i915) (&__to_intel_display(i915)->info.__runtime_info)
#define DISPLAY_INFO(__display) (__to_intel_display(__display)->info.__device_info)
#define DISPLAY_RUNTIME_INFO(__display) (&__to_intel_display(__display)->info.__runtime_info)
#define DISPLAY_VER(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver)
#define DISPLAY_VERx100(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver * 100 + \
DISPLAY_RUNTIME_INFO(i915)->ip.rel)
#define IS_DISPLAY_VER(i915, from, until) \
(DISPLAY_VER(i915) >= (from) && DISPLAY_VER(i915) <= (until))
#define DISPLAY_VER(__display) (DISPLAY_RUNTIME_INFO(__display)->ip.ver)
#define DISPLAY_VERx100(__display) (DISPLAY_RUNTIME_INFO(__display)->ip.ver * 100 + \
DISPLAY_RUNTIME_INFO(__display)->ip.rel)
#define IS_DISPLAY_VER(__display, from, until) \
(DISPLAY_VER(__display) >= (from) && DISPLAY_VER(__display) <= (until))
#define INTEL_DISPLAY_STEP(__i915) (DISPLAY_RUNTIME_INFO(__i915)->step)
#define INTEL_DISPLAY_STEP(__display) (DISPLAY_RUNTIME_INFO(__display)->step)
#define IS_DISPLAY_STEP(__i915, since, until) \
(drm_WARN_ON(__to_intel_display(__i915)->drm, INTEL_DISPLAY_STEP(__i915) == STEP_NONE), \
INTEL_DISPLAY_STEP(__i915) >= (since) && INTEL_DISPLAY_STEP(__i915) < (until))
#define IS_DISPLAY_STEP(__display, since, until) \
(drm_WARN_ON(__to_intel_display(__display)->drm, INTEL_DISPLAY_STEP(__display) == STEP_NONE), \
INTEL_DISPLAY_STEP(__display) >= (since) && INTEL_DISPLAY_STEP(__display) < (until))
struct intel_display_runtime_info {
struct intel_display_ip_ver {
@ -283,10 +290,10 @@ struct intel_display_device_info {
} color;
};
bool intel_display_device_enabled(struct drm_i915_private *i915);
void intel_display_device_probe(struct drm_i915_private *i915);
void intel_display_device_remove(struct drm_i915_private *i915);
void intel_display_device_info_runtime_init(struct drm_i915_private *i915);
bool intel_display_device_enabled(struct intel_display *display);
struct intel_display *intel_display_device_probe(struct pci_dev *pdev);
void intel_display_device_remove(struct intel_display *display);
void intel_display_device_info_runtime_init(struct intel_display *display);
void intel_display_device_info_print(const struct intel_display_device_info *info,
const struct intel_display_runtime_info *runtime,

View File

@ -80,12 +80,12 @@ bool intel_display_driver_probe_defer(struct pci_dev *pdev)
return false;
}
void intel_display_driver_init_hw(struct drm_i915_private *i915)
void intel_display_driver_init_hw(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_cdclk_state *cdclk_state;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
cdclk_state = to_intel_cdclk_state(display->cdclk.obj.state);
@ -112,12 +112,12 @@ static const struct drm_mode_config_helper_funcs intel_mode_config_funcs = {
.atomic_commit_setup = drm_dp_mst_atomic_setup_commit,
};
static void intel_mode_config_init(struct drm_i915_private *i915)
static void intel_mode_config_init(struct intel_display *display)
{
struct drm_mode_config *mode_config = &i915->drm.mode_config;
struct drm_mode_config *mode_config = &display->drm->mode_config;
drm_mode_config_init(&i915->drm);
INIT_LIST_HEAD(&i915->display.global.obj_list);
drm_mode_config_init(display->drm);
INIT_LIST_HEAD(&display->global.obj_list);
mode_config->min_width = 0;
mode_config->min_height = 0;
@ -128,19 +128,19 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
mode_config->funcs = &intel_mode_funcs;
mode_config->helper_private = &intel_mode_config_funcs;
mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915);
mode_config->async_page_flip = HAS_ASYNC_FLIPS(display);
/*
* Maximum framebuffer dimensions, chosen to match
* the maximum render engine surface size on gen4+.
*/
if (DISPLAY_VER(i915) >= 7) {
if (DISPLAY_VER(display) >= 7) {
mode_config->max_width = 16384;
mode_config->max_height = 16384;
} else if (DISPLAY_VER(i915) >= 4) {
} else if (DISPLAY_VER(display) >= 4) {
mode_config->max_width = 8192;
mode_config->max_height = 8192;
} else if (DISPLAY_VER(i915) == 3) {
} else if (DISPLAY_VER(display) == 3) {
mode_config->max_width = 4096;
mode_config->max_height = 4096;
} else {
@ -148,11 +148,11 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
mode_config->max_height = 2048;
}
if (IS_I845G(i915) || IS_I865G(i915)) {
mode_config->cursor_width = IS_I845G(i915) ? 64 : 512;
if (display->platform.i845g || display->platform.i865g) {
mode_config->cursor_width = display->platform.i845g ? 64 : 512;
mode_config->cursor_height = 1023;
} else if (IS_I830(i915) || IS_I85X(i915) ||
IS_I915G(i915) || IS_I915GM(i915)) {
} else if (display->platform.i830 || display->platform.i85x ||
display->platform.i915g || display->platform.i915gm) {
mode_config->cursor_width = 64;
mode_config->cursor_height = 64;
} else {
@ -161,18 +161,19 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
}
}
static void intel_mode_config_cleanup(struct drm_i915_private *i915)
static void intel_mode_config_cleanup(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
intel_atomic_global_obj_cleanup(i915);
drm_mode_config_cleanup(&i915->drm);
drm_mode_config_cleanup(display->drm);
}
static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
static void intel_plane_possible_crtcs_init(struct intel_display *display)
{
struct intel_display *display = &dev_priv->display;
struct intel_plane *plane;
for_each_intel_plane(&dev_priv->drm, plane) {
for_each_intel_plane(display->drm, plane) {
struct intel_crtc *crtc = intel_crtc_for_pipe(display,
plane->pipe);
@ -180,41 +181,43 @@ static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
}
}
void intel_display_driver_early_probe(struct drm_i915_private *i915)
void intel_display_driver_early_probe(struct intel_display *display)
{
if (!HAS_DISPLAY(i915))
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(display))
return;
spin_lock_init(&i915->display.fb_tracking.lock);
mutex_init(&i915->display.backlight.lock);
mutex_init(&i915->display.audio.mutex);
mutex_init(&i915->display.wm.wm_mutex);
mutex_init(&i915->display.pps.mutex);
mutex_init(&i915->display.hdcp.hdcp_mutex);
spin_lock_init(&display->fb_tracking.lock);
mutex_init(&display->backlight.lock);
mutex_init(&display->audio.mutex);
mutex_init(&display->wm.wm_mutex);
mutex_init(&display->pps.mutex);
mutex_init(&display->hdcp.hdcp_mutex);
intel_display_irq_init(i915);
intel_dkl_phy_init(i915);
intel_color_init_hooks(&i915->display);
intel_init_cdclk_hooks(&i915->display);
intel_color_init_hooks(display);
intel_init_cdclk_hooks(display);
intel_audio_hooks_init(i915);
intel_dpll_init_clock_hook(i915);
intel_init_display_hooks(i915);
intel_fdi_init_hook(i915);
intel_dmc_wl_init(&i915->display);
intel_dmc_wl_init(display);
}
/* part #1: call before irq install */
int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
int intel_display_driver_probe_noirq(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
int ret;
if (i915_inject_probe_failure(i915))
return -ENODEV;
if (HAS_DISPLAY(i915)) {
ret = drm_vblank_init(&i915->drm,
INTEL_NUM_PIPES(i915));
if (HAS_DISPLAY(display)) {
ret = drm_vblank_init(display->drm,
INTEL_NUM_PIPES(display));
if (ret)
return ret;
}
@ -226,24 +229,25 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
goto cleanup_bios;
/* FIXME: completely on the wrong abstraction layer */
ret = intel_power_domains_init(i915);
ret = intel_power_domains_init(display);
if (ret < 0)
goto cleanup_vga;
intel_pmdemand_init_early(i915);
intel_power_domains_init_hw(i915, false);
intel_power_domains_init_hw(display, false);
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
intel_dmc_init(display);
i915->display.wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
i915->display.wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
display->wq.modeset = alloc_ordered_workqueue("i915_modeset", 0);
display->wq.flip = alloc_workqueue("i915_flip", WQ_HIGHPRI |
WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
display->wq.cleanup = alloc_workqueue("i915_cleanup", WQ_HIGHPRI, 0);
intel_mode_config_init(i915);
intel_mode_config_init(display);
ret = intel_cdclk_init(display);
if (ret)
@ -273,7 +277,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
cleanup_vga_client_pw_domain_dmc:
intel_dmc_fini(display);
intel_power_domains_driver_remove(i915);
intel_power_domains_driver_remove(display);
cleanup_vga:
intel_vga_unregister(display);
cleanup_bios:
@ -282,7 +286,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915)
return ret;
}
static void set_display_access(struct drm_i915_private *i915,
static void set_display_access(struct intel_display *display,
bool any_task_allowed,
struct task_struct *allowed_task)
{
@ -290,20 +294,20 @@ static void set_display_access(struct drm_i915_private *i915,
int err;
intel_modeset_lock_ctx_retry(&ctx, NULL, 0, err) {
err = drm_modeset_lock_all_ctx(&i915->drm, &ctx);
err = drm_modeset_lock_all_ctx(display->drm, &ctx);
if (err)
continue;
i915->display.access.any_task_allowed = any_task_allowed;
i915->display.access.allowed_task = allowed_task;
display->access.any_task_allowed = any_task_allowed;
display->access.allowed_task = allowed_task;
}
drm_WARN_ON(&i915->drm, err);
drm_WARN_ON(display->drm, err);
}
/**
* intel_display_driver_enable_user_access - Enable display HW access for all threads
* @i915: i915 device instance
* @display: display device instance
*
* Enable the display HW access for all threads. Examples for such accesses
* are modeset commits and connector probing.
@ -311,16 +315,18 @@ static void set_display_access(struct drm_i915_private *i915,
* This function should be called during driver loading and system resume once
* all the HW initialization steps are done.
*/
void intel_display_driver_enable_user_access(struct drm_i915_private *i915)
void intel_display_driver_enable_user_access(struct intel_display *display)
{
set_display_access(i915, true, NULL);
struct drm_i915_private *i915 = to_i915(display->drm);
set_display_access(display, true, NULL);
intel_hpd_enable_detection_work(i915);
}
/**
* intel_display_driver_disable_user_access - Disable display HW access for user threads
* @i915: i915 device instance
* @display: display device instance
*
* Disable the display HW access for user threads. Examples for such accesses
* are modeset commits and connector probing. For the current thread the
@ -335,16 +341,18 @@ void intel_display_driver_enable_user_access(struct drm_i915_private *i915)
* This function should be called during driver loading/unloading and system
* suspend/shutdown before starting the HW init/deinit programming.
*/
void intel_display_driver_disable_user_access(struct drm_i915_private *i915)
void intel_display_driver_disable_user_access(struct intel_display *display)
{
struct drm_i915_private *i915 = to_i915(display->drm);
intel_hpd_disable_detection_work(i915);
set_display_access(i915, false, current);
set_display_access(display, false, current);
}
/**
* intel_display_driver_suspend_access - Suspend display HW access for all threads
* @i915: i915 device instance
* @display: display device instance
*
* Disable the display HW access for all threads. Examples for such accesses
* are modeset commits and connector probing. This call should be either
@ -354,14 +362,14 @@ void intel_display_driver_disable_user_access(struct drm_i915_private *i915)
* This function should be called during driver unloading and system
* suspend/shutdown after completing the HW deinit programming.
*/
void intel_display_driver_suspend_access(struct drm_i915_private *i915)
void intel_display_driver_suspend_access(struct intel_display *display)
{
set_display_access(i915, false, NULL);
set_display_access(display, false, NULL);
}
/**
* intel_display_driver_resume_access - Resume display HW access for the resume thread
* @i915: i915 device instance
* @display: display device instance
*
* Enable the display HW access for the current resume thread, keeping the
* access disabled for all other (user) threads. Examples for such accesses
@ -373,14 +381,14 @@ void intel_display_driver_suspend_access(struct drm_i915_private *i915)
* This function should be called during system resume before starting the HW
* init steps.
*/
void intel_display_driver_resume_access(struct drm_i915_private *i915)
void intel_display_driver_resume_access(struct intel_display *display)
{
set_display_access(i915, false, current);
set_display_access(display, false, current);
}
/**
* intel_display_driver_check_access - Check if the current thread has disaplay HW access
* @i915: i915 device instance
* @display: display device instance
*
* Check whether the current thread has display HW access, print a debug
* message if it doesn't. Such accesses are modeset commits and connector
@ -389,26 +397,26 @@ void intel_display_driver_resume_access(struct drm_i915_private *i915)
* Returns %true if the current thread has display HW access, %false
* otherwise.
*/
bool intel_display_driver_check_access(struct drm_i915_private *i915)
bool intel_display_driver_check_access(struct intel_display *display)
{
char comm[TASK_COMM_LEN];
char current_task[TASK_COMM_LEN + 16];
char allowed_task[TASK_COMM_LEN + 16] = "none";
if (i915->display.access.any_task_allowed ||
i915->display.access.allowed_task == current)
if (display->access.any_task_allowed ||
display->access.allowed_task == current)
return true;
snprintf(current_task, sizeof(current_task), "%s[%d]",
get_task_comm(comm, current),
task_pid_vnr(current));
if (i915->display.access.allowed_task)
if (display->access.allowed_task)
snprintf(allowed_task, sizeof(allowed_task), "%s[%d]",
get_task_comm(comm, i915->display.access.allowed_task),
task_pid_vnr(i915->display.access.allowed_task));
get_task_comm(comm, display->access.allowed_task),
task_pid_vnr(display->access.allowed_task));
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Reject display access from task %s (allowed to %s)\n",
current_task, allowed_task);
@ -416,14 +424,13 @@ bool intel_display_driver_check_access(struct drm_i915_private *i915)
}
/* part #2: call after irq install, but before gem init */
int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
int intel_display_driver_probe_nogem(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_device *dev = display->drm;
struct drm_i915_private *i915 = to_i915(display->drm);
enum pipe pipe;
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
intel_wm_init(i915);
@ -434,22 +441,22 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
intel_gmbus_setup(display);
drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
INTEL_NUM_PIPES(i915),
INTEL_NUM_PIPES(i915) > 1 ? "s" : "");
drm_dbg_kms(display->drm, "%d display pipe%s available.\n",
INTEL_NUM_PIPES(display),
INTEL_NUM_PIPES(display) > 1 ? "s" : "");
for_each_pipe(i915, pipe) {
for_each_pipe(display, pipe) {
ret = intel_crtc_init(i915, pipe);
if (ret)
goto err_mode_config;
}
intel_plane_possible_crtcs_init(i915);
intel_plane_possible_crtcs_init(display);
intel_shared_dpll_init(i915);
intel_fdi_pll_freq_update(i915);
intel_update_czclk(i915);
intel_display_driver_init_hw(i915);
intel_display_driver_init_hw(display);
intel_dpll_update_ref_clks(i915);
if (display->cdclk.max_cdclk_freq == 0)
@ -465,21 +472,21 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
if (ret)
goto err_hdcp;
intel_display_driver_disable_user_access(i915);
intel_display_driver_disable_user_access(display);
drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(i915, dev->mode_config.acquire_ctx);
drm_modeset_lock_all(display->drm);
intel_modeset_setup_hw_state(i915, display->drm->mode_config.acquire_ctx);
intel_acpi_assign_connector_fwnodes(display);
drm_modeset_unlock_all(dev);
drm_modeset_unlock_all(display->drm);
intel_initial_plane_config(i915);
intel_initial_plane_config(display);
/*
* Make sure hardware watermarks really match the state we read out.
* Note that we need to do this after reconstructing the BIOS fb's
* since the watermark calculation done here will use pstate->fb.
*/
if (!HAS_GMCH(i915))
if (!HAS_GMCH(display))
ilk_wm_sanitize(i915);
return 0;
@ -487,18 +494,18 @@ int intel_display_driver_probe_nogem(struct drm_i915_private *i915)
err_hdcp:
intel_hdcp_component_fini(display);
err_mode_config:
intel_mode_config_cleanup(i915);
intel_mode_config_cleanup(display);
return ret;
}
/* part #3: call after gem init */
int intel_display_driver_probe(struct drm_i915_private *i915)
int intel_display_driver_probe(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
/*
@ -514,11 +521,11 @@ int intel_display_driver_probe(struct drm_i915_private *i915)
* are already calculated and there is no assert_plane warnings
* during bootup.
*/
ret = intel_initial_commit(&i915->drm);
ret = intel_initial_commit(display->drm);
if (ret)
drm_dbg_kms(&i915->drm, "Initial modeset failed, %d\n", ret);
drm_dbg_kms(display->drm, "Initial modeset failed, %d\n", ret);
intel_overlay_setup(i915);
intel_overlay_setup(display);
/* Only enable hotplug handling once the fbdev is fully set up. */
intel_hpd_init(i915);
@ -528,13 +535,13 @@ int intel_display_driver_probe(struct drm_i915_private *i915)
return 0;
}
void intel_display_driver_register(struct drm_i915_private *i915)
void intel_display_driver_register(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_printer p = drm_dbg_printer(&i915->drm, DRM_UT_KMS,
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_printer p = drm_dbg_printer(display->drm, DRM_UT_KMS,
"i915 display info:");
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
/* Must be done after probing outputs */
@ -543,7 +550,7 @@ void intel_display_driver_register(struct drm_i915_private *i915)
intel_audio_init(i915);
intel_display_driver_enable_user_access(i915);
intel_display_driver_enable_user_access(display);
intel_audio_register(i915);
@ -554,41 +561,42 @@ void intel_display_driver_register(struct drm_i915_private *i915)
* fbdev configuration, for which we use the
* fbdev->async_cookie.
*/
drm_kms_helper_poll_init(&i915->drm);
drm_kms_helper_poll_init(display->drm);
intel_hpd_poll_disable(i915);
intel_fbdev_setup(i915);
intel_display_device_info_print(DISPLAY_INFO(i915),
DISPLAY_RUNTIME_INFO(i915), &p);
intel_display_device_info_print(DISPLAY_INFO(display),
DISPLAY_RUNTIME_INFO(display), &p);
}
/* part #1: call before irq uninstall */
void intel_display_driver_remove(struct drm_i915_private *i915)
void intel_display_driver_remove(struct intel_display *display)
{
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
flush_workqueue(i915->display.wq.flip);
flush_workqueue(i915->display.wq.modeset);
flush_workqueue(display->wq.flip);
flush_workqueue(display->wq.modeset);
flush_workqueue(display->wq.cleanup);
/*
* MST topology needs to be suspended so we don't have any calls to
* fbdev after it's finalized. MST will be destroyed later as part of
* drm_mode_config_cleanup()
*/
intel_dp_mst_suspend(i915);
intel_dp_mst_suspend(display);
}
/* part #2: call after irq uninstall */
void intel_display_driver_remove_noirq(struct drm_i915_private *i915)
void intel_display_driver_remove_noirq(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
intel_display_driver_suspend_access(i915);
intel_display_driver_suspend_access(display);
/*
* Due to the hpd irq storm handling the hotplug work can re-arm the
@ -603,55 +611,54 @@ void intel_display_driver_remove_noirq(struct drm_i915_private *i915)
intel_hdcp_component_fini(display);
intel_mode_config_cleanup(i915);
intel_mode_config_cleanup(display);
intel_dp_tunnel_mgr_cleanup(display);
intel_overlay_cleanup(i915);
intel_overlay_cleanup(display);
intel_gmbus_teardown(display);
destroy_workqueue(i915->display.wq.flip);
destroy_workqueue(i915->display.wq.modeset);
destroy_workqueue(display->wq.flip);
destroy_workqueue(display->wq.modeset);
destroy_workqueue(display->wq.cleanup);
intel_fbc_cleanup(&i915->display);
intel_fbc_cleanup(display);
}
/* part #3: call after gem init */
void intel_display_driver_remove_nogem(struct drm_i915_private *i915)
void intel_display_driver_remove_nogem(struct intel_display *display)
{
struct intel_display *display = &i915->display;
intel_dmc_fini(display);
intel_power_domains_driver_remove(i915);
intel_power_domains_driver_remove(display);
intel_vga_unregister(display);
intel_bios_driver_remove(display);
}
void intel_display_driver_unregister(struct drm_i915_private *i915)
void intel_display_driver_unregister(struct intel_display *display)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
drm_client_dev_unregister(&i915->drm);
drm_client_dev_unregister(display->drm);
/*
* After flushing the fbdev (incl. a late async config which
* will have delayed queuing of a hotplug event), then flush
* the hotplug events.
*/
drm_kms_helper_poll_fini(&i915->drm);
drm_kms_helper_poll_fini(display->drm);
intel_display_driver_disable_user_access(i915);
intel_display_driver_disable_user_access(display);
intel_audio_deinit(i915);
drm_atomic_helper_shutdown(&i915->drm);
drm_atomic_helper_shutdown(display->drm);
acpi_video_unregister();
intel_opregion_unregister(display);
@ -661,30 +668,36 @@ void intel_display_driver_unregister(struct drm_i915_private *i915)
* turn all crtc's off, but do not adjust state
* This has to be paired with a call to intel_modeset_setup_hw_state.
*/
int intel_display_driver_suspend(struct drm_i915_private *i915)
int intel_display_driver_suspend(struct intel_display *display)
{
struct drm_atomic_state *state;
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return 0;
state = drm_atomic_helper_suspend(&i915->drm);
state = drm_atomic_helper_suspend(display->drm);
ret = PTR_ERR_OR_ZERO(state);
if (ret)
drm_err(&i915->drm, "Suspending crtc's failed with %i\n",
drm_err(display->drm, "Suspending crtc's failed with %i\n",
ret);
else
i915->display.restore.modeset_state = state;
display->restore.modeset_state = state;
/* ensure all DPT VMAs have been unpinned for intel_dpt_suspend() */
flush_workqueue(display->wq.cleanup);
intel_dp_mst_suspend(display);
return ret;
}
int
__intel_display_driver_resume(struct drm_i915_private *i915,
__intel_display_driver_resume(struct intel_display *display,
struct drm_atomic_state *state,
struct drm_modeset_acquire_ctx *ctx)
{
struct intel_display *display = &i915->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
int ret, i;
@ -710,33 +723,37 @@ __intel_display_driver_resume(struct drm_i915_private *i915,
}
/* ignore any reset values/BIOS leftovers in the WM registers */
if (!HAS_GMCH(i915))
if (!HAS_GMCH(display))
to_intel_atomic_state(state)->skip_intermediate_wm = true;
ret = drm_atomic_helper_commit_duplicated_state(state, ctx);
drm_WARN_ON(&i915->drm, ret == -EDEADLK);
drm_WARN_ON(display->drm, ret == -EDEADLK);
return ret;
}
void intel_display_driver_resume(struct drm_i915_private *i915)
void intel_display_driver_resume(struct intel_display *display)
{
struct drm_atomic_state *state = i915->display.restore.modeset_state;
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_atomic_state *state = display->restore.modeset_state;
struct drm_modeset_acquire_ctx ctx;
int ret;
if (!HAS_DISPLAY(i915))
if (!HAS_DISPLAY(display))
return;
i915->display.restore.modeset_state = NULL;
/* MST sideband requires HPD interrupts enabled */
intel_dp_mst_resume(display);
display->restore.modeset_state = NULL;
if (state)
state->acquire_ctx = &ctx;
drm_modeset_acquire_init(&ctx, 0);
while (1) {
ret = drm_modeset_lock_all_ctx(&i915->drm, &ctx);
ret = drm_modeset_lock_all_ctx(display->drm, &ctx);
if (ret != -EDEADLK)
break;
@ -744,14 +761,14 @@ void intel_display_driver_resume(struct drm_i915_private *i915)
}
if (!ret)
ret = __intel_display_driver_resume(i915, state, &ctx);
ret = __intel_display_driver_resume(display, state, &ctx);
skl_watermark_ipc_update(i915);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
if (ret)
drm_err(&i915->drm,
drm_err(display->drm,
"Restoring old state failed with %i\n", ret);
if (state)
drm_atomic_state_put(state);

View File

@ -9,34 +9,34 @@
#include <linux/types.h>
struct drm_atomic_state;
struct drm_i915_private;
struct drm_modeset_acquire_ctx;
struct intel_display;
struct pci_dev;
bool intel_display_driver_probe_defer(struct pci_dev *pdev);
void intel_display_driver_init_hw(struct drm_i915_private *i915);
void intel_display_driver_early_probe(struct drm_i915_private *i915);
int intel_display_driver_probe_noirq(struct drm_i915_private *i915);
int intel_display_driver_probe_nogem(struct drm_i915_private *i915);
int intel_display_driver_probe(struct drm_i915_private *i915);
void intel_display_driver_register(struct drm_i915_private *i915);
void intel_display_driver_remove(struct drm_i915_private *i915);
void intel_display_driver_remove_noirq(struct drm_i915_private *i915);
void intel_display_driver_remove_nogem(struct drm_i915_private *i915);
void intel_display_driver_unregister(struct drm_i915_private *i915);
int intel_display_driver_suspend(struct drm_i915_private *i915);
void intel_display_driver_resume(struct drm_i915_private *i915);
void intel_display_driver_init_hw(struct intel_display *display);
void intel_display_driver_early_probe(struct intel_display *display);
int intel_display_driver_probe_noirq(struct intel_display *display);
int intel_display_driver_probe_nogem(struct intel_display *display);
int intel_display_driver_probe(struct intel_display *display);
void intel_display_driver_register(struct intel_display *display);
void intel_display_driver_remove(struct intel_display *display);
void intel_display_driver_remove_noirq(struct intel_display *display);
void intel_display_driver_remove_nogem(struct intel_display *display);
void intel_display_driver_unregister(struct intel_display *display);
int intel_display_driver_suspend(struct intel_display *display);
void intel_display_driver_resume(struct intel_display *display);
/* interface for intel_display_reset.c */
int __intel_display_driver_resume(struct drm_i915_private *i915,
int __intel_display_driver_resume(struct intel_display *display,
struct drm_atomic_state *state,
struct drm_modeset_acquire_ctx *ctx);
void intel_display_driver_enable_user_access(struct drm_i915_private *i915);
void intel_display_driver_disable_user_access(struct drm_i915_private *i915);
void intel_display_driver_suspend_access(struct drm_i915_private *i915);
void intel_display_driver_resume_access(struct drm_i915_private *i915);
bool intel_display_driver_check_access(struct drm_i915_private *i915);
void intel_display_driver_enable_user_access(struct intel_display *display);
void intel_display_driver_disable_user_access(struct intel_display *display);
void intel_display_driver_suspend_access(struct intel_display *display);
void intel_display_driver_resume_access(struct intel_display *display);
bool intel_display_driver_check_access(struct intel_display *display);
#endif /* __INTEL_DISPLAY_DRIVER_H__ */

View File

@ -434,7 +434,8 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
spin_lock(&dev_priv->irq_lock);
if (!dev_priv->display.irq.display_irqs_enabled) {
if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
!dev_priv->display.irq.vlv_display_irqs_enabled) {
spin_unlock(&dev_priv->irq_lock);
return;
}
@ -843,7 +844,9 @@ static u32 gen8_de_port_aux_mask(struct drm_i915_private *dev_priv)
static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
{
if (DISPLAY_VER(dev_priv) >= 14)
struct intel_display *display = &dev_priv->display;
if (DISPLAY_VER(display) >= 14)
return MTL_PIPEDMC_ATS_FAULT |
MTL_PLANE_ATS_FAULT |
GEN12_PIPEDMC_FAULT |
@ -853,7 +856,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
if (DISPLAY_VER(dev_priv) >= 13 || HAS_D12_PLANE_MINIMIZATION(dev_priv))
if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display))
return GEN12_PIPEDMC_FAULT |
GEN9_PIPE_CURSOR_FAULT |
GEN11_PIPE_PLANE5_FAULT |
@ -861,7 +864,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
else if (DISPLAY_VER(dev_priv) == 12)
else if (DISPLAY_VER(display) == 12)
return GEN12_PIPEDMC_FAULT |
GEN9_PIPE_CURSOR_FAULT |
GEN11_PIPE_PLANE7_FAULT |
@ -871,7 +874,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
else if (DISPLAY_VER(dev_priv) == 11)
else if (DISPLAY_VER(display) == 11)
return GEN9_PIPE_CURSOR_FAULT |
GEN11_PIPE_PLANE7_FAULT |
GEN11_PIPE_PLANE6_FAULT |
@ -880,7 +883,7 @@ static u32 gen8_de_pipe_fault_mask(struct drm_i915_private *dev_priv)
GEN9_PIPE_PLANE3_FAULT |
GEN9_PIPE_PLANE2_FAULT |
GEN9_PIPE_PLANE1_FAULT;
else if (DISPLAY_VER(dev_priv) >= 9)
else if (DISPLAY_VER(display) >= 9)
return GEN9_PIPE_CURSOR_FAULT |
GEN9_PIPE_PLANE4_FAULT |
GEN9_PIPE_PLANE3_FAULT |
@ -1420,7 +1423,6 @@ static void intel_display_vblank_dc_work(struct work_struct *work)
{
struct intel_display *display =
container_of(work, typeof(*display), irq.vblank_dc_work);
struct drm_i915_private *i915 = to_i915(display->drm);
int vblank_wa_num_pipes = READ_ONCE(display->irq.vblank_wa_num_pipes);
/*
@ -1429,7 +1431,7 @@ static void intel_display_vblank_dc_work(struct work_struct *work)
* PSR code. If DC3CO is taken into use we need take that into account
* here as well.
*/
intel_display_power_set_target_dc_state(i915, vblank_wa_num_pipes ? DC_STATE_DISABLE :
intel_display_power_set_target_dc_state(display, vblank_wa_num_pipes ? DC_STATE_DISABLE :
DC_STATE_EN_UPTO_DC6);
}
@ -1479,7 +1481,7 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
schedule_work(&display->irq.vblank_dc_work);
}
void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@ -1497,6 +1499,12 @@ void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
dev_priv->irq_mask = ~0u;
}
void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
{
if (dev_priv->display.irq.vlv_display_irqs_enabled)
_vlv_display_irq_reset(dev_priv);
}
void i9xx_display_irq_reset(struct drm_i915_private *i915)
{
if (I915_HAS_HOTPLUG(i915)) {
@ -1516,6 +1524,9 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
u32 enable_mask;
enum pipe pipe;
if (!dev_priv->display.irq.vlv_display_irqs_enabled)
return;
pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS;
i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
@ -1688,13 +1699,13 @@ void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
{
lockdep_assert_held(&dev_priv->irq_lock);
if (dev_priv->display.irq.display_irqs_enabled)
if (dev_priv->display.irq.vlv_display_irqs_enabled)
return;
dev_priv->display.irq.display_irqs_enabled = true;
dev_priv->display.irq.vlv_display_irqs_enabled = true;
if (intel_irqs_enabled(dev_priv)) {
vlv_display_irq_reset(dev_priv);
_vlv_display_irq_reset(dev_priv);
vlv_display_irq_postinstall(dev_priv);
}
}
@ -1703,13 +1714,13 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
{
lockdep_assert_held(&dev_priv->irq_lock);
if (!dev_priv->display.irq.display_irqs_enabled)
if (!dev_priv->display.irq.vlv_display_irqs_enabled)
return;
dev_priv->display.irq.display_irqs_enabled = false;
dev_priv->display.irq.vlv_display_irqs_enabled = false;
if (intel_irqs_enabled(dev_priv))
vlv_display_irq_reset(dev_priv);
_vlv_display_irq_reset(dev_priv);
}
void ilk_de_irq_postinstall(struct drm_i915_private *i915)
@ -1902,17 +1913,6 @@ void intel_display_irq_init(struct drm_i915_private *i915)
{
i915->drm.vblank_disable_immediate = true;
/*
* Most platforms treat the display irq block as an always-on power
* domain. vlv/chv can disable it at runtime and need special care to
* avoid writing any of the display block registers outside of the power
* domain. We defer setting up the display irqs in this case to the
* runtime pm.
*/
i915->display.irq.display_irqs_enabled = true;
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
i915->display.irq.display_irqs_enabled = false;
intel_hotplug_irq_init(i915);
INIT_WORK(&i915->display.irq.vblank_dc_work,

View File

@ -3,8 +3,13 @@
* Copyright © 2023 Intel Corporation
*/
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
#include <drm/drm_print.h>
#include "intel_display_params.h"
#include "i915_drv.h"
#define intel_display_param_named(name, T, perm, desc) \
module_param_named(name, intel_display_modparams.name, T, perm); \
@ -123,10 +128,10 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400,
"(0=disabled, 1=enabled) "
"Default: 1");
intel_display_param_named_unsafe(enable_dmc_wl, bool, 0400,
intel_display_param_named_unsafe(enable_dmc_wl, int, 0400,
"Enable DMC wakelock "
"(0=disabled, 1=enabled) "
"Default: 0");
"(-1=use per-chip default, 0=disabled, 1=enabled) "
"Default: -1");
__maybe_unused
static void _param_print_bool(struct drm_printer *p, const char *driver_name,

View File

@ -47,7 +47,7 @@ struct drm_printer;
param(int, enable_psr, -1, 0600) \
param(bool, psr_safest_params, false, 0400) \
param(bool, enable_psr2_sel_fetch, true, 0400) \
param(bool, enable_dmc_wl, false, 0400) \
param(int, enable_dmc_wl, -1, 0400) \
#define MEMBER(T, member, ...) T member;
struct intel_display_params {

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@ enum aux_ch;
enum port;
struct drm_i915_private;
struct i915_power_well;
struct intel_display;
struct intel_encoder;
struct seq_file;
@ -166,21 +167,21 @@ struct intel_display_power_domain_set {
for ((__domain) = 0; (__domain) < POWER_DOMAIN_NUM; (__domain)++) \
for_each_if(test_bit((__domain), (__mask)->bits))
int intel_power_domains_init(struct drm_i915_private *dev_priv);
void intel_power_domains_cleanup(struct drm_i915_private *dev_priv);
void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
void intel_power_domains_driver_remove(struct drm_i915_private *dev_priv);
void intel_power_domains_enable(struct drm_i915_private *dev_priv);
void intel_power_domains_disable(struct drm_i915_private *dev_priv);
void intel_power_domains_suspend(struct drm_i915_private *dev_priv, bool s2idle);
void intel_power_domains_resume(struct drm_i915_private *dev_priv);
void intel_power_domains_sanitize_state(struct drm_i915_private *dev_priv);
int intel_power_domains_init(struct intel_display *display);
void intel_power_domains_cleanup(struct intel_display *display);
void intel_power_domains_init_hw(struct intel_display *display, bool resume);
void intel_power_domains_driver_remove(struct intel_display *display);
void intel_power_domains_enable(struct intel_display *display);
void intel_power_domains_disable(struct intel_display *display);
void intel_power_domains_suspend(struct intel_display *display, bool s2idle);
void intel_power_domains_resume(struct intel_display *display);
void intel_power_domains_sanitize_state(struct intel_display *display);
void intel_display_power_suspend_late(struct drm_i915_private *i915);
void intel_display_power_resume_early(struct drm_i915_private *i915);
void intel_display_power_suspend(struct drm_i915_private *i915);
void intel_display_power_resume(struct drm_i915_private *i915);
void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,
void intel_display_power_suspend_late(struct intel_display *display, bool s2idle);
void intel_display_power_resume_early(struct intel_display *display);
void intel_display_power_suspend(struct intel_display *display);
void intel_display_power_resume(struct intel_display *display);
void intel_display_power_set_target_dc_state(struct intel_display *display,
u32 state);
bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,

View File

@ -3,14 +3,12 @@
* Copyright © 2022 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "vlv_sideband_reg.h"
#include "intel_display_core.h"
#include "intel_display_power_map.h"
#include "intel_display_power_well.h"
#include "intel_display_types.h"
#include "vlv_sideband_reg.h"
#define __LIST_INLINE_ELEMS(__elem_type, ...) \
((__elem_type[]) { __VA_ARGS__ })
@ -1752,9 +1750,9 @@ __set_power_wells(struct i915_power_domains *power_domains,
const struct i915_power_well_desc_list *power_well_descs,
int power_well_descs_sz)
{
struct drm_i915_private *i915 = container_of(power_domains,
struct drm_i915_private,
display.power.domains);
struct intel_display *display = container_of(power_domains,
struct intel_display,
power.domains);
u64 power_well_ids = 0;
const struct i915_power_well_desc_list *desc_list;
const struct i915_power_well_desc *desc;
@ -1778,7 +1776,7 @@ __set_power_wells(struct i915_power_domains *power_domains,
enum i915_power_well_id id = inst->id;
pw->desc = desc;
drm_WARN_ON(&i915->drm,
drm_WARN_ON(display->drm,
overflows_type(inst - desc->instances->list, pw->instance_idx));
pw->instance_idx = inst - desc->instances->list;
@ -1789,8 +1787,8 @@ __set_power_wells(struct i915_power_domains *power_domains,
if (id == DISP_PW_ID_NONE)
continue;
drm_WARN_ON(&i915->drm, id >= sizeof(power_well_ids) * 8);
drm_WARN_ON(&i915->drm, power_well_ids & BIT_ULL(id));
drm_WARN_ON(display->drm, id >= sizeof(power_well_ids) * 8);
drm_WARN_ON(display->drm, power_well_ids & BIT_ULL(id));
power_well_ids |= BIT_ULL(id);
}
@ -1811,53 +1809,53 @@ __set_power_wells(struct i915_power_domains *power_domains,
*/
int intel_display_power_map_init(struct i915_power_domains *power_domains)
{
struct drm_i915_private *i915 = container_of(power_domains,
struct drm_i915_private,
display.power.domains);
struct intel_display *display = container_of(power_domains,
struct intel_display,
power.domains);
/*
* The enabling order will be from lower to higher indexed wells,
* the disabling order is reversed.
*/
if (!HAS_DISPLAY(i915)) {
if (!HAS_DISPLAY(display)) {
power_domains->power_well_count = 0;
return 0;
}
if (DISPLAY_VER(i915) >= 30)
if (DISPLAY_VER(display) >= 30)
return set_power_wells(power_domains, xe3lpd_power_wells);
else if (DISPLAY_VER(i915) >= 20)
else if (DISPLAY_VER(display) >= 20)
return set_power_wells(power_domains, xe2lpd_power_wells);
else if (DISPLAY_VER(i915) >= 14)
else if (DISPLAY_VER(display) >= 14)
return set_power_wells(power_domains, xelpdp_power_wells);
else if (IS_DG2(i915))
else if (display->platform.dg2)
return set_power_wells(power_domains, xehpd_power_wells);
else if (DISPLAY_VER(i915) >= 13)
else if (DISPLAY_VER(display) >= 13)
return set_power_wells(power_domains, xelpd_power_wells);
else if (IS_DG1(i915))
else if (display->platform.dg1)
return set_power_wells(power_domains, dg1_power_wells);
else if (IS_ALDERLAKE_S(i915))
else if (display->platform.alderlake_s)
return set_power_wells(power_domains, adls_power_wells);
else if (IS_ROCKETLAKE(i915))
else if (display->platform.rocketlake)
return set_power_wells(power_domains, rkl_power_wells);
else if (DISPLAY_VER(i915) == 12)
else if (DISPLAY_VER(display) == 12)
return set_power_wells(power_domains, tgl_power_wells);
else if (DISPLAY_VER(i915) == 11)
else if (DISPLAY_VER(display) == 11)
return set_power_wells(power_domains, icl_power_wells);
else if (IS_GEMINILAKE(i915))
else if (display->platform.geminilake)
return set_power_wells(power_domains, glk_power_wells);
else if (IS_BROXTON(i915))
else if (display->platform.broxton)
return set_power_wells(power_domains, bxt_power_wells);
else if (DISPLAY_VER(i915) == 9)
else if (DISPLAY_VER(display) == 9)
return set_power_wells(power_domains, skl_power_wells);
else if (IS_CHERRYVIEW(i915))
else if (display->platform.cherryview)
return set_power_wells(power_domains, chv_power_wells);
else if (IS_BROADWELL(i915))
else if (display->platform.broadwell)
return set_power_wells(power_domains, bdw_power_wells);
else if (IS_HASWELL(i915))
else if (display->platform.haswell)
return set_power_wells(power_domains, hsw_power_wells);
else if (IS_VALLEYVIEW(i915))
else if (display->platform.valleyview)
return set_power_wells(power_domains, vlv_power_wells);
else if (IS_I830(i915))
else if (display->platform.i830)
return set_power_wells(power_domains, i830_power_wells);
else
return set_power_wells(power_domains, i9xx_power_wells);

File diff suppressed because it is too large Load Diff

View File

@ -10,21 +10,20 @@
#include "intel_display_power.h"
#include "intel_dpio_phy.h"
struct drm_i915_private;
struct i915_power_well_ops;
struct intel_display;
struct intel_encoder;
#define for_each_power_well(__dev_priv, __power_well) \
for ((__power_well) = (__dev_priv)->display.power.domains.power_wells; \
(__power_well) - (__dev_priv)->display.power.domains.power_wells < \
(__dev_priv)->display.power.domains.power_well_count; \
#define for_each_power_well(___display, __power_well) \
for ((__power_well) = (___display)->power.domains.power_wells; \
(__power_well) - (___display)->power.domains.power_wells < \
(___display)->power.domains.power_well_count; \
(__power_well)++)
#define for_each_power_well_reverse(__dev_priv, __power_well) \
for ((__power_well) = (__dev_priv)->display.power.domains.power_wells + \
(__dev_priv)->display.power.domains.power_well_count - 1; \
(__power_well) - (__dev_priv)->display.power.domains.power_wells >= 0; \
#define for_each_power_well_reverse(___display, __power_well) \
for ((__power_well) = (___display)->power.domains.power_wells + \
(___display)->power.domains.power_well_count - 1; \
(__power_well) - (___display)->power.domains.power_wells >= 0; \
(__power_well)--)
/*
@ -127,23 +126,23 @@ struct i915_power_well {
u8 instance_idx;
};
struct i915_power_well *lookup_power_well(struct drm_i915_private *i915,
struct i915_power_well *lookup_power_well(struct intel_display *display,
enum i915_power_well_id id);
void intel_power_well_enable(struct drm_i915_private *i915,
void intel_power_well_enable(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_disable(struct drm_i915_private *i915,
void intel_power_well_disable(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_sync_hw(struct drm_i915_private *i915,
void intel_power_well_sync_hw(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_get(struct drm_i915_private *i915,
void intel_power_well_get(struct intel_display *display,
struct i915_power_well *power_well);
void intel_power_well_put(struct drm_i915_private *i915,
void intel_power_well_put(struct intel_display *display,
struct i915_power_well *power_well);
bool intel_power_well_is_enabled(struct drm_i915_private *i915,
bool intel_power_well_is_enabled(struct intel_display *display,
struct i915_power_well *power_well);
bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well);
bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
bool intel_display_power_well_is_enabled(struct intel_display *display,
enum i915_power_well_id power_well_id);
bool intel_power_well_is_always_on(struct i915_power_well *power_well);
const char *intel_power_well_name(struct i915_power_well *power_well);
@ -152,7 +151,7 @@ int intel_power_well_refcount(struct i915_power_well *power_well);
void chv_phy_powergate_lanes(struct intel_encoder *encoder,
bool override, unsigned int mask);
bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
bool chv_phy_powergate_ch(struct intel_display *display, enum dpio_phy phy,
enum dpio_channel ch, bool override);
void gen9_enable_dc5(struct intel_display *display);

View File

@ -114,11 +114,11 @@ void intel_display_reset_finish(struct drm_i915_private *i915)
* so need a full re-initialization.
*/
intel_pps_unlock_regs_wa(display);
intel_display_driver_init_hw(i915);
intel_display_driver_init_hw(display);
intel_clock_gating_init(i915);
intel_hpd_init(i915);
ret = __intel_display_driver_resume(i915, state, ctx);
ret = __intel_display_driver_resume(display, state, ctx);
if (ret)
drm_err(&i915->drm,
"Restoring old state failed with %i\n", ret);

View File

@ -3,7 +3,9 @@
#include <linux/slab.h>
#include "i915_drv.h"
#include <drm/drm_drv.h>
#include "intel_display_core.h"
#include "intel_display_device.h"
#include "intel_display_params.h"
#include "intel_display_snapshot.h"

View File

@ -14,8 +14,8 @@
#include <linux/types.h>
#include <linux/tracepoint.h>
#include "i915_drv.h"
#include "intel_crtc.h"
#include "intel_display_core.h"
#include "intel_display_limits.h"
#include "intel_display_types.h"
#include "intel_vblank.h"

View File

@ -45,6 +45,7 @@
#include "i915_vma_types.h"
#include "intel_bios.h"
#include "intel_display.h"
#include "intel_display_conversion.h"
#include "intel_display_limits.h"
#include "intel_display_power.h"
#include "intel_dpll_mgr.h"
@ -301,6 +302,15 @@ struct intel_panel_bl_funcs {
u32 (*hz_to_pwm)(struct intel_connector *connector, u32 hz);
};
/* in 100us units */
struct intel_pps_delays {
u16 power_up; /* eDP: T1+T3, LVDS: T1+T2 */
u16 backlight_on; /* eDP: T8, LVDS: T5 */
u16 backlight_off; /* eDP: T9, LVDS: T6/TX */
u16 power_down; /* eDP: T10, LVDS: T3 */
u16 power_cycle; /* eDP: T11+T12, LVDS: T7+T4 */
};
enum drrs_type {
DRRS_TYPE_NONE,
DRRS_TYPE_STATIC,
@ -328,7 +338,7 @@ struct intel_vbt_panel_data {
int preemphasis;
int vswing;
int bpp;
struct edp_power_seq pps;
struct intel_pps_delays pps;
u8 drrs_msa_timing_delay;
bool low_vswing;
bool hobl;
@ -587,6 +597,8 @@ struct intel_atomic_state {
bool skip_intermediate_wm;
bool rps_interactive;
struct work_struct cleanup_work;
};
struct intel_plane_state {
@ -697,8 +709,8 @@ struct intel_initial_plane_config {
};
struct intel_scaler {
int in_use;
u32 mode;
bool in_use;
};
struct intel_crtc_scaler_state {
@ -769,6 +781,7 @@ struct skl_wm_level {
u8 lines;
bool enable;
bool ignore_lines;
bool auto_min_alloc_wm_enable;
bool can_sagv;
};
@ -863,6 +876,13 @@ struct intel_crtc_wm_state {
struct skl_ddb_entry plane_ddb[I915_MAX_PLANES];
/* pre-icl: for planar Y */
struct skl_ddb_entry plane_ddb_y[I915_MAX_PLANES];
/*
* xe3: Minimum amount of display blocks and minimum
* sagv allocation required for async flip
*/
u16 plane_min_ddb[I915_MAX_PLANES];
u16 plane_interim_ddb[I915_MAX_PLANES];
} skl;
struct {
@ -1235,7 +1255,7 @@ struct intel_crtc_state {
/* Display Stream compression state */
struct {
bool compression_enable;
bool dsc_split;
int num_streams;
/* Compressed Bpp in U6.4 format (first 4 bits for fractional part) */
u16 compressed_bpp_x16;
u8 slice_count;
@ -1568,8 +1588,8 @@ struct intel_pps {
* requiring a reinitialization. Only relevant on BXT+.
*/
bool bxt_pps_reset;
struct edp_power_seq pps_delays;
struct edp_power_seq bios_pps_delays;
struct intel_pps_delays pps_delays;
struct intel_pps_delays bios_pps_delays;
};
struct intel_psr {
@ -1803,11 +1823,13 @@ struct intel_lspcon {
struct intel_digital_port {
struct intel_encoder base;
u32 saved_port_bits;
struct intel_dp dp;
struct intel_hdmi hdmi;
struct intel_lspcon lspcon;
enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
bool lane_reversal;
bool ddi_a_4_lanes;
bool release_cl2_override;
u8 max_lanes;
/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
@ -2086,7 +2108,7 @@ to_intel_frontbuffer(struct drm_framebuffer *fb)
* intel_display pointer.
*/
#define __drm_device_to_intel_display(p) \
((p) ? &to_i915(p)->display : NULL)
((p) ? __drm_to_display(p) : NULL)
#define __device_to_intel_display(p) \
__drm_device_to_intel_display(dev_get_drvdata(p))
#define __pci_dev_to_intel_display(p) \

View File

@ -638,8 +638,6 @@ void intel_dmc_disable_program(struct intel_display *display)
pipedmc_clock_gating_wa(display, true);
disable_all_event_handlers(display);
pipedmc_clock_gating_wa(display, false);
intel_dmc_wl_disable(display);
}
void assert_dmc_loaded(struct intel_display *display)
@ -1146,8 +1144,6 @@ void intel_dmc_suspend(struct intel_display *display)
if (dmc)
flush_work(&dmc->work);
intel_dmc_wl_disable(display);
/* Drop the reference held in case DMC isn't loaded. */
if (!intel_dmc_has_payload(display))
intel_dmc_runtime_pm_put(display);

View File

@ -5,6 +5,10 @@
#include <linux/kernel.h>
#include <drm/drm_print.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_dmc.h"
#include "intel_dmc_regs.h"
@ -39,7 +43,11 @@
* potential future use.
*/
#define DMC_WAKELOCK_CTL_TIMEOUT 5
/*
* Define DMC_WAKELOCK_CTL_TIMEOUT_US in microseconds because we use the
* atomic variant of waiting MMIO.
*/
#define DMC_WAKELOCK_CTL_TIMEOUT_US 5000
#define DMC_WAKELOCK_HOLD_TIME 50
struct intel_dmc_wl_range {
@ -47,8 +55,90 @@ struct intel_dmc_wl_range {
u32 end;
};
static struct intel_dmc_wl_range lnl_wl_range[] = {
static struct intel_dmc_wl_range powered_off_ranges[] = {
{ .start = 0x60000, .end = 0x7ffff },
{},
};
static struct intel_dmc_wl_range xe3lpd_dc5_dc6_dmc_ranges[] = {
{ .start = 0x45500 }, /* DC_STATE_SEL */
{ .start = 0x457a0, .end = 0x457b0 }, /* DC*_RESIDENCY_COUNTER */
{ .start = 0x45504 }, /* DC_STATE_EN */
{ .start = 0x45400, .end = 0x4540c }, /* PWR_WELL_CTL_* */
{ .start = 0x454f0 }, /* RETENTION_CTRL */
/* DBUF_CTL_* */
{ .start = 0x44300 },
{ .start = 0x44304 },
{ .start = 0x44f00 },
{ .start = 0x44f04 },
{ .start = 0x44fe8 },
{ .start = 0x45008 },
{ .start = 0x46070 }, /* CDCLK_PLL_ENABLE */
{ .start = 0x46000 }, /* CDCLK_CTL */
{ .start = 0x46008 }, /* CDCLK_SQUASH_CTL */
/* TRANS_CMTG_CTL_* */
{ .start = 0x6fa88 },
{ .start = 0x6fb88 },
{ .start = 0x46430 }, /* CHICKEN_DCPR_1 */
{ .start = 0x46434 }, /* CHICKEN_DCPR_2 */
{ .start = 0x454a0 }, /* CHICKEN_DCPR_4 */
{ .start = 0x42084 }, /* CHICKEN_MISC_2 */
{ .start = 0x42088 }, /* CHICKEN_MISC_3 */
{ .start = 0x46160 }, /* CMTG_CLK_SEL */
{ .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */
{},
};
static struct intel_dmc_wl_range xe3lpd_dc3co_dmc_ranges[] = {
{ .start = 0x454a0 }, /* CHICKEN_DCPR_4 */
{ .start = 0x45504 }, /* DC_STATE_EN */
/* DBUF_CTL_* */
{ .start = 0x44300 },
{ .start = 0x44304 },
{ .start = 0x44f00 },
{ .start = 0x44f04 },
{ .start = 0x44fe8 },
{ .start = 0x45008 },
{ .start = 0x46070 }, /* CDCLK_PLL_ENABLE */
{ .start = 0x46000 }, /* CDCLK_CTL */
{ .start = 0x46008 }, /* CDCLK_SQUASH_CTL */
{ .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */
/* Scanline registers */
{ .start = 0x70000 },
{ .start = 0x70004 },
{ .start = 0x70014 },
{ .start = 0x70018 },
{ .start = 0x71000 },
{ .start = 0x71004 },
{ .start = 0x71014 },
{ .start = 0x71018 },
{ .start = 0x72000 },
{ .start = 0x72004 },
{ .start = 0x72014 },
{ .start = 0x72018 },
{ .start = 0x73000 },
{ .start = 0x73004 },
{ .start = 0x73014 },
{ .start = 0x73018 },
{ .start = 0x7b000 },
{ .start = 0x7b004 },
{ .start = 0x7b014 },
{ .start = 0x7b018 },
{ .start = 0x7c000 },
{ .start = 0x7c004 },
{ .start = 0x7c014 },
{ .start = 0x7c018 },
{},
};
static void __intel_dmc_wl_release(struct intel_display *display)
@ -72,15 +162,18 @@ static void intel_dmc_wl_work(struct work_struct *work)
spin_lock_irqsave(&wl->lock, flags);
/* Bail out if refcount reached zero while waiting for the spinlock */
if (!refcount_read(&wl->refcount))
/*
* Bail out if refcount became non-zero while waiting for the spinlock,
* meaning that the lock is now taken again.
*/
if (refcount_read(&wl->refcount))
goto out_unlock;
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, DMC_WAKELOCK_CTL_REQ, 0);
if (__intel_de_wait_for_register_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK, 0,
DMC_WAKELOCK_CTL_TIMEOUT)) {
if (__intel_de_wait_for_register_atomic_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK, 0,
DMC_WAKELOCK_CTL_TIMEOUT_US)) {
WARN_RATELIMIT(1, "DMC wakelock release timed out");
goto out_unlock;
}
@ -91,38 +184,110 @@ static void intel_dmc_wl_work(struct work_struct *work)
spin_unlock_irqrestore(&wl->lock, flags);
}
static bool intel_dmc_wl_check_range(u32 address)
static void __intel_dmc_wl_take(struct intel_display *display)
{
int i;
bool wl_needed = false;
struct intel_dmc_wl *wl = &display->wl;
for (i = 0; i < ARRAY_SIZE(lnl_wl_range); i++) {
if (address >= lnl_wl_range[i].start &&
address <= lnl_wl_range[i].end) {
wl_needed = true;
break;
}
/*
* Only try to take the wakelock if it's not marked as taken
* yet. It may be already taken at this point if we have
* already released the last reference, but the work has not
* run yet.
*/
if (wl->taken)
return;
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, 0,
DMC_WAKELOCK_CTL_REQ);
/*
* We need to use the atomic variant of the waiting routine
* because the DMC wakelock is also taken in atomic context.
*/
if (__intel_de_wait_for_register_atomic_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_TIMEOUT_US)) {
WARN_RATELIMIT(1, "DMC wakelock ack timed out");
return;
}
return wl_needed;
wl->taken = true;
}
static bool intel_dmc_wl_reg_in_range(i915_reg_t reg,
const struct intel_dmc_wl_range ranges[])
{
u32 offset = i915_mmio_reg_offset(reg);
for (int i = 0; ranges[i].start; i++) {
u32 end = ranges[i].end ?: ranges[i].start;
if (ranges[i].start <= offset && offset <= end)
return true;
}
return false;
}
static bool intel_dmc_wl_check_range(i915_reg_t reg, u32 dc_state)
{
const struct intel_dmc_wl_range *ranges;
/*
* Check that the offset is in one of the ranges for which
* registers are powered off during DC states.
*/
if (intel_dmc_wl_reg_in_range(reg, powered_off_ranges))
return true;
/*
* Check that the offset is for a register that is touched by
* the DMC and requires a DC exit for proper access.
*/
switch (dc_state) {
case DC_STATE_EN_DC3CO:
ranges = xe3lpd_dc3co_dmc_ranges;
break;
case DC_STATE_EN_UPTO_DC5:
case DC_STATE_EN_UPTO_DC6:
ranges = xe3lpd_dc5_dc6_dmc_ranges;
break;
default:
ranges = NULL;
}
if (ranges && intel_dmc_wl_reg_in_range(reg, ranges))
return true;
return false;
}
static bool __intel_dmc_wl_supported(struct intel_display *display)
{
if (DISPLAY_VER(display) < 20 ||
!intel_dmc_has_payload(display) ||
!display->params.enable_dmc_wl)
return false;
return display->params.enable_dmc_wl && intel_dmc_has_payload(display);
}
return true;
static void intel_dmc_wl_sanitize_param(struct intel_display *display)
{
if (!HAS_DMC_WAKELOCK(display))
display->params.enable_dmc_wl = 0;
else if (display->params.enable_dmc_wl >= 0)
display->params.enable_dmc_wl = !!display->params.enable_dmc_wl;
else
display->params.enable_dmc_wl = DISPLAY_VER(display) >= 30;
drm_dbg_kms(display->drm, "Sanitized enable_dmc_wl value: %d\n",
display->params.enable_dmc_wl);
}
void intel_dmc_wl_init(struct intel_display *display)
{
struct intel_dmc_wl *wl = &display->wl;
/* don't call __intel_dmc_wl_supported(), DMC is not loaded yet */
if (DISPLAY_VER(display) < 20 || !display->params.enable_dmc_wl)
intel_dmc_wl_sanitize_param(display);
if (!display->params.enable_dmc_wl)
return;
INIT_DELAYED_WORK(&wl->work, intel_dmc_wl_work);
@ -130,7 +295,8 @@ void intel_dmc_wl_init(struct intel_display *display)
refcount_set(&wl->refcount, 0);
}
void intel_dmc_wl_enable(struct intel_display *display)
/* Must only be called as part of enabling dynamic DC states. */
void intel_dmc_wl_enable(struct intel_display *display, u32 dc_state)
{
struct intel_dmc_wl *wl = &display->wl;
unsigned long flags;
@ -140,7 +306,9 @@ void intel_dmc_wl_enable(struct intel_display *display)
spin_lock_irqsave(&wl->lock, flags);
if (wl->enabled)
wl->dc_state = dc_state;
if (drm_WARN_ON(display->drm, wl->enabled))
goto out_unlock;
/*
@ -151,12 +319,29 @@ void intel_dmc_wl_enable(struct intel_display *display)
__intel_de_rmw_nowl(display, DMC_WAKELOCK_CFG, 0, DMC_WAKELOCK_CFG_ENABLE);
wl->enabled = true;
wl->taken = false;
/*
* This would be racy in the following scenario:
*
* 1. Function A calls intel_dmc_wl_get();
* 2. Some function calls intel_dmc_wl_disable();
* 3. Some function calls intel_dmc_wl_enable();
* 4. Concurrently with (3), function A performs the MMIO in between
* setting DMC_WAKELOCK_CFG_ENABLE and asserting the lock with
* __intel_dmc_wl_take().
*
* TODO: Check with the hardware team whether it is safe to assert the
* hardware lock before enabling to avoid such a scenario. Otherwise, we
* would need to deal with it via software synchronization.
*/
if (refcount_read(&wl->refcount))
__intel_dmc_wl_take(display);
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
}
/* Must only be called as part of disabling dynamic DC states. */
void intel_dmc_wl_disable(struct intel_display *display)
{
struct intel_dmc_wl *wl = &display->wl;
@ -165,24 +350,44 @@ void intel_dmc_wl_disable(struct intel_display *display)
if (!__intel_dmc_wl_supported(display))
return;
flush_delayed_work(&wl->work);
intel_dmc_wl_flush_release_work(display);
spin_lock_irqsave(&wl->lock, flags);
if (!wl->enabled)
if (drm_WARN_ON(display->drm, !wl->enabled))
goto out_unlock;
/* Disable wakelock in DMC */
__intel_de_rmw_nowl(display, DMC_WAKELOCK_CFG, DMC_WAKELOCK_CFG_ENABLE, 0);
refcount_set(&wl->refcount, 0);
wl->enabled = false;
/*
* The spec is not explicit about the expectation of existing
* lock users at the moment of disabling, but it does say that we must
* clear DMC_WAKELOCK_CTL_REQ, which gives us a clue that it is okay to
* disable with existing lock users.
*
* TODO: Get the correct expectation from the hardware team.
*/
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, DMC_WAKELOCK_CTL_REQ, 0);
wl->taken = false;
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
}
void intel_dmc_wl_flush_release_work(struct intel_display *display)
{
struct intel_dmc_wl *wl = &display->wl;
if (!__intel_dmc_wl_supported(display))
return;
flush_delayed_work(&wl->work);
}
void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
{
struct intel_dmc_wl *wl = &display->wl;
@ -191,14 +396,17 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
if (!__intel_dmc_wl_supported(display))
return;
if (!intel_dmc_wl_check_range(reg.reg))
return;
spin_lock_irqsave(&wl->lock, flags);
if (!wl->enabled)
if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
goto out_unlock;
if (!wl->enabled) {
if (!refcount_inc_not_zero(&wl->refcount))
refcount_set(&wl->refcount, 1);
goto out_unlock;
}
cancel_delayed_work(&wl->work);
if (refcount_inc_not_zero(&wl->refcount))
@ -206,26 +414,7 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
refcount_set(&wl->refcount, 1);
/*
* Only try to take the wakelock if it's not marked as taken
* yet. It may be already taken at this point if we have
* already released the last reference, but the work has not
* run yet.
*/
if (!wl->taken) {
__intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, 0,
DMC_WAKELOCK_CTL_REQ);
if (__intel_de_wait_for_register_nowl(display, DMC_WAKELOCK1_CTL,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_ACK,
DMC_WAKELOCK_CTL_TIMEOUT)) {
WARN_RATELIMIT(1, "DMC wakelock ack timed out");
goto out_unlock;
}
wl->taken = true;
}
__intel_dmc_wl_take(display);
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
@ -239,12 +428,9 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
if (!__intel_dmc_wl_supported(display))
return;
if (!intel_dmc_wl_check_range(reg.reg))
return;
spin_lock_irqsave(&wl->lock, flags);
if (!wl->enabled)
if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
goto out_unlock;
if (WARN_RATELIMIT(!refcount_read(&wl->refcount),
@ -252,6 +438,9 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
goto out_unlock;
if (refcount_dec_and_test(&wl->refcount)) {
if (!wl->enabled)
goto out_unlock;
__intel_dmc_wl_release(display);
goto out_unlock;
@ -260,3 +449,13 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
out_unlock:
spin_unlock_irqrestore(&wl->lock, flags);
}
void intel_dmc_wl_get_noreg(struct intel_display *display)
{
intel_dmc_wl_get(display, INVALID_MMIO_REG);
}
void intel_dmc_wl_put_noreg(struct intel_display *display)
{
intel_dmc_wl_put(display, INVALID_MMIO_REG);
}

View File

@ -15,17 +15,27 @@
struct intel_display;
struct intel_dmc_wl {
spinlock_t lock; /* protects enabled, taken and refcount */
spinlock_t lock; /* protects enabled, taken, dc_state and refcount */
bool enabled;
bool taken;
refcount_t refcount;
/*
* We are keeping a copy of the enabled DC state because
* intel_display.power.domains is protected by a mutex and we do
* not want call mutex_lock() in atomic context, where some of
* the tracked MMIO operations happen.
*/
u32 dc_state;
struct delayed_work work;
};
void intel_dmc_wl_init(struct intel_display *display);
void intel_dmc_wl_enable(struct intel_display *display);
void intel_dmc_wl_enable(struct intel_display *display, u32 dc_state);
void intel_dmc_wl_disable(struct intel_display *display);
void intel_dmc_wl_flush_release_work(struct intel_display *display);
void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg);
void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg);
void intel_dmc_wl_get_noreg(struct intel_display *display);
void intel_dmc_wl_put_noreg(struct intel_display *display);
#endif /* __INTEL_WAKELOCK_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -12,14 +12,14 @@ enum intel_output_format;
enum pipe;
enum port;
struct drm_connector_state;
struct drm_encoder;
struct drm_i915_private;
struct drm_modeset_acquire_ctx;
struct drm_dp_vsc_sdp;
struct drm_encoder;
struct drm_modeset_acquire_ctx;
struct intel_atomic_state;
struct intel_connector;
struct intel_crtc_state;
struct intel_digital_port;
struct intel_display;
struct intel_dp;
struct intel_encoder;
@ -87,15 +87,15 @@ bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state);
bool intel_dp_has_dsc(const struct intel_connector *connector);
int intel_dp_link_symbol_size(int rate);
int intel_dp_link_symbol_clock(int rate);
bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
bool intel_dp_is_port_edp(struct intel_display *display, enum port port);
enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port,
bool long_hpd);
void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
void intel_edp_backlight_off(const struct drm_connector_state *conn_state);
void intel_edp_fixup_vbt_bpp(struct intel_encoder *encoder, int pipe_bpp);
void intel_dp_mst_suspend(struct drm_i915_private *dev_priv);
void intel_dp_mst_resume(struct drm_i915_private *dev_priv);
void intel_dp_mst_suspend(struct intel_display *display);
void intel_dp_mst_resume(struct intel_display *display);
int intel_dp_max_source_lane_count(struct intel_digital_port *dig_port);
int intel_dp_max_link_rate(struct intel_dp *intel_dp);
int intel_dp_max_lane_count(struct intel_dp *intel_dp);
@ -112,15 +112,15 @@ void intel_dp_reset_link_params(struct intel_dp *intel_dp);
void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
u8 *link_bw, u8 *rate_select);
bool intel_dp_source_supports_tps3(struct drm_i915_private *i915);
bool intel_dp_source_supports_tps4(struct drm_i915_private *i915);
bool intel_dp_source_supports_tps3(struct intel_display *display);
bool intel_dp_source_supports_tps4(struct intel_display *display);
int intel_dp_link_required(int pixel_clock, int bpp);
int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16,
int bw_overhead);
int intel_dp_max_link_data_rate(struct intel_dp *intel_dp,
int max_dprx_rate, int max_dprx_lanes);
bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915,
bool intel_dp_joiner_needs_dsc(struct intel_display *display,
int num_joined_pipes);
bool intel_dp_has_joiner(struct intel_dp *intel_dp);
bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state,
@ -137,7 +137,7 @@ bool intel_digital_port_connected(struct intel_encoder *encoder);
bool intel_digital_port_connected_locked(struct intel_encoder *encoder);
int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector,
u8 dsc_max_bpc);
u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
u16 intel_dp_dsc_get_max_compressed_bpp(struct intel_display *display,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
int num_joined_pipes,
@ -173,7 +173,7 @@ bool intel_dp_supports_fec(struct intel_dp *intel_dp,
bool intel_dp_supports_dsc(const struct intel_connector *connector,
const struct intel_crtc_state *crtc_state);
u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp);
u32 intel_dp_dsc_nearest_valid_bpp(struct intel_display *display, u32 bpp, u32 pipe_bpp);
void intel_ddi_update_pipe(struct intel_atomic_state *state,
struct intel_encoder *encoder,
@ -193,11 +193,11 @@ void intel_dp_invalidate_source_oui(struct intel_dp *intel_dp);
void intel_dp_wait_source_oui(struct intel_dp *intel_dp);
int intel_dp_output_bpp(enum intel_output_format output_format, int bpp);
bool
intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
bool dsc,
struct link_config_limits *limits);
bool intel_dp_compute_config_limits(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state,
bool respect_downstream_limits,
bool dsc,
struct link_config_limits *limits);
void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector);
bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder);

View File

@ -5,8 +5,6 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_trace.h"
#include "intel_bios.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
@ -15,6 +13,7 @@
#include "intel_pps.h"
#include "intel_quirks.h"
#include "intel_tc.h"
#include "intel_uncore_trace.h"
#define AUX_CH_NAME_BUFSIZE 6

View File

@ -34,8 +34,9 @@
* for some reason.
*/
#include "i915_drv.h"
#include "i915_utils.h"
#include "intel_backlight.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_aux_backlight.h"

View File

@ -25,7 +25,8 @@
#include <drm/display/drm_dp_helper.h>
#include "i915_drv.h"
#include "i915_utils.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_dp_link_training.h"
@ -221,7 +222,6 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 dpcd[DP_RECEIVER_CAP_SIZE])
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *i915 = to_i915(display->drm);
if (intel_dp_is_edp(intel_dp))
return 0;
@ -230,7 +230,7 @@ int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 dpcd[DP_RECEIVER_CAP_S
* Detecting LTTPRs must be avoided on platforms with an AUX timeout
* period < 3.2ms. (see DP Standard v2.0, 2.11.2, 3.6.6.1).
*/
if (DISPLAY_VER(display) >= 10 && !IS_GEMINILAKE(i915))
if (DISPLAY_VER(display) >= 10 && !display->platform.geminilake)
if (drm_dp_dpcd_probe(&intel_dp->aux,
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV))
return -EIO;
@ -262,7 +262,6 @@ int intel_dp_read_dprx_caps(struct intel_dp *intel_dp, u8 dpcd[DP_RECEIVER_CAP_S
int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *i915 = to_i915(display->drm);
int lttpr_count = 0;
/*
@ -270,7 +269,7 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
* period < 3.2ms. (see DP Standard v2.0, 2.11.2, 3.6.6.1).
*/
if (!intel_dp_is_edp(intel_dp) &&
(DISPLAY_VER(display) >= 10 && !IS_GEMINILAKE(i915))) {
(DISPLAY_VER(display) >= 10 && !display->platform.geminilake)) {
u8 dpcd[DP_RECEIVER_CAP_SIZE];
int err = intel_dp_read_dprx_caps(intel_dp, dpcd);
@ -391,10 +390,9 @@ static bool has_per_lane_signal_levels(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *i915 = to_i915(display->drm);
return !intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy) ||
DISPLAY_VER(display) >= 10 || IS_BROXTON(i915);
DISPLAY_VER(display) >= 10 || display->platform.broxton;
}
/* 128b/132b */
@ -898,7 +896,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
voltage_tries = 1;
for (cr_tries = 0; cr_tries < max_cr_tries; ++cr_tries) {
usleep_range(delay_us, 2 * delay_us);
fsleep(delay_us);
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
link_status) < 0) {
@ -959,7 +957,6 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp,
enum drm_dp_phy dp_phy)
{
struct intel_display *display = to_intel_display(intel_dp);
struct drm_i915_private *i915 = to_i915(display->drm);
bool source_tps3, sink_tps3, source_tps4, sink_tps4;
/* UHBR+ use separate 128b/132b TPS2 */
@ -972,7 +969,7 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp,
* TPS4 as of Feb 2018 as per VESA eDP_v1.4b_E1 specification.
* LTTPRs must support TPS4.
*/
source_tps4 = intel_dp_source_supports_tps4(i915);
source_tps4 = intel_dp_source_supports_tps4(display);
sink_tps4 = dp_phy != DP_PHY_DPRX ||
drm_dp_tps4_supported(intel_dp->dpcd);
if (source_tps4 && sink_tps4) {
@ -990,7 +987,7 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp,
* TPS3 support is mandatory for downstream devices that
* support HBR2. However, not all sinks follow the spec.
*/
source_tps3 = intel_dp_source_supports_tps3(i915);
source_tps3 = intel_dp_source_supports_tps3(display);
sink_tps3 = dp_phy != DP_PHY_DPRX ||
drm_dp_tps3_supported(intel_dp->dpcd);
if (source_tps3 && sink_tps3) {
@ -1040,7 +1037,7 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
}
for (tries = 0; tries < 5; tries++) {
usleep_range(delay_us, 2 * delay_us);
fsleep(delay_us);
if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
link_status) < 0) {
@ -1414,16 +1411,10 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
}
/* Time budget for the LANEx_EQ_DONE Sequence */
deadline = jiffies + msecs_to_jiffies_timeout(400);
deadline = jiffies + msecs_to_jiffies_timeout(450);
for (try = 0; try < max_tries; try++) {
usleep_range(delay_us, 2 * delay_us);
/*
* The delay may get updated. The transmitter shall read the
* delay before link status during link training.
*/
delay_us = drm_dp_128b132b_read_aux_rd_interval(&intel_dp->aux);
fsleep(delay_us);
if (drm_dp_dpcd_read_link_status(&intel_dp->aux, link_status) < 0) {
lt_err(intel_dp, DP_PHY_DPRX, "Failed to read link status\n");
@ -1451,8 +1442,15 @@ intel_dp_128b132b_lane_eq(struct intel_dp *intel_dp,
if (time_after(jiffies, deadline))
timeout = true; /* try one last time after deadline */
/* Update signal levels and training set as requested. */
/*
* During LT, Tx shall read AUX_RD_INTERVAL just before writing the new FFE
* presets.
*/
delay_us = drm_dp_128b132b_read_aux_rd_interval(&intel_dp->aux);
intel_dp_get_adjust_train(intel_dp, crtc_state, DP_PHY_DPRX, link_status);
/* Update signal levels and training set as requested. */
if (!intel_dp_update_link_train(intel_dp, crtc_state, DP_PHY_DPRX)) {
lt_err(intel_dp, DP_PHY_DPRX, "Failed to update TX FFE settings\n");
return false;

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,6 @@
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_de.h"

View File

@ -3,11 +3,10 @@
* Copyright © 2023 Intel Corporation
*/
#include "i915_drv.h"
#include <drm/display/drm_dp_tunnel.h>
#include "intel_atomic.h"
#include "intel_display_core.h"
#include "intel_display_limits.h"
#include "intel_display_types.h"
#include "intel_dp.h"

View File

@ -22,6 +22,7 @@
*/
#include "bxt_dpio_phy_regs.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
@ -855,6 +856,7 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder,
void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@ -871,7 +873,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
*/
if (ch == DPIO_CH0 && pipe == PIPE_B)
dig_port->release_cl2_override =
!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
!chv_phy_powergate_ch(display, DPIO_PHY0, DPIO_CH1, true);
chv_phy_powergate_lanes(encoder, true, lane_mask);
@ -1013,11 +1015,11 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
void chv_phy_release_cl2_override(struct intel_encoder *encoder)
{
struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
if (dig_port->release_cl2_override) {
chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
chv_phy_powergate_ch(display, DPIO_PHY0, DPIO_CH1, false);
dig_port->release_cl2_override = false;
}
}

View File

@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/string_helpers.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_crtc.h"

View File

@ -25,6 +25,7 @@
#include <linux/string_helpers.h>
#include "bxt_dpio_phy_regs.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"

View File

@ -205,7 +205,7 @@ void intel_dpt_resume(struct drm_i915_private *i915)
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb->dpt_vm)
i915_ggtt_resume_vm(fb->dpt_vm);
i915_ggtt_resume_vm(fb->dpt_vm, true);
}
mutex_unlock(&i915->drm.mode_config.fb_lock);
}
@ -233,7 +233,7 @@ void intel_dpt_suspend(struct drm_i915_private *i915)
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb->dpt_vm)
i915_ggtt_suspend_vm(fb->dpt_vm);
i915_ggtt_suspend_vm(fb->dpt_vm, true);
}
mutex_unlock(&i915->drm.mode_config.fb_lock);

View File

@ -3,6 +3,7 @@
* Copyright © 2023 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"

View File

@ -68,7 +68,9 @@ const char *intel_drrs_type_str(enum drrs_type drrs_type)
bool intel_cpu_transcoder_has_drrs(struct drm_i915_private *i915,
enum transcoder cpu_transcoder)
{
if (HAS_DOUBLE_BUFFERED_M_N(i915))
struct intel_display *display = &i915->display;
if (HAS_DOUBLE_BUFFERED_M_N(display))
return true;
return intel_cpu_transcoder_has_m2_n2(i915, cpu_transcoder);

View File

@ -256,15 +256,6 @@ static bool intel_dsb_prev_ins_is_write(struct intel_dsb *dsb,
return prev_opcode == opcode && prev_reg == i915_mmio_reg_offset(reg);
}
static bool intel_dsb_prev_ins_is_mmio_write(struct intel_dsb *dsb, i915_reg_t reg)
{
/* only full byte-enables can be converted to indexed writes */
return intel_dsb_prev_ins_is_write(dsb,
DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT |
DSB_BYTE_EN << DSB_BYTE_EN_SHIFT,
reg);
}
static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_t reg)
{
return intel_dsb_prev_ins_is_write(dsb,
@ -273,7 +264,7 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_
}
/**
* intel_dsb_reg_write_indexed() - Emit register wriite to the DSB context
* intel_dsb_reg_write_indexed() - Emit indexed register write to the DSB context
* @dsb: DSB context
* @reg: register address.
* @val: value.
@ -304,44 +295,23 @@ void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
* we are writing odd no of dwords, Zeros will be added in the end for
* padding.
*/
if (!intel_dsb_prev_ins_is_mmio_write(dsb, reg) &&
!intel_dsb_prev_ins_is_indexed_write(dsb, reg)) {
intel_dsb_emit(dsb, val,
(DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
(DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
if (!intel_dsb_prev_ins_is_indexed_write(dsb, reg))
intel_dsb_emit(dsb, 0, /* count */
(DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg));
} else {
if (!assert_dsb_has_room(dsb))
return;
/* convert to indexed write? */
if (intel_dsb_prev_ins_is_mmio_write(dsb, reg)) {
u32 prev_val = dsb->ins[0];
if (!assert_dsb_has_room(dsb))
return;
dsb->ins[0] = 1; /* count */
dsb->ins[1] = (DSB_OPCODE_INDEXED_WRITE << DSB_OPCODE_SHIFT) |
i915_mmio_reg_offset(reg);
/* Update the count */
dsb->ins[0]++;
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 1,
dsb->ins[1]);
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 2,
prev_val);
dsb->free_pos++;
}
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val);
/* Update the count */
dsb->ins[0]++;
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->ins_start_offset + 0,
dsb->ins[0]);
/* if number of data words is odd, then the last dword should be 0.*/
if (dsb->free_pos & 0x1)
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos, 0);
}
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos++, val);
/* if number of data words is odd, then the last dword should be 0.*/
if (dsb->free_pos & 0x1)
intel_dsb_buffer_write(&dsb->dsb_buf, dsb->free_pos, 0);
}
void intel_dsb_reg_write(struct intel_dsb *dsb,

View File

@ -745,6 +745,23 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi)
str_enabled_disabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
}
static enum mipi_dsi_pixel_format vbt_to_dsi_pixel_format(unsigned int format)
{
switch (format) {
case PIXEL_FORMAT_RGB888:
return MIPI_DSI_FMT_RGB888;
case PIXEL_FORMAT_RGB666_LOOSELY_PACKED:
return MIPI_DSI_FMT_RGB666;
case PIXEL_FORMAT_RGB666:
return MIPI_DSI_FMT_RGB666_PACKED;
case PIXEL_FORMAT_RGB565:
return MIPI_DSI_FMT_RGB565;
default:
MISSING_CASE(format);
return MIPI_DSI_FMT_RGB666;
}
}
bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
{
struct drm_device *dev = intel_dsi->base.base.dev;
@ -762,8 +779,7 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
intel_dsi->lane_count = mipi_config->lane_cnt + 1;
intel_dsi->pixel_format =
pixel_format_from_register_bits(
mipi_config->videomode_color_format << 7);
vbt_to_dsi_pixel_format(mipi_config->videomode_color_format);
intel_dsi->dual_link = mipi_config->dual_link;
intel_dsi->pixel_overlap = mipi_config->pixel_overlap;

View File

@ -318,6 +318,7 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state,
static enum drm_connector_status
intel_dvo_detect(struct drm_connector *_connector, bool force)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
@ -325,10 +326,10 @@ intel_dvo_detect(struct drm_connector *_connector, bool force)
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
connector->base.base.id, connector->base.name);
if (!intel_display_device_enabled(i915))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return connector->base.status;
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
@ -336,11 +337,11 @@ intel_dvo_detect(struct drm_connector *_connector, bool force)
static int intel_dvo_get_modes(struct drm_connector *_connector)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int num_modes;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return drm_edid_connector_add_modes(&connector->base);
/*

View File

@ -7,6 +7,7 @@
#include <drm/drm_fixed.h>
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_crtc.h"

View File

@ -496,14 +496,13 @@ static int
gmbus_xfer_read(struct intel_display *display, struct i2c_msg *msg,
u32 gmbus0_reg, u32 gmbus1_index)
{
struct drm_i915_private *i915 = to_i915(display->drm);
u8 *buf = msg->buf;
unsigned int rx_size = msg->len;
unsigned int len;
int ret;
do {
if (HAS_GMBUS_BURST_READ(i915))
if (HAS_GMBUS_BURST_READ(display))
len = min(rx_size, INTEL_GMBUS_BURST_READ_MAX_LEN);
else
len = min(rx_size, gmbus_max_xfer_size(display));

View File

@ -31,27 +31,33 @@
#define KEY_LOAD_TRIES 5
#define HDCP2_LC_RETRY_CNT 3
/* WA: 16022217614 */
static void
intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder,
struct intel_hdcp *hdcp)
intel_hdcp_adjust_hdcp_line_rekeying(struct intel_encoder *encoder,
struct intel_hdcp *hdcp,
bool enable)
{
struct intel_display *display = to_intel_display(encoder);
i915_reg_t rekey_reg;
u32 rekey_bit = 0;
/* Here we assume HDMI is in TMDS mode of operation */
if (encoder->type != INTEL_OUTPUT_HDMI)
return;
if (DISPLAY_VER(display) >= 14) {
if (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_D0, STEP_FOREVER))
intel_de_rmw(display, MTL_CHICKEN_TRANS(hdcp->cpu_transcoder),
0, HDCP_LINE_REKEY_DISABLE);
else if (IS_DISPLAY_VERx100_STEP(display, 1401, STEP_B0, STEP_FOREVER) ||
IS_DISPLAY_VERx100_STEP(display, 2000, STEP_B0, STEP_FOREVER))
intel_de_rmw(display,
TRANS_DDI_FUNC_CTL(display, hdcp->cpu_transcoder),
0, TRANS_DDI_HDCP_LINE_REKEY_DISABLE);
if (DISPLAY_VER(display) >= 30) {
rekey_reg = TRANS_DDI_FUNC_CTL(display, hdcp->cpu_transcoder);
rekey_bit = XE3_TRANS_DDI_HDCP_LINE_REKEY_DISABLE;
} else if (IS_DISPLAY_VERx100_STEP(display, 1401, STEP_B0, STEP_FOREVER) ||
IS_DISPLAY_VERx100_STEP(display, 2000, STEP_B0, STEP_FOREVER)) {
rekey_reg = TRANS_DDI_FUNC_CTL(display, hdcp->cpu_transcoder);
rekey_bit = TRANS_DDI_HDCP_LINE_REKEY_DISABLE;
} else if (IS_DISPLAY_VERx100_STEP(display, 1400, STEP_D0, STEP_FOREVER)) {
rekey_reg = CHICKEN_TRANS(display, hdcp->cpu_transcoder);
rekey_bit = HDCP_LINE_REKEY_DISABLE;
}
if (rekey_bit)
intel_de_rmw(display, rekey_reg, rekey_bit, enable ? 0 : rekey_bit);
}
static int intel_conn_to_vcpi(struct intel_atomic_state *state,
@ -343,7 +349,7 @@ static bool hdcp_key_loadable(struct intel_display *display)
/* PG1 (power well #1) needs to be enabled */
with_intel_runtime_pm(&i915->runtime_pm, wakeref)
enabled = intel_display_power_well_is_enabled(i915, id);
enabled = intel_display_power_well_is_enabled(display, id);
/*
* Another req for hdcp key loadability is enabled state of pll for
@ -1048,6 +1054,8 @@ static int intel_hdcp1_enable(struct intel_connector *connector)
return ret;
}
intel_hdcp_adjust_hdcp_line_rekeying(connector->encoder, hdcp, true);
/* Incase of authentication failures, HDCP spec expects reauth. */
for (i = 0; i < tries; i++) {
ret = intel_hdcp_auth(connector);
@ -2069,7 +2077,7 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state,
connector->base.base.id, connector->base.name,
hdcp->content_type);
intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp);
intel_hdcp_adjust_hdcp_line_rekeying(connector->encoder, hdcp, false);
ret = hdcp2_authenticate_and_encrypt(state, connector);
if (ret) {

View File

@ -1600,14 +1600,12 @@ static
bool intel_hdmi_hdcp_check_link(struct intel_digital_port *dig_port,
struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(dig_port);
int retry;
for (retry = 0; retry < 3; retry++)
if (intel_hdmi_hdcp_check_link_once(dig_port, connector))
return true;
drm_err(display->drm, "Link check failed\n");
return false;
}
@ -2556,10 +2554,10 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_device_enabled(dev_priv))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(dev_priv))
if (!intel_display_driver_check_access(display))
return connector->status;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
@ -2586,12 +2584,11 @@ static void
intel_hdmi_force(struct drm_connector *connector)
{
struct intel_display *display = to_intel_display(connector->dev);
struct drm_i915_private *i915 = to_i915(connector->dev);
drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return;
intel_hdmi_unset_edid(connector);

View File

@ -813,8 +813,10 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
*/
void intel_hpd_poll_enable(struct drm_i915_private *dev_priv)
{
struct intel_display *display = &dev_priv->display;
if (!HAS_DISPLAY(dev_priv) ||
!intel_display_device_enabled(dev_priv))
!intel_display_device_enabled(display))
return;
WRITE_ONCE(dev_priv->display.hotplug.poll_enabled, true);

View File

@ -1457,7 +1457,11 @@ void intel_hpd_enable_detection(struct intel_encoder *encoder)
void intel_hpd_irq_setup(struct drm_i915_private *i915)
{
if (i915->display.irq.display_irqs_enabled && i915->display.funcs.hotplug)
if ((IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) &&
!i915->display.irq.vlv_display_irqs_enabled)
return;
if (i915->display.funcs.hotplug)
i915->display.funcs.hotplug->hpd_irq_setup(i915);
}

View File

@ -3,7 +3,8 @@
* Copyright © 2022 Intel Corporation
*/
#include "i915_drv.h"
#include <drm/drm_device.h>
#include "intel_de.h"
#include "intel_display.h"
#include "intel_hti.h"

View File

@ -5,10 +5,9 @@
#include <drm/drm_fixed.h>
#include "i915_drv.h"
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_dp_mst.h"
#include "intel_dp_tunnel.h"

View File

@ -7,9 +7,9 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
#include "i915_drv.h"
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_display_core.h"
#include "intel_display_types.h"
#include "intel_load_detect.h"

View File

@ -29,11 +29,12 @@
#include <drm/drm_edid.h>
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_lspcon.h"
#include "intel_hdmi.h"
#include "intel_lspcon.h"
/* LSPCON OUI Vendor ID(signatures) */
#define LSPCON_VENDOR_PARADE_OUI 0x001CF8

View File

@ -57,12 +57,7 @@
/* Private structure for the integrated LVDS support */
struct intel_lvds_pps {
/* 100us units */
int t1_t2;
int t3;
int t4;
int t5;
int tx;
struct intel_pps_delays delays;
int divider;
@ -168,12 +163,12 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
val = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, 0));
pps->port = REG_FIELD_GET(PANEL_PORT_SELECT_MASK, val);
pps->t1_t2 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val);
pps->t5 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val);
pps->delays.power_up = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val);
pps->delays.backlight_on = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val);
val = intel_de_read(dev_priv, PP_OFF_DELAYS(dev_priv, 0));
pps->t3 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val);
pps->tx = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val);
pps->delays.power_down = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val);
pps->delays.backlight_off = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val);
val = intel_de_read(dev_priv, PP_DIVISOR(dev_priv, 0));
pps->divider = REG_FIELD_GET(PP_REFERENCE_DIVIDER_MASK, val);
@ -186,25 +181,30 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
if (val)
val--;
/* Convert from 100ms to 100us units */
pps->t4 = val * 1000;
pps->delays.power_cycle = val * 1000;
if (DISPLAY_VER(dev_priv) < 5 &&
pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
pps->delays.power_up == 0 &&
pps->delays.backlight_on == 0 &&
pps->delays.power_down == 0 &&
pps->delays.backlight_off == 0) {
drm_dbg_kms(&dev_priv->drm,
"Panel power timings uninitialized, "
"setting defaults\n");
/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
pps->t1_t2 = 40 * 10;
pps->t5 = 200 * 10;
pps->delays.power_up = 40 * 10;
pps->delays.backlight_on = 200 * 10;
/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
pps->t3 = 35 * 10;
pps->tx = 200 * 10;
pps->delays.power_down = 35 * 10;
pps->delays.backlight_off = 200 * 10;
}
drm_dbg(&dev_priv->drm, "LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
drm_dbg(&dev_priv->drm, "LVDS PPS:power_up %d power_down %d power_cycle %d backlight_on %d backlight_off %d "
"divider %d port %d powerdown_on_reset %d\n",
pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
pps->divider, pps->port, pps->powerdown_on_reset);
pps->delays.power_up, pps->delays.power_down,
pps->delays.power_cycle, pps->delays.backlight_on,
pps->delays.backlight_off, pps->divider,
pps->port, pps->powerdown_on_reset);
}
static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
@ -221,16 +221,17 @@ static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
intel_de_write(dev_priv, PP_ON_DELAYS(dev_priv, 0),
REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, pps->port) |
REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->t1_t2) |
REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->t5));
REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->delays.power_up) |
REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->delays.backlight_on));
intel_de_write(dev_priv, PP_OFF_DELAYS(dev_priv, 0),
REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->t3) |
REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->tx));
REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->delays.power_down) |
REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->delays.backlight_off));
intel_de_write(dev_priv, PP_DIVISOR(dev_priv, 0),
REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, pps->divider) |
REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(pps->t4, 1000) + 1));
REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK,
DIV_ROUND_UP(pps->delays.power_cycle, 1000) + 1));
}
static void intel_pre_enable_lvds(struct intel_atomic_state *state,

View File

@ -1024,5 +1024,5 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915,
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
intel_power_domains_sanitize_state(i915);
intel_power_domains_sanitize_state(display);
}

View File

@ -183,7 +183,7 @@ struct overlay_registers {
};
struct intel_overlay {
struct drm_i915_private *i915;
struct intel_display *display;
struct intel_context *context;
struct intel_crtc *crtc;
struct i915_vma *vma;
@ -205,17 +205,17 @@ struct intel_overlay {
void (*flip_complete)(struct intel_overlay *ovl);
};
static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv,
static void i830_overlay_clock_gating(struct intel_display *display,
bool enable)
{
struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
struct pci_dev *pdev = to_pci_dev(display->drm->dev);
u8 val;
/* WA_OVERLAY_CLKGATE:alm */
if (enable)
intel_de_write(dev_priv, DSPCLK_GATE_D(dev_priv), 0);
intel_de_write(display, DSPCLK_GATE_D(display), 0);
else
intel_de_write(dev_priv, DSPCLK_GATE_D(dev_priv),
intel_de_write(display, DSPCLK_GATE_D(display),
OVRUNIT_CLOCK_GATE_DISABLE);
/* WA_DISABLE_L2CACHE_CLOCK_GATING:alm */
@ -253,11 +253,11 @@ alloc_request(struct intel_overlay *overlay, void (*fn)(struct intel_overlay *))
/* overlay needs to be disable in OCMD reg */
static int intel_overlay_on(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs;
drm_WARN_ON(&dev_priv->drm, overlay->active);
drm_WARN_ON(display->drm, overlay->active);
rq = alloc_request(overlay, NULL);
if (IS_ERR(rq))
@ -271,8 +271,8 @@ static int intel_overlay_on(struct intel_overlay *overlay)
overlay->active = true;
if (IS_I830(dev_priv))
i830_overlay_clock_gating(dev_priv, false);
if (display->platform.i830)
i830_overlay_clock_gating(display, false);
*cs++ = MI_OVERLAY_FLIP | MI_OVERLAY_ON;
*cs++ = overlay->flip_addr | OFC_UPDATE;
@ -288,10 +288,12 @@ static int intel_overlay_on(struct intel_overlay *overlay)
static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
struct i915_vma *vma)
{
struct intel_display *display = overlay->display;
struct drm_i915_private *i915 = to_i915(display->drm);
enum pipe pipe = overlay->crtc->pipe;
struct intel_frontbuffer *frontbuffer = NULL;
drm_WARN_ON(&overlay->i915->drm, overlay->old_vma);
drm_WARN_ON(display->drm, overlay->old_vma);
if (vma)
frontbuffer = intel_frontbuffer_get(intel_bo_to_drm_bo(vma->obj));
@ -303,8 +305,7 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
intel_frontbuffer_put(overlay->frontbuffer);
overlay->frontbuffer = frontbuffer;
intel_frontbuffer_flip_prepare(overlay->i915,
INTEL_FRONTBUFFER_OVERLAY(pipe));
intel_frontbuffer_flip_prepare(i915, INTEL_FRONTBUFFER_OVERLAY(pipe));
overlay->old_vma = overlay->vma;
if (vma)
@ -318,20 +319,20 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
struct i915_vma *vma,
bool load_polyphase_filter)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 flip_addr = overlay->flip_addr;
u32 tmp, *cs;
drm_WARN_ON(&dev_priv->drm, !overlay->active);
drm_WARN_ON(display->drm, !overlay->active);
if (load_polyphase_filter)
flip_addr |= OFC_UPDATE;
/* check for underruns */
tmp = intel_de_read(dev_priv, DOVSTA);
tmp = intel_de_read(display, DOVSTA);
if (tmp & (1 << 17))
drm_dbg(&dev_priv->drm, "overlay underrun, DOVSTA: %x\n", tmp);
drm_dbg(display->drm, "overlay underrun, DOVSTA: %x\n", tmp);
rq = alloc_request(overlay, NULL);
if (IS_ERR(rq))
@ -355,14 +356,15 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
static void intel_overlay_release_old_vma(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct i915_vma *vma;
vma = fetch_and_zero(&overlay->old_vma);
if (drm_WARN_ON(&overlay->i915->drm, !vma))
if (drm_WARN_ON(display->drm, !vma))
return;
intel_frontbuffer_flip_complete(overlay->i915,
INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
intel_frontbuffer_flip_complete(i915, INTEL_FRONTBUFFER_OVERLAY(overlay->crtc->pipe));
i915_vma_unpin(vma);
i915_vma_put(vma);
@ -376,7 +378,7 @@ intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
static void intel_overlay_off_tail(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
intel_overlay_release_old_vma(overlay);
@ -384,8 +386,8 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
overlay->crtc = NULL;
overlay->active = false;
if (IS_I830(dev_priv))
i830_overlay_clock_gating(dev_priv, true);
if (display->platform.i830)
i830_overlay_clock_gating(display, true);
}
static void intel_overlay_last_flip_retire(struct i915_active *active)
@ -400,10 +402,11 @@ static void intel_overlay_last_flip_retire(struct i915_active *active)
/* overlay needs to be disabled in OCMD reg */
static int intel_overlay_off(struct intel_overlay *overlay)
{
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs, flip_addr = overlay->flip_addr;
drm_WARN_ON(&overlay->i915->drm, !overlay->active);
drm_WARN_ON(display->drm, !overlay->active);
/* According to intel docs the overlay hw may hang (when switching
* off) without loading the filter coeffs. It is however unclear whether
@ -452,7 +455,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
*/
static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
struct i915_request *rq;
u32 *cs;
@ -463,7 +466,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
if (!overlay->old_vma)
return 0;
if (!(intel_de_read(dev_priv, GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) {
if (!(intel_de_read(display, GEN2_ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT)) {
intel_overlay_release_old_vid_tail(overlay);
return 0;
}
@ -487,9 +490,9 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
return i915_active_wait(&overlay->last_flip);
}
void intel_overlay_reset(struct drm_i915_private *dev_priv)
void intel_overlay_reset(struct intel_display *display)
{
struct intel_overlay *overlay = dev_priv->display.overlay;
struct intel_overlay *overlay = display->overlay;
if (!overlay)
return;
@ -550,11 +553,11 @@ static int uv_vsubsampling(u32 format)
}
}
static u32 calc_swidthsw(struct drm_i915_private *dev_priv, u32 offset, u32 width)
static u32 calc_swidthsw(struct intel_display *display, u32 offset, u32 width)
{
u32 sw;
if (DISPLAY_VER(dev_priv) == 2)
if (DISPLAY_VER(display) == 2)
sw = ALIGN((offset & 31) + width, 32);
else
sw = ALIGN((offset & 63) + width, 64);
@ -789,16 +792,17 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
struct drm_i915_gem_object *new_bo,
struct drm_intel_overlay_put_image *params)
{
struct intel_display *display = overlay->display;
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct overlay_registers __iomem *regs = overlay->regs;
struct drm_i915_private *dev_priv = overlay->i915;
u32 swidth, swidthsw, sheight, ostride;
enum pipe pipe = overlay->crtc->pipe;
bool scale_changed = false;
struct i915_vma *vma;
int ret, tmp_width;
drm_WARN_ON(&dev_priv->drm,
!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
ret = intel_overlay_release_old_vid(overlay);
if (ret != 0)
@ -824,7 +828,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
oconfig |= OCONF_CC_OUT_8BIT;
if (crtc_state->gamma_enable)
oconfig |= OCONF_GAMMA2_ENABLE;
if (DISPLAY_VER(dev_priv) == 4)
if (DISPLAY_VER(display) == 4)
oconfig |= OCONF_CSC_MODE_BT709;
oconfig |= pipe == 0 ?
OCONF_PIPE_A : OCONF_PIPE_B;
@ -845,7 +849,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
tmp_width = params->src_width;
swidth = params->src_width;
swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width);
swidthsw = calc_swidthsw(display, params->offset_Y, tmp_width);
sheight = params->src_height;
iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y);
ostride = params->stride_Y;
@ -858,9 +862,9 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
swidth |= (params->src_width / uv_hscale) << 16;
sheight |= (params->src_height / uv_vscale) << 16;
tmp_U = calc_swidthsw(dev_priv, params->offset_U,
tmp_U = calc_swidthsw(display, params->offset_U,
params->src_width / uv_hscale);
tmp_V = calc_swidthsw(dev_priv, params->offset_V,
tmp_V = calc_swidthsw(display, params->offset_V,
params->src_width / uv_hscale);
swidthsw |= max(tmp_U, tmp_V) << 16;
@ -899,11 +903,11 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
int intel_overlay_switch_off(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
int ret;
drm_WARN_ON(&dev_priv->drm,
!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
ret = intel_overlay_recover_from_interrupt(overlay);
if (ret != 0)
@ -936,26 +940,24 @@ static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
static void update_pfit_vscale_ratio(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct intel_display *display = overlay->display;
u32 ratio;
/* XXX: This is not the same logic as in the xorg driver, but more in
* line with the intel documentation for the i965
*/
if (DISPLAY_VER(dev_priv) >= 4) {
u32 tmp = intel_de_read(dev_priv, PFIT_PGM_RATIOS(dev_priv));
if (DISPLAY_VER(display) >= 4) {
u32 tmp = intel_de_read(display, PFIT_PGM_RATIOS(display));
/* on i965 use the PGM reg to read out the autoscaler values */
ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK_965, tmp);
} else {
u32 tmp;
if (intel_de_read(dev_priv, PFIT_CONTROL(dev_priv)) & PFIT_VERT_AUTO_SCALE)
tmp = intel_de_read(dev_priv,
PFIT_AUTO_RATIOS(dev_priv));
if (intel_de_read(display, PFIT_CONTROL(display)) & PFIT_VERT_AUTO_SCALE)
tmp = intel_de_read(display, PFIT_AUTO_RATIOS(display));
else
tmp = intel_de_read(dev_priv,
PFIT_PGM_RATIOS(dev_priv));
tmp = intel_de_read(display, PFIT_PGM_RATIOS(display));
ratio = REG_FIELD_GET(PFIT_VERT_SCALE_MASK, tmp);
}
@ -1000,7 +1002,7 @@ static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
return 0;
}
static int check_overlay_src(struct drm_i915_private *dev_priv,
static int check_overlay_src(struct intel_display *display,
struct drm_intel_overlay_put_image *rec,
struct drm_i915_gem_object *new_bo)
{
@ -1011,7 +1013,7 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
u32 tmp;
/* check src dimensions */
if (IS_I845G(dev_priv) || IS_I830(dev_priv)) {
if (display->platform.i845g || display->platform.i830) {
if (rec->src_height > IMAGE_MAX_HEIGHT_LEGACY ||
rec->src_width > IMAGE_MAX_WIDTH_LEGACY)
return -EINVAL;
@ -1063,14 +1065,14 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
return -EINVAL;
/* stride checking */
if (IS_I830(dev_priv) || IS_I845G(dev_priv))
if (display->platform.i830 || display->platform.i845g)
stride_mask = 255;
else
stride_mask = 63;
if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
return -EINVAL;
if (DISPLAY_VER(dev_priv) == 4 && rec->stride_Y < 512)
if (DISPLAY_VER(display) == 4 && rec->stride_Y < 512)
return -EINVAL;
tmp = (rec->flags & I915_OVERLAY_TYPE_MASK) == I915_OVERLAY_YUV_PLANAR ?
@ -1114,17 +1116,17 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct intel_display *display = to_intel_display(dev);
struct drm_intel_overlay_put_image *params = data;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_overlay *overlay;
struct drm_crtc *drmmode_crtc;
struct intel_crtc *crtc;
struct drm_i915_gem_object *new_bo;
int ret;
overlay = dev_priv->display.overlay;
overlay = display->overlay;
if (!overlay) {
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
drm_dbg(display->drm, "userspace bug: no overlay\n");
return -ENODEV;
}
@ -1148,7 +1150,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
if (i915_gem_object_is_tiled(new_bo)) {
drm_dbg_kms(&dev_priv->drm,
drm_dbg_kms(display->drm,
"buffer used for overlay image can not be tiled\n");
ret = -EINVAL;
goto out_unlock;
@ -1197,7 +1199,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}
ret = check_overlay_src(dev_priv, params, new_bo);
ret = check_overlay_src(display, params, new_bo);
if (ret != 0)
goto out_unlock;
@ -1277,14 +1279,14 @@ static int check_gamma(struct drm_intel_overlay_attrs *attrs)
int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct intel_display *display = to_intel_display(dev);
struct drm_intel_overlay_attrs *attrs = data;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_overlay *overlay;
int ret;
overlay = dev_priv->display.overlay;
overlay = display->overlay;
if (!overlay) {
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
drm_dbg(display->drm, "userspace bug: no overlay\n");
return -ENODEV;
}
@ -1297,13 +1299,13 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
attrs->contrast = overlay->contrast;
attrs->saturation = overlay->saturation;
if (DISPLAY_VER(dev_priv) != 2) {
attrs->gamma0 = intel_de_read(dev_priv, OGAMC0);
attrs->gamma1 = intel_de_read(dev_priv, OGAMC1);
attrs->gamma2 = intel_de_read(dev_priv, OGAMC2);
attrs->gamma3 = intel_de_read(dev_priv, OGAMC3);
attrs->gamma4 = intel_de_read(dev_priv, OGAMC4);
attrs->gamma5 = intel_de_read(dev_priv, OGAMC5);
if (DISPLAY_VER(display) != 2) {
attrs->gamma0 = intel_de_read(display, OGAMC0);
attrs->gamma1 = intel_de_read(display, OGAMC1);
attrs->gamma2 = intel_de_read(display, OGAMC2);
attrs->gamma3 = intel_de_read(display, OGAMC3);
attrs->gamma4 = intel_de_read(display, OGAMC4);
attrs->gamma5 = intel_de_read(display, OGAMC5);
}
} else {
if (attrs->brightness < -128 || attrs->brightness > 127)
@ -1321,7 +1323,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
update_reg_attrs(overlay, overlay->regs);
if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
if (DISPLAY_VER(dev_priv) == 2)
if (DISPLAY_VER(display) == 2)
goto out_unlock;
if (overlay->active) {
@ -1333,12 +1335,12 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
if (ret)
goto out_unlock;
intel_de_write(dev_priv, OGAMC0, attrs->gamma0);
intel_de_write(dev_priv, OGAMC1, attrs->gamma1);
intel_de_write(dev_priv, OGAMC2, attrs->gamma2);
intel_de_write(dev_priv, OGAMC3, attrs->gamma3);
intel_de_write(dev_priv, OGAMC4, attrs->gamma4);
intel_de_write(dev_priv, OGAMC5, attrs->gamma5);
intel_de_write(display, OGAMC0, attrs->gamma0);
intel_de_write(display, OGAMC1, attrs->gamma1);
intel_de_write(display, OGAMC2, attrs->gamma2);
intel_de_write(display, OGAMC3, attrs->gamma3);
intel_de_write(display, OGAMC4, attrs->gamma4);
intel_de_write(display, OGAMC5, attrs->gamma5);
}
}
overlay->color_key_enabled = (attrs->flags & I915_OVERLAY_DISABLE_DEST_COLORKEY) == 0;
@ -1352,12 +1354,13 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
static int get_registers(struct intel_overlay *overlay, bool use_phys)
{
struct drm_i915_private *i915 = overlay->i915;
struct intel_display *display = overlay->display;
struct drm_i915_private *i915 = to_i915(display->drm);
struct drm_i915_gem_object *obj = ERR_PTR(-ENODEV);
struct i915_vma *vma;
int err;
if (!IS_METEORLAKE(i915)) /* Wa_22018444074 */
if (!display->platform.meteorlake) /* Wa_22018444074 */
obj = i915_gem_object_create_stolen(i915, PAGE_SIZE);
if (IS_ERR(obj))
obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
@ -1390,13 +1393,14 @@ static int get_registers(struct intel_overlay *overlay, bool use_phys)
return err;
}
void intel_overlay_setup(struct drm_i915_private *dev_priv)
void intel_overlay_setup(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_overlay *overlay;
struct intel_engine_cs *engine;
int ret;
if (!HAS_OVERLAY(dev_priv))
if (!HAS_OVERLAY(display))
return;
engine = to_gt(dev_priv)->engine[RCS0];
@ -1407,7 +1411,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
if (!overlay)
return;
overlay->i915 = dev_priv;
overlay->display = display;
overlay->context = engine->kernel_context;
overlay->color_key = 0x0101fe;
overlay->color_key_enabled = true;
@ -1418,7 +1422,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
i915_active_init(&overlay->last_flip,
NULL, intel_overlay_last_flip_retire, 0);
ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv));
ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(display));
if (ret)
goto out_free;
@ -1426,19 +1430,24 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
update_polyphase_filter(overlay->regs);
update_reg_attrs(overlay, overlay->regs);
dev_priv->display.overlay = overlay;
drm_info(&dev_priv->drm, "Initialized overlay support.\n");
display->overlay = overlay;
drm_info(display->drm, "Initialized overlay support.\n");
return;
out_free:
kfree(overlay);
}
void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
bool intel_overlay_available(struct intel_display *display)
{
return display->overlay;
}
void intel_overlay_cleanup(struct intel_display *display)
{
struct intel_overlay *overlay;
overlay = fetch_and_zero(&dev_priv->display.overlay);
overlay = fetch_and_zero(&display->overlay);
if (!overlay)
return;
@ -1447,7 +1456,7 @@ void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
* Furthermore modesetting teardown happens beforehand so the
* hardware should be off already.
*/
drm_WARN_ON(&dev_priv->drm, overlay->active);
drm_WARN_ON(display->drm, overlay->active);
i915_gem_object_put(overlay->reg_bo);
i915_active_fini(&overlay->last_flip);
@ -1467,8 +1476,7 @@ struct intel_overlay_snapshot {
struct intel_overlay_snapshot *
intel_overlay_snapshot_capture(struct intel_display *display)
{
struct drm_i915_private *dev_priv = to_i915(display->drm);
struct intel_overlay *overlay = dev_priv->display.overlay;
struct intel_overlay *overlay = display->overlay;
struct intel_overlay_snapshot *error;
if (!overlay || !overlay->active)
@ -1478,8 +1486,8 @@ intel_overlay_snapshot_capture(struct intel_display *display)
if (error == NULL)
return NULL;
error->dovsta = intel_de_read(dev_priv, DOVSTA);
error->isr = intel_de_read(dev_priv, GEN2_ISR);
error->dovsta = intel_de_read(display, DOVSTA);
error->isr = intel_de_read(display, GEN2_ISR);
error->base = overlay->flip_addr;
memcpy_fromio(&error->regs, overlay->regs, sizeof(error->regs));

View File

@ -17,19 +17,24 @@ struct intel_overlay;
struct intel_overlay_snapshot;
#ifdef I915
void intel_overlay_setup(struct drm_i915_private *dev_priv);
void intel_overlay_cleanup(struct drm_i915_private *dev_priv);
void intel_overlay_setup(struct intel_display *display);
bool intel_overlay_available(struct intel_display *display);
void intel_overlay_cleanup(struct intel_display *display);
int intel_overlay_switch_off(struct intel_overlay *overlay);
int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
void intel_overlay_reset(struct drm_i915_private *dev_priv);
void intel_overlay_reset(struct intel_display *display);
#else
static inline void intel_overlay_setup(struct drm_i915_private *dev_priv)
static inline void intel_overlay_setup(struct intel_display *display)
{
}
static inline void intel_overlay_cleanup(struct drm_i915_private *dev_priv)
static inline bool intel_overlay_available(struct intel_display *display)
{
return false;
}
static inline void intel_overlay_cleanup(struct intel_display *display)
{
}
static inline int intel_overlay_switch_off(struct intel_overlay *overlay)
@ -37,7 +42,7 @@ static inline int intel_overlay_switch_off(struct intel_overlay *overlay)
return 0;
}
static inline int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
struct drm_file *file_priv)
{
return 0;
}
@ -46,7 +51,7 @@ static inline int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
{
return 0;
}
static inline void intel_overlay_reset(struct drm_i915_private *dev_priv)
static inline void intel_overlay_reset(struct intel_display *display)
{
}
#endif

View File

@ -33,7 +33,6 @@
#include <drm/drm_edid.h>
#include "i915_drv.h"
#include "intel_backlight.h"
#include "intel_connector.h"
#include "intel_display_core.h"
@ -383,12 +382,12 @@ void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector,
enum drm_connector_status
intel_panel_detect(struct drm_connector *connector, bool force)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_display *display = to_intel_display(connector->dev);
if (!intel_display_device_enabled(i915))
if (!intel_display_device_enabled(display))
return connector_status_disconnected;
if (!intel_display_driver_check_access(i915))
if (!intel_display_driver_check_access(display))
return connector->status;
return connector_status_connected;

View File

@ -4,8 +4,10 @@
*/
#include "g4x_dp.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_crt.h"
#include "intel_crt_regs.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dpll.h"

View File

@ -3,6 +3,7 @@
* Copyright © 2021 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
@ -108,13 +109,13 @@ void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
intel_de_write(dev_priv, PIXCLK_GATE, PIXCLK_GATE_GATE);
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
temp |= SBI_SSCCTL_DISABLE;
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
struct iclkip_params {
@ -195,7 +196,7 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
"iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
clock, p.auxdiv, p.divsel, p.phasedir, p.phaseinc);
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
/* Program SSCDIVINTPHASE6 */
temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
@ -218,7 +219,7 @@ void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
temp &= ~SBI_SSCCTL_DISABLE;
intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
/* Wait for initialization time */
udelay(24);
@ -236,11 +237,11 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv)
iclkip_params_init(&p);
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
if (temp & SBI_SSCCTL_DISABLE) {
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
return 0;
}
@ -254,7 +255,7 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv)
p.auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >>
SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT;
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
p.desired_divisor = (p.divsel + 2) * p.iclk_pi_range + p.phaseinc;
@ -279,7 +280,7 @@ static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
with_fdi, "LP PCH doesn't have FDI\n"))
with_fdi = false;
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK);
tmp &= ~SBI_SSCCTL_DISABLE;
@ -302,7 +303,7 @@ static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
/* Sequence to disable CLKOUT_DP */
@ -310,7 +311,7 @@ void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
{
u32 reg, tmp;
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
@ -328,7 +329,7 @@ void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK);
}
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
#define BEND_IDX(steps) ((50 + (steps)) / 5)
@ -374,7 +375,7 @@ static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
if (drm_WARN_ON(&dev_priv->drm, idx >= ARRAY_SIZE(sscdivintphase)))
return;
mutex_lock(&dev_priv->sb_lock);
intel_sbi_lock(dev_priv);
if (steps % 10 != 0)
tmp = 0xAAAAAAAB;
@ -387,7 +388,7 @@ static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
tmp |= sscdivintphase[idx];
intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
mutex_unlock(&dev_priv->sb_lock);
intel_sbi_unlock(dev_priv);
}
#undef BEND_IDX

View File

@ -3,8 +3,8 @@
* Copyright © 2024 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "intel_display_core.h"
#include "intel_display_driver.h"
#include "intel_display_types.h"

View File

@ -28,6 +28,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include "i915_drv.h"
#include "i915_irq.h"
#include "i915_reg.h"
#include "intel_atomic.h"

View File

@ -20,10 +20,10 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
struct drm_framebuffer **fb,
struct i915_vma **vma)
{
struct drm_i915_private *i915 = to_i915(this->base.dev);
struct intel_display *display = to_intel_display(this);
struct intel_crtc *crtc;
for_each_intel_crtc(&i915->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
struct intel_plane *plane =
to_intel_plane(crtc->base.primary);
const struct intel_plane_state *plane_state =
@ -48,9 +48,10 @@ intel_reuse_initial_plane_obj(struct intel_crtc *this,
}
static bool
initial_plane_phys_lmem(struct drm_i915_private *i915,
initial_plane_phys_lmem(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
gen8_pte_t __iomem *gte = to_gt(i915)->ggtt->gsm;
struct intel_memory_region *mem;
dma_addr_t dma_addr;
@ -63,7 +64,7 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
pte = ioread64(gte);
if (!(pte & GEN12_GGTT_PTE_LM)) {
drm_err(&i915->drm,
drm_err(display->drm,
"Initial plane programming missing PTE_LM bit\n");
return false;
}
@ -75,7 +76,7 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
else
mem = i915->mm.stolen_region;
if (!mem) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Initial plane memory region not initialized\n");
return false;
}
@ -85,13 +86,13 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
* ever be placed in the stolen portion.
*/
if (dma_addr < mem->region.start || dma_addr > mem->region.end) {
drm_err(&i915->drm,
drm_err(display->drm,
"Initial plane programming using invalid range, dma_addr=%pa (%s [%pa-%pa])\n",
&dma_addr, mem->region.name, &mem->region.start, &mem->region.end);
return false;
}
drm_dbg(&i915->drm,
drm_dbg(display->drm,
"Using dma_addr=%pa, based on initial plane programming\n",
&dma_addr);
@ -102,9 +103,10 @@ initial_plane_phys_lmem(struct drm_i915_private *i915,
}
static bool
initial_plane_phys_smem(struct drm_i915_private *i915,
initial_plane_phys_smem(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_memory_region *mem;
u32 base;
@ -112,7 +114,7 @@ initial_plane_phys_smem(struct drm_i915_private *i915,
mem = i915->mm.stolen_region;
if (!mem) {
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Initial plane memory region not initialized\n");
return false;
}
@ -125,19 +127,22 @@ initial_plane_phys_smem(struct drm_i915_private *i915,
}
static bool
initial_plane_phys(struct drm_i915_private *i915,
initial_plane_phys(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
if (IS_DGFX(i915) || HAS_LMEMBAR_SMEM_STOLEN(i915))
return initial_plane_phys_lmem(i915, plane_config);
return initial_plane_phys_lmem(display, plane_config);
else
return initial_plane_phys_smem(i915, plane_config);
return initial_plane_phys_smem(display, plane_config);
}
static struct i915_vma *
initial_plane_vma(struct drm_i915_private *i915,
initial_plane_vma(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_private *i915 = to_i915(display->drm);
struct intel_memory_region *mem;
struct drm_i915_gem_object *obj;
struct drm_mm_node orig_mm = {};
@ -149,7 +154,7 @@ initial_plane_vma(struct drm_i915_private *i915,
if (plane_config->size == 0)
return NULL;
if (!initial_plane_phys(i915, plane_config))
if (!initial_plane_phys(display, plane_config))
return NULL;
phys_base = plane_config->phys_base;
@ -168,7 +173,7 @@ initial_plane_vma(struct drm_i915_private *i915,
if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) &&
mem == i915->mm.stolen_region &&
size * 2 > i915->dsm.usable_size) {
drm_dbg_kms(&i915->drm, "Initial FB size exceeds half of stolen, discarding\n");
drm_dbg_kms(display->drm, "Initial FB size exceeds half of stolen, discarding\n");
return NULL;
}
@ -176,7 +181,7 @@ initial_plane_vma(struct drm_i915_private *i915,
I915_BO_ALLOC_USER |
I915_BO_PREALLOC);
if (IS_ERR(obj)) {
drm_dbg_kms(&i915->drm, "Failed to preallocate initial FB in %s\n",
drm_dbg_kms(display->drm, "Failed to preallocate initial FB in %s\n",
mem->region.name);
return NULL;
}
@ -254,7 +259,7 @@ initial_plane_vma(struct drm_i915_private *i915,
if (drm_mm_node_allocated(&orig_mm))
drm_mm_remove_node(&orig_mm);
drm_dbg_kms(&i915->drm,
drm_dbg_kms(display->drm,
"Initial plane fb bound to 0x%x in the ggtt (original 0x%x)\n",
i915_ggtt_offset(vma), plane_config->base);
@ -271,8 +276,7 @@ static bool
intel_alloc_initial_plane_obj(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_display *display = to_intel_display(crtc);
struct drm_mode_fb_cmd2 mode_cmd = {};
struct drm_framebuffer *fb = &plane_config->fb->base;
struct i915_vma *vma;
@ -284,13 +288,13 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
case I915_FORMAT_MOD_4_TILED:
break;
default:
drm_dbg(&dev_priv->drm,
drm_dbg(display->drm,
"Unsupported modifier for initial FB: 0x%llx\n",
fb->modifier);
return false;
}
vma = initial_plane_vma(dev_priv, plane_config);
vma = initial_plane_vma(display, plane_config);
if (!vma)
return false;
@ -303,7 +307,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
if (intel_framebuffer_init(to_intel_framebuffer(fb),
intel_bo_to_drm_bo(vma->obj), &mode_cmd)) {
drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n");
drm_dbg_kms(display->drm, "intel fb init failed\n");
goto err_vma;
}
@ -410,12 +414,12 @@ static void plane_config_fini(struct intel_initial_plane_config *plane_config)
i915_vma_put(plane_config->vma);
}
void intel_initial_plane_config(struct drm_i915_private *i915)
void intel_initial_plane_config(struct intel_display *display)
{
struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
struct intel_crtc *crtc;
for_each_intel_crtc(&i915->drm, crtc) {
for_each_intel_crtc(display->drm, crtc) {
struct intel_initial_plane_config *plane_config =
&plane_configs[crtc->pipe];
@ -429,7 +433,7 @@ void intel_initial_plane_config(struct drm_i915_private *i915)
* can even allow for smooth boot transitions if the BIOS
* fb is large enough for the active pipe configuration.
*/
i915->display.funcs.display->get_initial_plane_config(crtc, plane_config);
display->funcs.display->get_initial_plane_config(crtc, plane_config);
/*
* If the fb is shared between multiple heads, we'll
@ -437,7 +441,7 @@ void intel_initial_plane_config(struct drm_i915_private *i915)
*/
intel_find_initial_plane_obj(crtc, plane_configs);
if (i915->display.funcs.display->fixup_initial_plane_config(crtc, plane_config))
if (display->funcs.display->fixup_initial_plane_config(crtc, plane_config))
intel_crtc_wait_for_next_vblank(crtc);
plane_config_fini(plane_config);

View File

@ -6,8 +6,8 @@
#ifndef __INTEL_PLANE_INITIAL_H__
#define __INTEL_PLANE_INITIAL_H__
struct drm_i915_private;
struct intel_display;
void intel_initial_plane_config(struct drm_i915_private *i915);
void intel_initial_plane_config(struct intel_display *display);
#endif

Some files were not shown because too many files have changed in this diff Show More