Merge tag 'drm-intel-next-2023-01-12' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

drm/i915 feature pull #1 for v6.3:

Features and functionality:
- Meteorlake display enabling (Animesh, Luca, Stan, Jouni, Anusha)
- DP MST DSC support (Stan)
- Gamma/degamma readout support for the state checker (Ville)
- Enable SDP split support for DP 2.0 (Vinod)
- Add probe blocking support to i915.force_probe parameter (Rodrigo)
- Enable Xe HP 4tile support (Jonathan)

Refactoring and cleanups:
- Color refactoring, especially related to DSB usage (Ville)
- DSB refactoring (Ville)
- DVO refactoring (Ville)
- Backlight register and logging cleanups (Jani)
- Avoid display direct calls to uncore (Maarten, Jani)
- Add new "soc" sub-directory (Jani)
- Refactor DSC platform support checks (Swati)

Fixes:
- Interlace modes are no longer supported starting at display version 12 (Ankit)
- Use polling read for aux control (Arun)
- DMC firmware no longer requires specific versions (Gustavo)
- Fix PSR flickering and freeze issues (Jouni)
- Fix ICL+ DSI GPIO handling (Jani)
- Ratelimit errors in display engine irqs (Lucas)
- Fix DP MST DSC bpp and timeslot calculations (Stan)
- Fix CDCLK squash and crawl sequences (Ville, Anusha)
- Fix bigjoiner checks for fused pipes (Ville)
- Fix ADP+ degamma LUT size (Ville)
- Fix DVO ch7xxx and sil164 suspend/resume (Ville)
- Fix memory leak in VBT parsing (Xia Fukun)
- Fix VBT packet port selection for dual link DSI (Mikko Kovanen)
- Fix SDP infoframe product string for discrete graphics (Clint)
- Fix VLV/CHV HDMI/DP audio enable (Ville)
- Fix VRR delays and calculations (Ville)
- No longer disable transcoder for PHY test pattern change (Khaled)
- Fix dual PPS handling (Ville)
- Fix timeout and wait for DDI BUF CTL active after enabling (Ankit)

Merges:
- Backmerge drm-next to sync up with v6.2-rc1 (Jani)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87tu0wez34.fsf@intel.com
This commit is contained in:
Dave Airlie 2023-01-17 05:23:07 +10:00
commit 0b45ac1170
65 changed files with 3131 additions and 1490 deletions

View File

@ -56,24 +56,33 @@ config DRM_I915
If "M" is selected, the module will be called i915.
config DRM_I915_FORCE_PROBE
string "Force probe driver for selected new Intel hardware"
string "Force probe i915 for selected Intel hardware IDs"
depends on DRM_I915
help
This is the default value for the i915.force_probe module
parameter. Using the module parameter overrides this option.
Force probe the driver for new Intel graphics devices that are
Force probe the i915 for Intel graphics devices that are
recognized but not properly supported by this kernel version. It is
recommended to upgrade to a kernel version with proper support as soon
as it is available.
It can also be used to block the probe of recognized and fully
supported devices.
Use "" to disable force probe. If in doubt, use this.
Use "<pci-id>[,<pci-id>,...]" to force probe the driver for listed
Use "<pci-id>[,<pci-id>,...]" to force probe the i915 for listed
devices. For example, "4500" or "4500,4571".
Use "*" to force probe the driver for all known devices.
Use "!" right before the ID to block the probe of the device. For
example, "4500,!4571" forces the probe of 4500 and blocks the probe of
4571.
Use "!*" to block the probe of the driver for all known devices.
config DRM_I915_CAPTURE_ERROR
bool "Enable capturing GPU state following a hang"
depends on DRM_I915

View File

@ -48,9 +48,7 @@ i915-y += i915_driver.o \
i915_sysfs.o \
i915_utils.o \
intel_device_info.o \
intel_dram.o \
intel_memory_region.o \
intel_pch.o \
intel_pcode.o \
intel_pm.o \
intel_region_ttm.o \
@ -62,6 +60,11 @@ i915-y += i915_driver.o \
vlv_sideband.o \
vlv_suspend.o
# core peripheral code
i915-y += \
soc/intel_dram.o \
soc/intel_pch.o
# core library code
i915-y += \
i915_memcpy.o \

View File

@ -50,15 +50,26 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define CH7xxx_INPUT_CLOCK 0x1d
#define CH7xxx_GPIO 0x1e
#define CH7xxx_GPIO_HPIR (1<<3)
#define CH7xxx_IDF 0x1f
#define CH7xxx_IDF 0x1f
#define CH7xxx_IDF_IBS (1<<7)
#define CH7xxx_IDF_DES (1<<6)
#define CH7xxx_IDF_HSP (1<<3)
#define CH7xxx_IDF_VSP (1<<4)
#define CH7xxx_CONNECTION_DETECT 0x20
#define CH7xxx_CDET_DVI (1<<5)
#define CH7301_DAC_CNTL 0x21
#define CH7xxx_DAC_CNTL 0x21
#define CH7xxx_SYNCO_MASK (3 << 3)
#define CH7xxx_SYNCO_VGA_HSYNC (1 << 3)
#define CH7xxx_CLOCK_OUTPUT 0x22
#define CH7xxx_BCOEN (1 << 4)
#define CH7xxx_BCOP (1 << 3)
#define CH7xxx_BCO_MASK (7 << 0)
#define CH7xxx_BCO_VGA_VSYNC (6 << 0)
#define CH7301_HOTPLUG 0x23
#define CH7xxx_TCTL 0x31
#define CH7xxx_TVCO 0x32
@ -301,6 +312,8 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
ch7xxx_readb(dvo, CH7xxx_IDF, &idf);
idf |= CH7xxx_IDF_IBS;
idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
idf |= CH7xxx_IDF_HSP;
@ -309,6 +322,11 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
idf |= CH7xxx_IDF_VSP;
ch7xxx_writeb(dvo, CH7xxx_IDF, idf);
ch7xxx_writeb(dvo, CH7xxx_DAC_CNTL,
CH7xxx_SYNCO_VGA_HSYNC);
ch7xxx_writeb(dvo, CH7xxx_CLOCK_OUTPUT,
CH7xxx_BCOEN | CH7xxx_BCO_VGA_VSYNC);
}
/* set the CH7xxx power state */

View File

@ -58,6 +58,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SIL164_9_MDI (1<<0)
#define SIL164_REGC 0x0c
#define SIL164_C_SCNT (1<<7)
#define SIL164_C_PLLF_MASK (0xf<<1)
#define SIL164_C_PLLF_REC (4<<1)
#define SIL164_C_PFEN (1<<0)
struct sil164_priv {
//I2CDevRec d;
@ -205,7 +209,13 @@ static void sil164_mode_set(struct intel_dvo_device *dvo,
sil164_writeb(sil, 0x0c, 0x89);
sil164_writeb(sil, 0x08, 0x31);*/
/* don't do much */
return;
sil164_writeb(dvo, SIL164_REG8,
SIL164_8_VEN | SIL164_8_HEN);
sil164_writeb(dvo, SIL164_REG9,
SIL164_9_TSEL);
sil164_writeb(dvo, SIL164_REGC,
SIL164_C_PLLF_REC | SIL164_C_PFEN);
}
/* set the SIL164 power state */
@ -224,7 +234,6 @@ static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
ch &= ~SIL164_8_PD;
sil164_writeb(dvo, SIL164_REG8, ch);
return;
}
static bool sil164_get_hw_state(struct intel_dvo_device *dvo)

View File

@ -2043,7 +2043,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
/* attach connector to encoder */
intel_connector_attach_encoder(intel_connector, encoder);
intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL);
intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL);
mutex_lock(&dev_priv->drm.mode_config.mutex);
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);

View File

@ -41,6 +41,7 @@
#include "intel_global_state.h"
#include "intel_hdcp.h"
#include "intel_psr.h"
#include "intel_fb.h"
#include "skl_universal_plane.h"
/**
@ -310,11 +311,11 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
kfree(crtc_state);
}
static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
int num_scalers_need, struct intel_crtc *intel_crtc,
const char *name, int idx,
struct intel_plane_state *plane_state,
int *scaler_id)
static int intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_state,
int num_scalers_need, struct intel_crtc *intel_crtc,
const char *name, int idx,
struct intel_plane_state *plane_state,
int *scaler_id)
{
struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
int j;
@ -334,7 +335,7 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
if (drm_WARN(&dev_priv->drm, *scaler_id < 0,
"Cannot find scaler for %s:%d\n", name, idx))
return;
return -EINVAL;
/* set scaler mode */
if (plane_state && plane_state->hw.fb &&
@ -375,9 +376,71 @@ static void intel_atomic_setup_scaler(struct intel_crtc_scaler_state *scaler_sta
mode = SKL_PS_SCALER_MODE_DYN;
}
/*
* FIXME: we should also check the scaler factors for pfit, so
* this shouldn't be tied directly to planes.
*/
if (plane_state && plane_state->hw.fb) {
const struct drm_framebuffer *fb = plane_state->hw.fb;
const struct drm_rect *src = &plane_state->uapi.src;
const struct drm_rect *dst = &plane_state->uapi.dst;
int hscale, vscale, max_vscale, max_hscale;
/*
* FIXME: When two scalers are needed, but only one of
* them needs to downscale, we should make sure that
* the one that needs downscaling support is assigned
* as the first scaler, so we don't reject downscaling
* unnecessarily.
*/
if (DISPLAY_VER(dev_priv) >= 14) {
/*
* On versions 14 and up, only the first
* scaler supports a vertical scaling factor
* of more than 1.0, while a horizontal
* scaling factor of 3.0 is supported.
*/
max_hscale = 0x30000 - 1;
if (*scaler_id == 0)
max_vscale = 0x30000 - 1;
else
max_vscale = 0x10000;
} else if (DISPLAY_VER(dev_priv) >= 10 ||
!intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
max_hscale = 0x30000 - 1;
max_vscale = 0x30000 - 1;
} else {
max_hscale = 0x20000 - 1;
max_vscale = 0x20000 - 1;
}
/*
* FIXME: We should change the if-else block above to
* support HQ vs dynamic scaler properly.
*/
/* Check if required scaling is within limits */
hscale = drm_rect_calc_hscale(src, dst, 1, max_hscale);
vscale = drm_rect_calc_vscale(src, dst, 1, max_vscale);
if (hscale < 0 || vscale < 0) {
drm_dbg_kms(&dev_priv->drm,
"Scaler %d doesn't support required plane scaling\n",
*scaler_id);
drm_rect_debug_print("src: ", src, true);
drm_rect_debug_print("dst: ", dst, false);
return -EINVAL;
}
}
drm_dbg_kms(&dev_priv->drm, "Attached scaler id %u.%u to %s:%d\n",
intel_crtc->pipe, *scaler_id, name, idx);
scaler_state->scalers[*scaler_id].mode = mode;
return 0;
}
/**
@ -437,7 +500,7 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
int *scaler_id;
const char *name;
int idx;
int idx, ret;
/* skip if scaler not required */
if (!(scaler_state->scaler_users & (1 << i)))
@ -494,9 +557,11 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
scaler_id = &plane_state->scaler_id;
}
intel_atomic_setup_scaler(scaler_state, num_scalers_need,
intel_crtc, name, idx,
plane_state, scaler_id);
ret = intel_atomic_setup_scaler(scaler_state, num_scalers_need,
intel_crtc, name, idx,
plane_state, scaler_id);
if (ret < 0)
return ret;
}
return 0;

View File

@ -798,6 +798,17 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder,
mutex_unlock(&i915->display.audio.mutex);
}
void intel_audio_sdp_split_update(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum transcoder trans = crtc_state->cpu_transcoder;
if (HAS_DP20(i915))
intel_de_rmw(i915, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT,
crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0);
}
/**
* intel_audio_codec_enable - Enable the audio codec for HD audio
* @encoder: encoder on which to enable audio

View File

@ -22,5 +22,7 @@ void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
void intel_audio_init(struct drm_i915_private *dev_priv);
void intel_audio_deinit(struct drm_i915_private *dev_priv);
void intel_audio_sdp_split_update(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_AUDIO_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -8,23 +8,20 @@
#include "intel_display_reg_defs.h"
#define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250)
#define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350)
#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \
_VLV_BLC_PWM_CTL2_B)
#define _VLV_BLC_PWM_CTL2_A (VLV_DISPLAY_BASE + 0x61250)
#define _VLV_BLC_PWM_CTL2_B (VLV_DISPLAY_BASE + 0x61350)
#define VLV_BLC_PWM_CTL2(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL2_A, _VLV_BLC_PWM_CTL2_B)
#define _VLV_BLC_PWM_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61254)
#define _VLV_BLC_PWM_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61354)
#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, \
_VLV_BLC_PWM_CTL_B)
#define _VLV_BLC_PWM_CTL_A (VLV_DISPLAY_BASE + 0x61254)
#define _VLV_BLC_PWM_CTL_B (VLV_DISPLAY_BASE + 0x61354)
#define VLV_BLC_PWM_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_PWM_CTL_A, _VLV_BLC_PWM_CTL_B)
#define _VLV_BLC_HIST_CTL_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61260)
#define _VLV_BLC_HIST_CTL_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61360)
#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, \
_VLV_BLC_HIST_CTL_B)
#define _VLV_BLC_HIST_CTL_A (VLV_DISPLAY_BASE + 0x61260)
#define _VLV_BLC_HIST_CTL_B (VLV_DISPLAY_BASE + 0x61360)
#define VLV_BLC_HIST_CTL(pipe) _MMIO_PIPE(pipe, _VLV_BLC_HIST_CTL_A, _VLV_BLC_HIST_CTL_B)
/* Backlight control */
#define BLC_PWM_CTL2 _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61250) /* 965+ only */
#define BLC_PWM_CTL2 _MMIO(0x61250) /* 965+ only */
#define BLM_PWM_ENABLE (1 << 31)
#define BLM_COMBINATION_MODE (1 << 30) /* gen4 only */
#define BLM_PIPE_SELECT (1 << 29)
@ -47,7 +44,7 @@
#define BLM_PHASE_IN_COUNT_MASK (0xff << 8)
#define BLM_PHASE_IN_INCR_SHIFT (0)
#define BLM_PHASE_IN_INCR_MASK (0xff << 0)
#define BLC_PWM_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61254)
#define BLC_PWM_CTL _MMIO(0x61254)
/*
* This is the most significant 15 bits of the number of backlight cycles in a
* complete cycle of the modulated backlight control.
@ -69,7 +66,7 @@
#define BACKLIGHT_DUTY_CYCLE_MASK_PNV (0xfffe)
#define BLM_POLARITY_PNV (1 << 0) /* pnv only */
#define BLC_HIST_CTL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61260)
#define BLC_HIST_CTL _MMIO(0x61260)
#define BLM_HISTOGRAM_ENABLE (1 << 31)
/* New registers for PCH-split platforms. Safe where new bits show up, the

View File

@ -620,14 +620,14 @@ static void dump_pnp_id(struct drm_i915_private *i915,
static int opregion_get_panel_type(struct drm_i915_private *i915,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid)
const struct edid *edid, bool use_fallback)
{
return intel_opregion_get_panel_type(i915);
}
static int vbt_get_panel_type(struct drm_i915_private *i915,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid)
const struct edid *edid, bool use_fallback)
{
const struct bdb_lvds_options *lvds_options;
@ -652,7 +652,7 @@ static int vbt_get_panel_type(struct drm_i915_private *i915,
static int pnpid_get_panel_type(struct drm_i915_private *i915,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid)
const struct edid *edid, bool use_fallback)
{
const struct bdb_lvds_lfp_data *data;
const struct bdb_lvds_lfp_data_ptrs *ptrs;
@ -701,9 +701,9 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915,
static int fallback_get_panel_type(struct drm_i915_private *i915,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid)
const struct edid *edid, bool use_fallback)
{
return 0;
return use_fallback ? 0 : -1;
}
enum panel_type {
@ -715,13 +715,13 @@ enum panel_type {
static int get_panel_type(struct drm_i915_private *i915,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid)
const struct edid *edid, bool use_fallback)
{
struct {
const char *name;
int (*get_panel_type)(struct drm_i915_private *i915,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid);
const struct edid *edid, bool use_fallback);
int panel_type;
} panel_types[] = {
[PANEL_TYPE_OPREGION] = {
@ -744,7 +744,8 @@ static int get_panel_type(struct drm_i915_private *i915,
int i;
for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, edid);
panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata,
edid, use_fallback);
drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf &&
panel_types[i].panel_type != 0xff);
@ -3183,14 +3184,26 @@ void intel_bios_init(struct drm_i915_private *i915)
kfree(oprom_vbt);
}
void intel_bios_init_panel(struct drm_i915_private *i915,
struct intel_panel *panel,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid)
static void intel_bios_init_panel(struct drm_i915_private *i915,
struct intel_panel *panel,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid,
bool use_fallback)
{
init_vbt_panel_defaults(panel);
/* already have it? */
if (panel->vbt.panel_type >= 0) {
drm_WARN_ON(&i915->drm, !use_fallback);
return;
}
panel->vbt.panel_type = get_panel_type(i915, devdata, edid);
panel->vbt.panel_type = get_panel_type(i915, devdata,
edid, use_fallback);
if (panel->vbt.panel_type < 0) {
drm_WARN_ON(&i915->drm, use_fallback);
return;
}
init_vbt_panel_defaults(panel);
parse_panel_options(i915, panel);
parse_generic_dtd(i915, panel);
@ -3205,6 +3218,21 @@ void intel_bios_init_panel(struct drm_i915_private *i915,
parse_mipi_sequence(i915, panel);
}
void intel_bios_init_panel_early(struct drm_i915_private *i915,
struct intel_panel *panel,
const struct intel_bios_encoder_data *devdata)
{
intel_bios_init_panel(i915, panel, devdata, NULL, false);
}
void intel_bios_init_panel_late(struct drm_i915_private *i915,
struct intel_panel *panel,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid)
{
intel_bios_init_panel(i915, panel, devdata, edid, true);
}
/**
* intel_bios_driver_remove - Free any resources allocated by intel_bios_init()
* @i915: i915 device instance

View File

@ -232,10 +232,13 @@ struct mipi_pps_data {
} __packed;
void intel_bios_init(struct drm_i915_private *dev_priv);
void intel_bios_init_panel(struct drm_i915_private *dev_priv,
struct intel_panel *panel,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid);
void intel_bios_init_panel_early(struct drm_i915_private *dev_priv,
struct intel_panel *panel,
const struct intel_bios_encoder_data *devdata);
void intel_bios_init_panel_late(struct drm_i915_private *dev_priv,
struct intel_panel *panel,
const struct intel_bios_encoder_data *devdata,
const struct edid *edid);
void intel_bios_fini_panel(struct intel_panel *panel);
void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
bool intel_bios_is_valid_vbt(const void *buf, size_t size);

View File

@ -1346,6 +1346,16 @@ static const struct intel_cdclk_vals dg2_cdclk_table[] = {
{}
};
static const struct intel_cdclk_vals mtl_cdclk_table[] = {
{ .refclk = 38400, .cdclk = 172800, .divider = 2, .ratio = 16, .waveform = 0xad5a },
{ .refclk = 38400, .cdclk = 192000, .divider = 2, .ratio = 16, .waveform = 0xb6b6 },
{ .refclk = 38400, .cdclk = 307200, .divider = 2, .ratio = 16, .waveform = 0x0000 },
{ .refclk = 38400, .cdclk = 480000, .divider = 2, .ratio = 25, .waveform = 0x0000 },
{ .refclk = 38400, .cdclk = 556800, .divider = 2, .ratio = 29, .waveform = 0x0000 },
{ .refclk = 38400, .cdclk = 652800, .divider = 2, .ratio = 34, .waveform = 0x0000 },
{}
};
static int bxt_calc_cdclk(struct drm_i915_private *dev_priv, int min_cdclk)
{
const struct intel_cdclk_vals *table = dev_priv->display.cdclk.table;
@ -1717,39 +1727,92 @@ static void dg2_cdclk_squash_program(struct drm_i915_private *i915,
intel_de_write(i915, CDCLK_SQUASH_CTL, squash_ctl);
}
static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
static bool cdclk_pll_is_unknown(unsigned int vco)
{
/*
* Ensure driver does not take the crawl path for the
* case when the vco is set to ~0 in the
* sanitize path.
*/
return vco == ~0;
}
static int cdclk_squash_divider(u16 waveform)
{
return hweight16(waveform ?: 0xffff);
}
static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915,
const struct intel_cdclk_config *old_cdclk_config,
const struct intel_cdclk_config *new_cdclk_config,
struct intel_cdclk_config *mid_cdclk_config)
{
u16 old_waveform, new_waveform, mid_waveform;
int size = 16;
int div = 2;
/* Return if PLL is in an unknown state, force a complete disable and re-enable. */
if (cdclk_pll_is_unknown(old_cdclk_config->vco))
return false;
/* Return if both Squash and Crawl are not present */
if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915))
return false;
old_waveform = cdclk_squash_waveform(i915, old_cdclk_config->cdclk);
new_waveform = cdclk_squash_waveform(i915, new_cdclk_config->cdclk);
/* Return if Squash only or Crawl only is the desired action */
if (old_cdclk_config->vco == 0 || new_cdclk_config->vco == 0 ||
old_cdclk_config->vco == new_cdclk_config->vco ||
old_waveform == new_waveform)
return false;
*mid_cdclk_config = *new_cdclk_config;
/*
* Populate the mid_cdclk_config accordingly.
* - If moving to a higher cdclk, the desired action is squashing.
* The mid cdclk config should have the new (squash) waveform.
* - If moving to a lower cdclk, the desired action is crawling.
* The mid cdclk config should have the new vco.
*/
if (cdclk_squash_divider(new_waveform) > cdclk_squash_divider(old_waveform)) {
mid_cdclk_config->vco = old_cdclk_config->vco;
mid_waveform = new_waveform;
} else {
mid_cdclk_config->vco = new_cdclk_config->vco;
mid_waveform = old_waveform;
}
mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) *
mid_cdclk_config->vco, size * div);
/* make sure the mid clock came out sane */
drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk <
min(old_cdclk_config->cdclk, new_cdclk_config->cdclk));
drm_WARN_ON(&i915->drm, mid_cdclk_config->cdclk >
i915->display.cdclk.max_cdclk_freq);
drm_WARN_ON(&i915->drm, cdclk_squash_waveform(i915, mid_cdclk_config->cdclk) !=
mid_waveform);
return true;
}
static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
int cdclk = cdclk_config->cdclk;
int vco = cdclk_config->vco;
u32 val;
u16 waveform;
int clock;
int ret;
/* Inform power controller of upcoming frequency change. */
if (DISPLAY_VER(dev_priv) >= 11)
ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
else
/*
* BSpec requires us to wait up to 150usec, but that leads to
* timeouts; the 2ms used here is based on experiment.
*/
ret = snb_pcode_write_timeout(&dev_priv->uncore,
HSW_PCODE_DE_WRITE_FREQ_REQ,
0x80000000, 150, 2);
if (ret) {
drm_err(&dev_priv->drm,
"Failed to inform PCU about cdclk change (err %d, freq %d)\n",
ret, cdclk);
return;
}
if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0) {
if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 &&
!cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) {
if (dev_priv->display.cdclk.hw.vco != vco)
adlp_cdclk_pll_crawl(dev_priv, vco);
} else if (DISPLAY_VER(dev_priv) >= 11)
@ -1782,11 +1845,62 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
if (pipe != INVALID_PIPE)
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe));
}
if (DISPLAY_VER(dev_priv) >= 11) {
static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
struct intel_cdclk_config mid_cdclk_config;
int cdclk = cdclk_config->cdclk;
int ret = 0;
/*
* Inform power controller of upcoming frequency change.
* Display versions 14 and beyond do not follow the PUnit
* mailbox communication, skip
* this step.
*/
if (DISPLAY_VER(dev_priv) >= 14)
/* NOOP */;
else if (DISPLAY_VER(dev_priv) >= 11)
ret = skl_pcode_request(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
SKL_CDCLK_PREPARE_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE,
SKL_CDCLK_READY_FOR_CHANGE, 3);
else
/*
* BSpec requires us to wait up to 150usec, but that leads to
* timeouts; the 2ms used here is based on experiment.
*/
ret = snb_pcode_write_timeout(&dev_priv->uncore,
HSW_PCODE_DE_WRITE_FREQ_REQ,
0x80000000, 150, 2);
if (ret) {
drm_err(&dev_priv->drm,
"Failed to inform PCU about cdclk change (err %d, freq %d)\n",
ret, cdclk);
return;
}
if (cdclk_compute_crawl_and_squash_midpoint(dev_priv, &dev_priv->display.cdclk.hw,
cdclk_config, &mid_cdclk_config)) {
_bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe);
_bxt_set_cdclk(dev_priv, cdclk_config, pipe);
} else {
_bxt_set_cdclk(dev_priv, cdclk_config, pipe);
}
if (DISPLAY_VER(dev_priv) >= 14)
/*
* NOOP - No Pcode communication needed for
* Display versions 14 and beyond
*/;
else if (DISPLAY_VER(dev_priv) >= 11)
ret = snb_pcode_write(&dev_priv->uncore, SKL_PCODE_CDCLK_CONTROL,
cdclk_config->voltage_level);
} else {
else
/*
* The timeout isn't specified, the 2ms used here is based on
* experiment.
@ -1797,7 +1911,6 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
HSW_PCODE_DE_WRITE_FREQ_REQ,
cdclk_config->voltage_level,
150, 2);
}
if (ret) {
drm_err(&dev_priv->drm,
@ -1954,6 +2067,28 @@ void intel_cdclk_uninit_hw(struct drm_i915_private *i915)
skl_cdclk_uninit_hw(i915);
}
static bool intel_cdclk_can_crawl_and_squash(struct drm_i915_private *i915,
const struct intel_cdclk_config *a,
const struct intel_cdclk_config *b)
{
u16 old_waveform;
u16 new_waveform;
drm_WARN_ON(&i915->drm, cdclk_pll_is_unknown(a->vco));
if (a->vco == 0 || b->vco == 0)
return false;
if (!HAS_CDCLK_CRAWL(i915) || !HAS_CDCLK_SQUASH(i915))
return false;
old_waveform = cdclk_squash_waveform(i915, a->cdclk);
new_waveform = cdclk_squash_waveform(i915, b->cdclk);
return a->vco != b->vco &&
old_waveform != new_waveform;
}
static bool intel_cdclk_can_crawl(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *a,
const struct intel_cdclk_config *b)
@ -2760,9 +2895,14 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
pipe = INVALID_PIPE;
}
if (intel_cdclk_can_squash(dev_priv,
&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
if (intel_cdclk_can_crawl_and_squash(dev_priv,
&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
drm_dbg_kms(&dev_priv->drm,
"Can change cdclk via crawling and squashing\n");
} else if (intel_cdclk_can_squash(dev_priv,
&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
drm_dbg_kms(&dev_priv->drm,
"Can change cdclk via squashing\n");
} else if (intel_cdclk_can_crawl(dev_priv,
@ -3060,6 +3200,13 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv)
return freq;
}
static const struct intel_cdclk_funcs mtl_cdclk_funcs = {
.get_cdclk = bxt_get_cdclk,
.set_cdclk = bxt_set_cdclk,
.modeset_calc_cdclk = bxt_modeset_calc_cdclk,
.calc_voltage_level = tgl_calc_voltage_level,
};
static const struct intel_cdclk_funcs tgl_cdclk_funcs = {
.get_cdclk = bxt_get_cdclk,
.set_cdclk = bxt_set_cdclk,
@ -3195,7 +3342,10 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = {
*/
void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
{
if (IS_DG2(dev_priv)) {
if (IS_METEORLAKE(dev_priv)) {
dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs;
dev_priv->display.cdclk.table = mtl_cdclk_table;
} else if (IS_DG2(dev_priv)) {
dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs;
dev_priv->display.cdclk.table = dg2_cdclk_table;
} else if (IS_ALDERLAKE_P(dev_priv)) {

File diff suppressed because it is too large Load Diff

View File

@ -17,14 +17,16 @@ void intel_color_init_hooks(struct drm_i915_private *i915);
int intel_color_init(struct drm_i915_private *i915);
void intel_color_crtc_init(struct intel_crtc *crtc);
int intel_color_check(struct intel_crtc_state *crtc_state);
void intel_color_prepare_commit(struct intel_crtc_state *crtc_state);
void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
void intel_color_get_config(struct intel_crtc_state *crtc_state);
int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state);
bool intel_color_lut_equal(struct drm_property_blob *blob1,
struct drm_property_blob *blob2,
u32 gamma_mode, u32 bit_precision);
bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob1,
const struct drm_property_blob *blob2,
bool is_pre_csc_lut);
void intel_color_assert_luts(const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_COLOR_H__ */

View File

@ -54,7 +54,7 @@ int intel_connector_init(struct intel_connector *connector)
__drm_atomic_helper_connector_reset(&connector->base,
&conn_state->base);
INIT_LIST_HEAD(&connector->panel.fixed_modes);
intel_panel_init_alloc(connector);
return 0;
}

View File

@ -682,30 +682,20 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
{
struct drm_device *dev = crt->base.base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_uncore *uncore = &dev_priv->uncore;
u32 save_bclrpat;
u32 save_vtotal;
u32 vtotal, vactive;
u32 vsample;
u32 vblank, vblank_start, vblank_end;
u32 dsl;
i915_reg_t bclrpat_reg, vtotal_reg,
vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg;
u8 st00;
enum drm_connector_status status;
drm_dbg_kms(&dev_priv->drm, "starting load-detect on CRT\n");
bclrpat_reg = BCLRPAT(pipe);
vtotal_reg = VTOTAL(pipe);
vblank_reg = VBLANK(pipe);
vsync_reg = VSYNC(pipe);
pipeconf_reg = PIPECONF(pipe);
pipe_dsl_reg = PIPEDSL(pipe);
save_bclrpat = intel_uncore_read(uncore, bclrpat_reg);
save_vtotal = intel_uncore_read(uncore, vtotal_reg);
vblank = intel_uncore_read(uncore, vblank_reg);
save_bclrpat = intel_de_read(dev_priv, BCLRPAT(pipe));
save_vtotal = intel_de_read(dev_priv, VTOTAL(pipe));
vblank = intel_de_read(dev_priv, VBLANK(pipe));
vtotal = ((save_vtotal >> 16) & 0xfff) + 1;
vactive = (save_vtotal & 0x7ff) + 1;
@ -714,23 +704,23 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
vblank_end = ((vblank >> 16) & 0xfff) + 1;
/* Set the border color to purple. */
intel_uncore_write(uncore, bclrpat_reg, 0x500050);
intel_de_write(dev_priv, BCLRPAT(pipe), 0x500050);
if (DISPLAY_VER(dev_priv) != 2) {
u32 pipeconf = intel_uncore_read(uncore, pipeconf_reg);
intel_uncore_write(uncore,
pipeconf_reg,
pipeconf | PIPECONF_FORCE_BORDER);
intel_uncore_posting_read(uncore, pipeconf_reg);
u32 pipeconf = intel_de_read(dev_priv, PIPECONF(pipe));
intel_de_write(dev_priv, PIPECONF(pipe),
pipeconf | PIPECONF_FORCE_BORDER);
intel_de_posting_read(dev_priv, PIPECONF(pipe));
/* Wait for next Vblank to substitue
* border color for Color info */
intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(dev_priv, pipe));
st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE);
st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE);
status = ((st00 & (1 << 4)) != 0) ?
connector_status_connected :
connector_status_disconnected;
intel_uncore_write(uncore, pipeconf_reg, pipeconf);
intel_de_write(dev_priv, PIPECONF(pipe), pipeconf);
} else {
bool restore_vblank = false;
int count, detect;
@ -740,14 +730,12 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
* Yes, this will flicker
*/
if (vblank_start <= vactive && vblank_end >= vtotal) {
u32 vsync = intel_de_read(dev_priv, vsync_reg);
u32 vsync = intel_de_read(dev_priv, VSYNC(pipe));
u32 vsync_start = (vsync & 0xffff) + 1;
vblank_start = vsync_start;
intel_uncore_write(uncore,
vblank_reg,
(vblank_start - 1) |
((vblank_end - 1) << 16));
intel_de_write(dev_priv, VBLANK(pipe),
(vblank_start - 1) | ((vblank_end - 1) << 16));
restore_vblank = true;
}
/* sample in the vertical border, selecting the larger one */
@ -759,10 +747,9 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
/*
* Wait for the border to be displayed
*/
while (intel_uncore_read(uncore, pipe_dsl_reg) >= vactive)
while (intel_de_read(dev_priv, PIPEDSL(pipe)) >= vactive)
;
while ((dsl = intel_uncore_read(uncore, pipe_dsl_reg)) <=
vsample)
while ((dsl = intel_de_read(dev_priv, PIPEDSL(pipe))) <= vsample)
;
/*
* Watch ST00 for an entire scanline
@ -772,14 +759,14 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
do {
count++;
/* Read the ST00 VGA status register */
st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE);
st00 = intel_de_read8(dev_priv, _VGA_MSR_WRITE);
if (st00 & (1 << 4))
detect++;
} while ((intel_uncore_read(uncore, pipe_dsl_reg) == dsl));
} while ((intel_de_read(dev_priv, PIPEDSL(pipe)) == dsl));
/* restore vblank if necessary */
if (restore_vblank)
intel_uncore_write(uncore, vblank_reg, vblank);
intel_de_write(dev_priv, VBLANK(pipe), vblank);
/*
* If more than 3/4 of the scanline detected a monitor,
* then it is assumed to be present. This works even on i830,
@ -792,7 +779,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
}
/* Restore previous settings */
intel_uncore_write(uncore, bclrpat_reg, save_bclrpat);
intel_de_write(dev_priv, BCLRPAT(pipe), save_bclrpat);
return status;
}

View File

@ -185,6 +185,8 @@ void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
enum port port)
{
enum phy phy = intel_port_to_phy(dev_priv, port);
int timeout_us;
int ret;
/* Wait > 518 usecs for DDI_BUF_CTL to be non idle */
@ -193,8 +195,19 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
return;
}
if (IS_DG2(dev_priv)) {
timeout_us = 1200;
} else if (DISPLAY_VER(dev_priv) >= 12) {
if (intel_phy_is_tc(dev_priv, phy))
timeout_us = 3000;
else
timeout_us = 1000;
} else {
timeout_us = 500;
}
ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
DDI_BUF_IS_IDLE), IS_DG2(dev_priv) ? 1200 : 500, 10, 10);
DDI_BUF_IS_IDLE), timeout_us, 10, 10);
if (ret)
drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n",
@ -2726,10 +2739,10 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) {
intel_crtc_vblank_off(old_crtc_state);
intel_disable_transcoder(old_crtc_state);
intel_vrr_disable(old_crtc_state);
intel_disable_transcoder(old_crtc_state);
intel_ddi_disable_transcoder_func(old_crtc_state);
intel_dsc_disable(old_crtc_state);
@ -2933,6 +2946,8 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
}
intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
intel_wait_ddi_buf_active(dev_priv, port);
intel_audio_codec_enable(encoder, crtc_state, conn_state);
}
@ -2946,10 +2961,13 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
if (!intel_crtc_is_bigjoiner_slave(crtc_state))
intel_ddi_enable_transcoder_func(encoder, crtc_state);
intel_vrr_enable(encoder, crtc_state);
/* Enable/Disable DP2.0 SDP split config before transcoder */
intel_audio_sdp_split_update(encoder, crtc_state);
intel_enable_transcoder(crtc_state);
intel_vrr_enable(encoder, crtc_state);
intel_crtc_vblank_on(crtc_state);
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))

View File

@ -16,6 +16,12 @@ intel_de_read(struct drm_i915_private *i915, i915_reg_t reg)
return intel_uncore_read(&i915->uncore, reg);
}
static inline u8
intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg)
{
return intel_uncore_read8(&i915->uncore, reg);
}
static inline void
intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg)
{
@ -28,10 +34,10 @@ intel_de_write(struct drm_i915_private *i915, i915_reg_t reg, u32 val)
intel_uncore_write(&i915->uncore, reg, val);
}
static inline void
static inline u32
intel_de_rmw(struct drm_i915_private *i915, i915_reg_t reg, u32 clear, u32 set)
{
intel_uncore_rmw(&i915->uncore, reg, clear, set);
return intel_uncore_rmw(&i915->uncore, reg, clear, set);
}
static inline int
@ -41,6 +47,23 @@ intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg,
return intel_wait_for_register(&i915->uncore, reg, mask, value, timeout);
}
static inline int
intel_de_wait_for_register_fw(struct drm_i915_private *i915, i915_reg_t reg,
u32 mask, u32 value, unsigned int timeout)
{
return intel_wait_for_register_fw(&i915->uncore, reg, mask, value, timeout);
}
static inline int
__intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg,
u32 mask, u32 value,
unsigned int fast_timeout_us,
unsigned int slow_timeout_ms, u32 *out_value)
{
return __intel_wait_for_register(&i915->uncore, reg, mask, value,
fast_timeout_us, slow_timeout_ms, out_value);
}
static inline int
intel_de_wait_for_set(struct drm_i915_private *i915, i915_reg_t reg,
u32 mask, unsigned int timeout)
@ -81,4 +104,16 @@ intel_de_write_fw(struct drm_i915_private *i915, i915_reg_t reg, u32 val)
intel_uncore_write_fw(&i915->uncore, reg, val);
}
static inline u32
intel_de_read_notrace(struct drm_i915_private *i915, i915_reg_t reg)
{
return intel_uncore_read_notrace(&i915->uncore, reg);
}
static inline void
intel_de_write_notrace(struct drm_i915_private *i915, i915_reg_t reg, u32 val)
{
intel_uncore_write_notrace(&i915->uncore, reg, val);
}
#endif /* __INTEL_DE_H__ */

View File

@ -70,8 +70,6 @@
#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_object.h"
#include "gt/gen8_ppgtt.h"
#include "g4x_dp.h"
#include "g4x_hdmi.h"
#include "hsw_ips.h"
@ -93,7 +91,6 @@
#include "intel_dp_link_training.h"
#include "intel_dpio_phy.h"
#include "intel_dpt.h"
#include "intel_dsb.h"
#include "intel_fbc.h"
#include "intel_fbdev.h"
#include "intel_fdi.h"
@ -1246,7 +1243,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
if (new_crtc_state->update_wm_post && new_crtc_state->hw.active)
intel_update_watermarks(dev_priv);
hsw_ips_post_update(state, crtc);
intel_fbc_post_update(state, crtc);
if (needs_async_flip_vtd_wa(old_crtc_state) &&
@ -5531,7 +5527,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *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);
bool ret = true;
u32 bp_gamma = 0;
bool fixup_inherited = fastset &&
current_config->inherited && !pipe_config->inherited;
@ -5682,21 +5677,14 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
} \
} while (0)
#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \
if (current_config->name1 != pipe_config->name1) { \
pipe_config_mismatch(fastset, crtc, __stringify(name1), \
"(expected %i, found %i, won't compare lut values)", \
current_config->name1, \
pipe_config->name1); \
ret = false;\
} else { \
if (!intel_color_lut_equal(current_config->name2, \
pipe_config->name2, pipe_config->name1, \
bit_precision)) { \
pipe_config_mismatch(fastset, crtc, __stringify(name2), \
"hw_state doesn't match sw_state"); \
ret = false; \
} \
#define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \
if (current_config->gamma_mode == pipe_config->gamma_mode && \
!intel_color_lut_equal(current_config, \
current_config->lut, pipe_config->lut, \
is_pre_csc_lut)) { \
pipe_config_mismatch(fastset, crtc, __stringify(lut), \
"hw_state doesn't match sw_state"); \
ret = false; \
} \
} while (0)
@ -5793,9 +5781,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(linetime);
PIPE_CONF_CHECK_I(ips_linetime);
bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);
if (bp_gamma)
PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, post_csc_lut, bp_gamma);
PIPE_CONF_CHECK_COLOR_LUT(pre_csc_lut, true);
PIPE_CONF_CHECK_COLOR_LUT(post_csc_lut, false);
if (current_config->active_planes) {
PIPE_CONF_CHECK_BOOL(has_psr);
@ -6941,7 +6928,7 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
if (intel_crtc_needs_color_update(crtc_state))
intel_dsb_prepare(crtc_state);
intel_color_prepare_commit(crtc_state);
}
return 0;
@ -7392,24 +7379,18 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat
&wait_reset);
}
static void intel_cleanup_dsbs(struct intel_atomic_state *state)
{
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i)
intel_dsb_cleanup(old_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);
struct drm_i915_private *i915 = to_i915(state->base.dev);
struct intel_crtc_state *old_crtc_state;
struct intel_crtc *crtc;
int i;
for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i)
intel_color_cleanup_commit(old_crtc_state);
intel_cleanup_dsbs(state);
drm_atomic_helper_cleanup_planes(&i915->drm, &state->base);
drm_atomic_helper_commit_cleanup_done(&state->base);
drm_atomic_state_put(&state->base);
@ -7587,6 +7568,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state);
/* Must be done after gamma readout due to HSW split gamma vs. IPS w/a */
hsw_ips_post_update(state, crtc);
/*
* Activate DRRS after state readout to avoid
* dp_m_n vs. dp_m2_n2 confusion on BDW+.
@ -7597,6 +7581,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
* DSB cleanup is done in cleanup_work aligning with framebuffer
* cleanup. So copy and reset the dsb structure to sync with
* commit_done and later do dsb cleanup in cleanup_work.
*
* FIXME get rid of this funny new->old swapping
*/
old_crtc_state->dsb = fetch_and_zero(&new_crtc_state->dsb);
}
@ -7747,7 +7733,7 @@ static int intel_atomic_commit(struct drm_device *dev,
i915_sw_fence_commit(&state->commit_ready);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
intel_dsb_cleanup(new_crtc_state);
intel_color_cleanup_commit(new_crtc_state);
drm_atomic_helper_cleanup_planes(dev, &state->base);
intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);

View File

@ -440,6 +440,14 @@ enum hpd_pin {
(__i)++) \
for_each_if(plane)
#define for_each_old_intel_crtc_in_state(__state, crtc, old_crtc_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->base.dev->mode_config.num_crtc && \
((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \
(old_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].old_state), 1); \
(__i)++) \
for_each_if(crtc)
#define for_each_new_intel_plane_in_state(__state, plane, new_plane_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->base.dev->mode_config.num_total_plane && \

View File

@ -1673,7 +1673,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv,
if (DISPLAY_VER(dev_priv) >= 12) {
val = DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM |
DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR;
intel_uncore_rmw(&dev_priv->uncore, GEN11_CHICKEN_DCPR_2, 0, val);
intel_de_rmw(dev_priv, GEN11_CHICKEN_DCPR_2, 0, val);
}
/* Wa_14011503030:xelpd */

View File

@ -291,7 +291,7 @@ struct intel_vbt_panel_data {
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
/* Feature bits */
unsigned int panel_type:4;
int panel_type;
unsigned int lvds_dither:1;
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
@ -330,7 +330,7 @@ struct intel_vbt_panel_data {
bool present;
bool active_low_pwm;
u8 min_brightness; /* min_brightness/255 of max */
u8 controller; /* brightness controller number */
s8 controller; /* brightness controller number */
enum intel_backlight_type type;
} backlight;
@ -1295,6 +1295,8 @@ struct intel_crtc_state {
/* Forward Error correction State */
bool fec_enable;
bool sdp_split_enable;
/* Pointer to master transcoder in case of tiled displays */
enum transcoder master_transcoder;
@ -1568,11 +1570,19 @@ struct intel_pps {
ktime_t panel_power_off_time;
intel_wakeref_t vdd_wakeref;
/*
* Pipe whose power sequencer is currently locked into
* this port. Only relevant on VLV/CHV.
*/
enum pipe pps_pipe;
union {
/*
* Pipe whose power sequencer is currently locked into
* this port. Only relevant on VLV/CHV.
*/
enum pipe pps_pipe;
/*
* Power sequencer index. Only relevant on BXT+.
*/
int pps_idx;
};
/*
* Pipe currently driving the port. Used for preventing
* the use of the PPS for any pipe currentrly driving
@ -1581,7 +1591,7 @@ struct intel_pps {
enum pipe active_pipe;
/*
* Set if the sequencer may be reset due to a power transition,
* requiring a reinitialization. Only relevant on BXT.
* requiring a reinitialization. Only relevant on BXT+.
*/
bool pps_reset;
struct edp_power_seq pps_delays;

View File

@ -53,51 +53,40 @@
#define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE
#define DG2_DMC_PATH DMC_PATH(dg2, 2, 08)
#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 8)
MODULE_FIRMWARE(DG2_DMC_PATH);
#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16)
#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 16)
MODULE_FIRMWARE(ADLP_DMC_PATH);
#define ADLS_DMC_PATH DMC_PATH(adls, 2, 01)
#define ADLS_DMC_VERSION_REQUIRED DMC_VERSION(2, 1)
MODULE_FIRMWARE(ADLS_DMC_PATH);
#define DG1_DMC_PATH DMC_PATH(dg1, 2, 02)
#define DG1_DMC_VERSION_REQUIRED DMC_VERSION(2, 2)
MODULE_FIRMWARE(DG1_DMC_PATH);
#define RKL_DMC_PATH DMC_PATH(rkl, 2, 03)
#define RKL_DMC_VERSION_REQUIRED DMC_VERSION(2, 3)
MODULE_FIRMWARE(RKL_DMC_PATH);
#define TGL_DMC_PATH DMC_PATH(tgl, 2, 12)
#define TGL_DMC_VERSION_REQUIRED DMC_VERSION(2, 12)
MODULE_FIRMWARE(TGL_DMC_PATH);
#define ICL_DMC_PATH DMC_PATH(icl, 1, 09)
#define ICL_DMC_VERSION_REQUIRED DMC_VERSION(1, 9)
#define ICL_DMC_MAX_FW_SIZE 0x6000
MODULE_FIRMWARE(ICL_DMC_PATH);
#define GLK_DMC_PATH DMC_PATH(glk, 1, 04)
#define GLK_DMC_VERSION_REQUIRED DMC_VERSION(1, 4)
#define GLK_DMC_MAX_FW_SIZE 0x4000
MODULE_FIRMWARE(GLK_DMC_PATH);
#define KBL_DMC_PATH DMC_PATH(kbl, 1, 04)
#define KBL_DMC_VERSION_REQUIRED DMC_VERSION(1, 4)
#define KBL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE
MODULE_FIRMWARE(KBL_DMC_PATH);
#define SKL_DMC_PATH DMC_PATH(skl, 1, 27)
#define SKL_DMC_VERSION_REQUIRED DMC_VERSION(1, 27)
#define SKL_DMC_MAX_FW_SIZE BXT_DMC_MAX_FW_SIZE
MODULE_FIRMWARE(SKL_DMC_PATH);
#define BXT_DMC_PATH DMC_PATH(bxt, 1, 07)
#define BXT_DMC_VERSION_REQUIRED DMC_VERSION(1, 7)
#define BXT_DMC_MAX_FW_SIZE 0x3000
MODULE_FIRMWARE(BXT_DMC_PATH);
@ -387,11 +376,11 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
{
enum pipe pipe;
if (DISPLAY_VER(i915) != 13)
if (DISPLAY_VER(i915) < 13)
return;
/*
* Wa_16015201720:adl-p,dg2
* Wa_16015201720:adl-p,dg2, mtl
* The WA requires clock gating to be disabled all the time
* for pipe A and B.
* For pipe C and D clock gating needs to be disabled only
@ -433,9 +422,9 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
for (id = 0; id < DMC_FW_MAX; id++) {
for (i = 0; i < dmc->dmc_info[id].dmc_fw_size; i++) {
intel_uncore_write_fw(&dev_priv->uncore,
DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i),
dmc->dmc_info[id].payload[i]);
intel_de_write_fw(dev_priv,
DMC_PROGRAM(dmc->dmc_info[id].start_mmioaddr, i),
dmc->dmc_info[id].payload[i]);
}
}
@ -765,17 +754,6 @@ static u32 parse_dmc_fw_css(struct intel_dmc *dmc,
return 0;
}
if (dmc->required_version &&
css_header->version != dmc->required_version) {
drm_info(&i915->drm, "Refusing to load DMC firmware v%u.%u,"
" please use v%u.%u\n",
DMC_VERSION_MAJOR(css_header->version),
DMC_VERSION_MINOR(css_header->version),
DMC_VERSION_MAJOR(dmc->required_version),
DMC_VERSION_MINOR(dmc->required_version));
return 0;
}
dmc->version = css_header->version;
return sizeof(struct intel_css_header);
@ -903,49 +881,38 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
if (IS_DG2(dev_priv)) {
dmc->fw_path = DG2_DMC_PATH;
dmc->required_version = DG2_DMC_VERSION_REQUIRED;
dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE;
} else if (IS_ALDERLAKE_P(dev_priv)) {
dmc->fw_path = ADLP_DMC_PATH;
dmc->required_version = ADLP_DMC_VERSION_REQUIRED;
dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE;
} else if (IS_ALDERLAKE_S(dev_priv)) {
dmc->fw_path = ADLS_DMC_PATH;
dmc->required_version = ADLS_DMC_VERSION_REQUIRED;
dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
} else if (IS_DG1(dev_priv)) {
dmc->fw_path = DG1_DMC_PATH;
dmc->required_version = DG1_DMC_VERSION_REQUIRED;
dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
} else if (IS_ROCKETLAKE(dev_priv)) {
dmc->fw_path = RKL_DMC_PATH;
dmc->required_version = RKL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
} else if (IS_TIGERLAKE(dev_priv)) {
dmc->fw_path = TGL_DMC_PATH;
dmc->required_version = TGL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE;
} else if (DISPLAY_VER(dev_priv) == 11) {
dmc->fw_path = ICL_DMC_PATH;
dmc->required_version = ICL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE;
} else if (IS_GEMINILAKE(dev_priv)) {
dmc->fw_path = GLK_DMC_PATH;
dmc->required_version = GLK_DMC_VERSION_REQUIRED;
dmc->max_fw_size = GLK_DMC_MAX_FW_SIZE;
} else if (IS_KABYLAKE(dev_priv) ||
IS_COFFEELAKE(dev_priv) ||
IS_COMETLAKE(dev_priv)) {
dmc->fw_path = KBL_DMC_PATH;
dmc->required_version = KBL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = KBL_DMC_MAX_FW_SIZE;
} else if (IS_SKYLAKE(dev_priv)) {
dmc->fw_path = SKL_DMC_PATH;
dmc->required_version = SKL_DMC_VERSION_REQUIRED;
dmc->max_fw_size = SKL_DMC_MAX_FW_SIZE;
} else if (IS_BROXTON(dev_priv)) {
dmc->fw_path = BXT_DMC_PATH;
dmc->required_version = BXT_DMC_VERSION_REQUIRED;
dmc->max_fw_size = BXT_DMC_MAX_FW_SIZE;
}
@ -958,8 +925,6 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv)
}
dmc->fw_path = dev_priv->params.dmc_firmware_path;
/* Bypass version check for firmware override. */
dmc->required_version = 0;
}
if (!dmc->fw_path) {

View File

@ -25,7 +25,6 @@ enum {
struct intel_dmc {
struct work_struct work;
const char *fw_path;
u32 required_version;
u32 max_fw_size; /* bytes */
u32 version;
struct dmc_fw_info {

View File

@ -117,7 +117,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
}
static void intel_dp_unset_edid(struct intel_dp *intel_dp);
static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
/* Is link rate UHBR and thus 128b/132b? */
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state)
@ -673,23 +672,59 @@ small_joiner_ram_size_bits(struct drm_i915_private *i915)
return 6144 * 8;
}
static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
bool bigjoiner,
u32 pipe_bpp)
u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp)
{
u32 bits_per_pixel = bpp;
int i;
/* Error out if the max bpp is less than smallest allowed valid bpp */
if (bits_per_pixel < valid_dsc_bpp[0]) {
drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n",
bits_per_pixel, valid_dsc_bpp[0]);
return 0;
}
/* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */
if (DISPLAY_VER(i915) >= 13) {
bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1);
} else {
/* Find the nearest match in the array of known BPPs from VESA */
for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
if (bits_per_pixel < valid_dsc_bpp[i + 1])
break;
}
drm_dbg_kms(&i915->drm, "Set dsc bpp from %d to VESA %d\n",
bits_per_pixel, valid_dsc_bpp[i]);
bits_per_pixel = valid_dsc_bpp[i];
}
return bits_per_pixel;
}
u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
bool bigjoiner,
u32 pipe_bpp,
u32 timeslots)
{
u32 bits_per_pixel, max_bpp_small_joiner_ram;
int i;
/*
* Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
* (LinkSymbolClock)* 8 * (TimeSlotsPerMTP)
* for SST -> TimeSlotsPerMTP is 1,
* for MST -> TimeSlotsPerMTP has to be calculated
* (LinkSymbolClock)* 8 * (TimeSlots / 64)
* for SST -> TimeSlots is 64(i.e all TimeSlots that are available)
* for MST -> TimeSlots has to be calculated, based on mode requirements
*/
bits_per_pixel = (link_clock * lane_count * 8) /
intel_dp_mode_to_fec_clock(mode_clock);
bits_per_pixel = DIV_ROUND_UP((link_clock * lane_count) * timeslots,
intel_dp_mode_to_fec_clock(mode_clock) * 8);
drm_dbg_kms(&i915->drm, "Max link bpp is %u for %u timeslots "
"total bw %u pixel clock %u\n",
bits_per_pixel, timeslots,
(link_clock * lane_count * 8),
intel_dp_mode_to_fec_clock(mode_clock));
/* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
max_bpp_small_joiner_ram = small_joiner_ram_size_bits(i915) /
@ -712,24 +747,7 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
bits_per_pixel = min(bits_per_pixel, max_bpp_bigjoiner);
}
/* Error out if the max bpp is less than smallest allowed valid bpp */
if (bits_per_pixel < valid_dsc_bpp[0]) {
drm_dbg_kms(&i915->drm, "Unsupported BPP %u, min %u\n",
bits_per_pixel, valid_dsc_bpp[0]);
return 0;
}
/* From XE_LPD onwards we support from bpc upto uncompressed bpp-1 BPPs */
if (DISPLAY_VER(i915) >= 13) {
bits_per_pixel = min(bits_per_pixel, pipe_bpp - 1);
} else {
/* Find the nearest match in the array of known BPPs from VESA */
for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
if (bits_per_pixel < valid_dsc_bpp[i + 1])
break;
}
bits_per_pixel = valid_dsc_bpp[i];
}
bits_per_pixel = intel_dp_dsc_nearest_valid_bpp(i915, bits_per_pixel, pipe_bpp);
/*
* Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
@ -738,9 +756,9 @@ static u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
return bits_per_pixel << 4;
}
static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
int mode_clock, int mode_hdisplay,
bool bigjoiner)
u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
int mode_clock, int mode_hdisplay,
bool bigjoiner)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 min_slice_count, i;
@ -947,8 +965,8 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
return MODE_OK;
}
static bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
int hdisplay, int clock)
bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
int hdisplay, int clock)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@ -974,9 +992,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
enum drm_mode_status status;
bool dsc = false, bigjoiner = false;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
if (mode->flags & DRM_MODE_FLAG_DBLCLK)
return MODE_H_ILLEGAL;
@ -1013,7 +1028,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
* Output bpp is stored in 6.4 format so right shift by 4 to get the
* integer value since we support only integer values of bpp.
*/
if (DISPLAY_VER(dev_priv) >= 10 &&
if (HAS_DSC(dev_priv) &&
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) {
/*
* TBD pass the connector BPC,
@ -1035,7 +1050,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
target_clock,
mode->hdisplay,
bigjoiner,
pipe_bpp) >> 4;
pipe_bpp, 64) >> 4;
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
target_clock,
@ -1364,7 +1379,7 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
return -EINVAL;
}
static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc)
int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 max_req_bpc)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
int i, num_bpc;
@ -1465,10 +1480,12 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
return drm_dsc_compute_rc_parameters(vdsc_cfg);
}
static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
struct link_config_limits *limits,
int timeslots,
bool compute_pipe_bpp)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
@ -1483,7 +1500,10 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
if (!intel_dp_supports_dsc(intel_dp, pipe_config))
return -EINVAL;
pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc);
if (compute_pipe_bpp)
pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, conn_state->max_requested_bpc);
else
pipe_bpp = pipe_config->pipe_bpp;
if (intel_dp->force_dsc_bpc) {
pipe_bpp = intel_dp->force_dsc_bpc * 3;
@ -1514,33 +1534,52 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
true);
} else {
u16 dsc_max_output_bpp;
u16 dsc_max_output_bpp = 0;
u8 dsc_dp_slice_count;
dsc_max_output_bpp =
intel_dp_dsc_get_output_bpp(dev_priv,
pipe_config->port_clock,
pipe_config->lane_count,
adjusted_mode->crtc_clock,
adjusted_mode->crtc_hdisplay,
pipe_config->bigjoiner_pipes,
pipe_bpp);
if (compute_pipe_bpp) {
dsc_max_output_bpp =
intel_dp_dsc_get_output_bpp(dev_priv,
pipe_config->port_clock,
pipe_config->lane_count,
adjusted_mode->crtc_clock,
adjusted_mode->crtc_hdisplay,
pipe_config->bigjoiner_pipes,
pipe_bpp,
timeslots);
if (!dsc_max_output_bpp) {
drm_dbg_kms(&dev_priv->drm,
"Compressed BPP not supported\n");
return -EINVAL;
}
}
dsc_dp_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
adjusted_mode->crtc_clock,
adjusted_mode->crtc_hdisplay,
pipe_config->bigjoiner_pipes);
if (!dsc_max_output_bpp || !dsc_dp_slice_count) {
if (!dsc_dp_slice_count) {
drm_dbg_kms(&dev_priv->drm,
"Compressed BPP/Slice Count not supported\n");
"Compressed Slice Count not supported\n");
return -EINVAL;
}
pipe_config->dsc.compressed_bpp = min_t(u16,
dsc_max_output_bpp >> 4,
pipe_config->pipe_bpp);
pipe_config->dsc.slice_count = dsc_dp_slice_count;
}
/*
* compute pipe bpp is set to false for DP MST DSC case
* and compressed_bpp is calculated same time once
* vpci timeslots are allocated, because overall bpp
* calculation procedure is bit different for MST case.
*/
if (compute_pipe_bpp) {
pipe_config->dsc.compressed_bpp = min_t(u16,
dsc_max_output_bpp >> 4,
pipe_config->pipe_bpp);
}
pipe_config->dsc.slice_count = dsc_dp_slice_count;
drm_dbg_kms(&dev_priv->drm, "DSC: compressed bpp %d slice count %d\n",
pipe_config->dsc.compressed_bpp,
pipe_config->dsc.slice_count);
}
/*
* VDSC engine operates at 1 Pixel per clock, so if peak pixel rate
* is greater than the maximum Cdclock and if slice count is even
@ -1548,13 +1587,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
*/
if (adjusted_mode->crtc_clock > dev_priv->display.cdclk.max_cdclk_freq ||
pipe_config->bigjoiner_pipes) {
if (pipe_config->dsc.slice_count < 2) {
if (pipe_config->dsc.slice_count > 1) {
pipe_config->dsc.dsc_split = true;
} else {
drm_dbg_kms(&dev_priv->drm,
"Cannot split stream to use 2 VDSC instances\n");
return -EINVAL;
}
pipe_config->dsc.dsc_split = true;
}
ret = intel_dp_dsc_compute_params(&dig_port->base, pipe_config);
@ -1643,7 +1682,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
str_yes_no(ret), str_yes_no(joiner_needs_dsc),
str_yes_no(intel_dp->force_dsc_en));
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
conn_state, &limits);
conn_state, &limits, 64, true);
if (ret < 0)
return ret;
}
@ -2009,6 +2048,23 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
return ret;
}
static void
intel_dp_audio_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct drm_connector *connector = conn_state->connector;
pipe_config->sdp_split_enable =
intel_dp_has_audio(encoder, pipe_config, conn_state) &&
intel_dp_is_uhbr(pipe_config);
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] SDP split enable: %s\n",
connector->base.id, connector->name,
str_yes_no(pipe_config->sdp_split_enable));
}
int
intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
@ -2036,7 +2092,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
if (HAS_GMCH(dev_priv) &&
if (!connector->base.interlace_allowed &&
adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return -EINVAL;
@ -2092,6 +2148,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
adjusted_mode->crtc_clock /= n;
}
intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
intel_link_compute_m_n(output_bpp,
pipe_config->lane_count,
adjusted_mode->crtc_clock,
@ -2907,7 +2965,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
intel_dp_set_max_sink_lane_count(intel_dp);
/* Read the eDP DSC DPCD registers */
if (DISPLAY_VER(dev_priv) >= 10)
if (HAS_DSC(dev_priv))
intel_dp_get_dsc_sink_cap(intel_dp);
/*
@ -4633,7 +4691,7 @@ intel_dp_detect(struct drm_connector *connector,
}
/* Read DP Sink DSC Cap DPCD regs for DP v1.4 */
if (DISPLAY_VER(dev_priv) >= 11)
if (HAS_DSC(dev_priv))
intel_dp_get_dsc_sink_cap(intel_dp);
intel_dp_configure_mst(intel_dp);
@ -5202,7 +5260,20 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
return false;
}
intel_pps_init(intel_dp);
intel_bios_init_panel_early(dev_priv, &intel_connector->panel,
encoder->devdata);
if (!intel_pps_init(intel_dp)) {
drm_info(&dev_priv->drm,
"[ENCODER:%d:%s] unusable PPS, disabling eDP\n",
encoder->base.base.id, encoder->base.name);
/*
* The BIOS may have still enabled VDD on the PPS even
* though it's unusable. Make sure we turn it back off
* and to release the power domain references/etc.
*/
goto out_vdd_off;
}
/* Cache DPCD and EDID for edp. */
has_dpcd = intel_edp_init_dpcd(intel_dp);
@ -5237,8 +5308,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
intel_connector->edid = edid;
intel_bios_init_panel(dev_priv, &intel_connector->panel,
encoder->devdata, IS_ERR(edid) ? NULL : edid);
intel_bios_init_panel_late(dev_priv, &intel_connector->panel,
encoder->devdata, IS_ERR(edid) ? NULL : edid);
intel_panel_add_edid_fixed_modes(intel_connector, true);
@ -5364,7 +5435,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
if (!HAS_GMCH(dev_priv))
if (!HAS_GMCH(dev_priv) && DISPLAY_VER(dev_priv) < 12)
connector->interlace_allowed = true;
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;

View File

@ -56,6 +56,12 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder);
int intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state);
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
struct link_config_limits *limits,
int timeslots,
bool recompute_pipe_bpp);
bool intel_dp_is_edp(struct intel_dp *intel_dp);
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state);
bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
@ -96,6 +102,18 @@ void intel_read_dp_sdp(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
unsigned int type);
bool intel_digital_port_connected(struct intel_encoder *encoder);
int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
u16 intel_dp_dsc_get_output_bpp(struct drm_i915_private *i915,
u32 link_clock, u32 lane_count,
u32 mode_clock, u32 mode_hdisplay,
bool bigjoiner,
u32 pipe_bpp,
u32 timeslots);
u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
int mode_clock, int mode_hdisplay,
bool bigjoiner);
bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp,
int hdisplay, int clock);
static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
{
@ -103,6 +121,7 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
}
u32 intel_dp_mode_to_fec_clock(u32 mode_clock);
u32 intel_dp_dsc_nearest_valid_bpp(struct drm_i915_private *i915, u32 bpp, u32 pipe_bpp);
void intel_ddi_update_pipe(struct intel_atomic_state *state,
struct intel_encoder *encoder,

View File

@ -6,6 +6,7 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_trace.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp_aux.h"
#include "intel_pps.h"
@ -40,20 +41,16 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
const unsigned int timeout_ms = 10;
u32 status;
bool done;
int ret;
#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
done = wait_event_timeout(i915->display.gmbus.wait_queue, C,
msecs_to_jiffies_timeout(timeout_ms));
ret = __intel_de_wait_for_register(i915, ch_ctl,
DP_AUX_CH_CTL_SEND_BUSY, 0,
2, timeout_ms, &status);
/* just trace the final value */
trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
if (!done)
if (ret == -ETIMEDOUT)
drm_err(&i915->drm,
"%s: did not complete or timeout within %ums (status 0x%08x)\n",
intel_dp->aux.name, timeout_ms, status);
#undef C
return status;
}
@ -191,7 +188,6 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_i915_private *i915 =
to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
bool is_tc_port = intel_phy_is_tc(i915, phy);
i915_reg_t ch_ctl, ch_data[5];
@ -235,7 +231,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
/* Try to wait for any previous AUX channel activity */
for (try = 0; try < 3; try++) {
status = intel_uncore_read_notrace(uncore, ch_ctl);
status = intel_de_read_notrace(i915, ch_ctl);
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
break;
msleep(1);
@ -244,7 +240,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
if (try == 3) {
const u32 status = intel_uncore_read(uncore, ch_ctl);
const u32 status = intel_de_read(i915, ch_ctl);
if (status != intel_dp->aux_busy_last_status) {
drm_WARN(&i915->drm, 1,
@ -274,23 +270,20 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
for (try = 0; try < 5; try++) {
/* Load the send data into the aux channel data registers */
for (i = 0; i < send_bytes; i += 4)
intel_uncore_write(uncore,
ch_data[i >> 2],
intel_dp_aux_pack(send + i,
send_bytes - i));
intel_de_write(i915, ch_data[i >> 2],
intel_dp_aux_pack(send + i,
send_bytes - i));
/* Send the command and wait for it to complete */
intel_uncore_write(uncore, ch_ctl, send_ctl);
intel_de_write(i915, ch_ctl, send_ctl);
status = intel_dp_aux_wait_done(intel_dp);
/* Clear done status and any errors */
intel_uncore_write(uncore,
ch_ctl,
status |
DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR);
intel_de_write(i915, ch_ctl,
status | DP_AUX_CH_CTL_DONE |
DP_AUX_CH_CTL_TIME_OUT_ERROR |
DP_AUX_CH_CTL_RECEIVE_ERROR);
/*
* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
@ -361,7 +354,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
recv_bytes = recv_size;
for (i = 0; i < recv_bytes; i += 4)
intel_dp_aux_unpack(intel_uncore_read(uncore, ch_data[i >> 2]),
intel_dp_aux_unpack(intel_de_read(i915, ch_data[i >> 2]),
recv + i, recv_bytes - i);
ret = recv_bytes;

View File

@ -45,10 +45,14 @@
#include "intel_hotplug.h"
#include "skl_scaler.h"
static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
int max_bpp,
int min_bpp,
struct link_config_limits *limits,
struct drm_connector_state *conn_state,
int step,
bool dsc)
{
struct drm_atomic_state *state = crtc_state->uapi.state;
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
@ -60,6 +64,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int bpp, slots = -EINVAL;
int ret = 0;
mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr);
if (IS_ERR(mst_state))
@ -71,30 +76,68 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
// TODO: Handle pbn_div changes by adding a new MST helper
if (!mst_state->pbn_div) {
mst_state->pbn_div = drm_dp_get_vc_payload_bw(&intel_dp->mst_mgr,
limits->max_rate,
limits->max_lane_count);
crtc_state->port_clock,
crtc_state->lane_count);
}
for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
crtc_state->pipe_bpp = bpp;
for (bpp = max_bpp; bpp >= min_bpp; bpp -= step) {
crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
crtc_state->pipe_bpp,
false);
dsc ? bpp << 4 : bpp,
dsc);
drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp);
slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
connector->port, crtc_state->pbn);
connector->port,
crtc_state->pbn);
if (slots == -EDEADLK)
return slots;
if (slots >= 0)
break;
if (slots >= 0) {
ret = drm_dp_mst_atomic_check(state);
/*
* If we got slots >= 0 and we can fit those based on check
* then we can exit the loop. Otherwise keep trying.
*/
if (!ret)
break;
}
}
/* Despite slots are non-zero, we still failed the atomic check */
if (ret && slots >= 0)
slots = ret;
if (slots < 0) {
drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n",
slots);
return slots;
} else {
if (!dsc)
crtc_state->pipe_bpp = bpp;
else
crtc_state->dsc.compressed_bpp = bpp;
drm_dbg_kms(&i915->drm, "Got %d slots for pipe bpp %d dsc %d\n", slots, bpp, dsc);
}
return slots;
}
static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
{
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int slots = -EINVAL;
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, limits->max_bpp,
limits->min_bpp, limits,
conn_state, 2 * 3, false);
if (slots < 0)
return slots;
intel_link_compute_m_n(crtc_state->pipe_bpp,
crtc_state->lane_count,
adjusted_mode->crtc_clock,
@ -106,6 +149,99 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
return 0;
}
static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state,
struct link_config_limits *limits)
{
struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
struct intel_dp *intel_dp = &intel_mst->primary->dp;
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int slots = -EINVAL;
int i, num_bpc;
u8 dsc_bpc[3] = {0};
int min_bpp, max_bpp, sink_min_bpp, sink_max_bpp;
u8 dsc_max_bpc;
bool need_timeslot_recalc = false;
u32 last_compressed_bpp;
/* Max DSC Input BPC for ICL is 10 and for TGL+ is 12 */
if (DISPLAY_VER(i915) >= 12)
dsc_max_bpc = min_t(u8, 12, conn_state->max_requested_bpc);
else
dsc_max_bpc = min_t(u8, 10, conn_state->max_requested_bpc);
max_bpp = min_t(u8, dsc_max_bpc * 3, limits->max_bpp);
min_bpp = limits->min_bpp;
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd,
dsc_bpc);
drm_dbg_kms(&i915->drm, "DSC Source supported min bpp %d max bpp %d\n",
min_bpp, max_bpp);
sink_max_bpp = dsc_bpc[0] * 3;
sink_min_bpp = sink_max_bpp;
for (i = 1; i < num_bpc; i++) {
if (sink_min_bpp > dsc_bpc[i] * 3)
sink_min_bpp = dsc_bpc[i] * 3;
if (sink_max_bpp < dsc_bpc[i] * 3)
sink_max_bpp = dsc_bpc[i] * 3;
}
drm_dbg_kms(&i915->drm, "DSC Sink supported min bpp %d max bpp %d\n",
sink_min_bpp, sink_max_bpp);
if (min_bpp < sink_min_bpp)
min_bpp = sink_min_bpp;
if (max_bpp > sink_max_bpp)
max_bpp = sink_max_bpp;
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state, max_bpp,
min_bpp, limits,
conn_state, 2 * 3, true);
if (slots < 0)
return slots;
last_compressed_bpp = crtc_state->dsc.compressed_bpp;
crtc_state->dsc.compressed_bpp = intel_dp_dsc_nearest_valid_bpp(i915,
last_compressed_bpp,
crtc_state->pipe_bpp);
if (crtc_state->dsc.compressed_bpp != last_compressed_bpp)
need_timeslot_recalc = true;
/*
* Apparently some MST hubs dislike if vcpi slots are not matching precisely
* the actual compressed bpp we use.
*/
if (need_timeslot_recalc) {
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
crtc_state->dsc.compressed_bpp,
crtc_state->dsc.compressed_bpp,
limits, conn_state, 2 * 3, true);
if (slots < 0)
return slots;
}
intel_link_compute_m_n(crtc_state->pipe_bpp,
crtc_state->lane_count,
adjusted_mode->crtc_clock,
crtc_state->port_clock,
&crtc_state->dp_m_n,
crtc_state->fec_enable);
crtc_state->dp_m_n.tu = slots;
return 0;
}
static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
@ -182,6 +318,29 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
conn_state, &limits);
if (ret == -EDEADLK)
return ret;
/* enable compression if the mode doesn't fit available BW */
drm_dbg_kms(&dev_priv->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en);
if (ret || intel_dp->force_dsc_en) {
/*
* Try to get at least some timeslots and then see, if
* we can fit there with DSC.
*/
drm_dbg_kms(&dev_priv->drm, "Trying to find VCPI slots in DSC mode\n");
ret = intel_dp_dsc_mst_compute_link_config(encoder, pipe_config,
conn_state, &limits);
if (ret < 0)
return ret;
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
conn_state, &limits,
pipe_config->dp_m_n.tu, false);
}
if (ret)
return ret;
@ -692,6 +851,10 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
int max_rate, mode_rate, max_lanes, max_link_clock;
int ret;
bool dsc = false, bigjoiner = false;
u16 dsc_max_output_bpp = 0;
u8 dsc_slice_count = 0;
int target_clock = mode->clock;
if (drm_connector_is_unregistered(connector)) {
*status = MODE_ERROR;
@ -729,6 +892,48 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
return 0;
}
if (intel_dp_need_bigjoiner(intel_dp, mode->hdisplay, target_clock)) {
bigjoiner = true;
max_dotclk *= 2;
}
if (DISPLAY_VER(dev_priv) >= 10 &&
drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)) {
/*
* TBD pass the connector BPC,
* for now U8_MAX so that max BPC on that platform would be picked
*/
int pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, U8_MAX);
if (drm_dp_sink_supports_fec(intel_dp->fec_capable)) {
dsc_max_output_bpp =
intel_dp_dsc_get_output_bpp(dev_priv,
max_link_clock,
max_lanes,
target_clock,
mode->hdisplay,
bigjoiner,
pipe_bpp, 64) >> 4;
dsc_slice_count =
intel_dp_dsc_get_slice_count(intel_dp,
target_clock,
mode->hdisplay,
bigjoiner);
}
dsc = dsc_max_output_bpp && dsc_slice_count;
}
/*
* Big joiner configuration needs DSC for TGL which is not true for
* XE_LPD where uncompressed joiner is supported.
*/
if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc)
return MODE_CLOCK_HIGH;
if (mode_rate > max_rate && !dsc)
return MODE_CLOCK_HIGH;
*status = intel_mode_valid_max_plane_size(dev_priv, mode, false);
return 0;
}

View File

@ -24,8 +24,10 @@ enum dsb_id {
struct intel_dsb {
enum dsb_id id;
u32 *cmd_buf;
struct i915_vma *vma;
struct intel_crtc *crtc;
/*
* free_pos will point the first free entry position
@ -113,7 +115,7 @@ static bool intel_dsb_disable_engine(struct drm_i915_private *i915,
/**
* intel_dsb_indexed_reg_write() -Write to the DSB context for auto
* increment register.
* @crtc_state: intel_crtc_state structure
* @dsb: DSB context
* @reg: register address.
* @val: value.
*
@ -123,20 +125,14 @@ static bool intel_dsb_disable_engine(struct drm_i915_private *i915,
* is done through mmio write.
*/
void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state,
void intel_dsb_indexed_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val)
{
struct intel_dsb *dsb = crtc_state->dsb;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 *buf;
u32 *buf = dsb->cmd_buf;
u32 reg_val;
if (!dsb) {
intel_de_write_fw(dev_priv, reg, val);
return;
}
buf = dsb->cmd_buf;
if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
return;
@ -200,21 +196,13 @@ void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state,
* and rest all erroneous condition register programming is done
* through mmio write.
*/
void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state,
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_dsb *dsb;
u32 *buf;
u32 *buf = dsb->cmd_buf;
dsb = crtc_state->dsb;
if (!dsb) {
intel_de_write_fw(dev_priv, reg, val);
return;
}
buf = dsb->cmd_buf;
if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
return;
@ -229,17 +217,14 @@ void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state,
/**
* intel_dsb_commit() - Trigger workload execution of DSB.
* @crtc_state: intel_crtc_state structure
* @dsb: DSB context
*
* This function is used to do actual write to hardware using DSB.
* On errors, fall back to MMIO. Also this function help to reset the context.
*/
void intel_dsb_commit(const struct intel_crtc_state *crtc_state)
void intel_dsb_commit(struct intel_dsb *dsb)
{
struct intel_dsb *dsb = crtc_state->dsb;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_crtc *crtc = dsb->crtc;
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 tail;
@ -286,14 +271,16 @@ void intel_dsb_commit(const struct intel_crtc_state *crtc_state)
/**
* intel_dsb_prepare() - Allocate, pin and map the DSB command buffer.
* @crtc_state: intel_crtc_state structure to prepare associated dsb instance.
* @crtc: the CRTC
*
* This function prepare the command buffer which is used to store dsb
* instructions with data.
*
* Returns:
* DSB context, NULL on failure
*/
void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_dsb *dsb;
struct drm_i915_gem_object *obj;
@ -302,63 +289,60 @@ void intel_dsb_prepare(struct intel_crtc_state *crtc_state)
intel_wakeref_t wakeref;
if (!HAS_DSB(i915))
return;
return NULL;
dsb = kmalloc(sizeof(*dsb), GFP_KERNEL);
if (!dsb) {
drm_err(&i915->drm, "DSB object creation failed\n");
return;
}
if (!dsb)
goto out;
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
if (IS_ERR(obj)) {
kfree(dsb);
goto out;
}
if (IS_ERR(obj))
goto out_put_rpm;
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
if (IS_ERR(vma)) {
i915_gem_object_put(obj);
kfree(dsb);
goto out;
goto out_put_rpm;
}
buf = i915_gem_object_pin_map_unlocked(vma->obj, I915_MAP_WC);
if (IS_ERR(buf)) {
i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
kfree(dsb);
goto out;
goto out_put_rpm;
}
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
dsb->id = DSB1;
dsb->vma = vma;
dsb->crtc = crtc;
dsb->cmd_buf = buf;
dsb->free_pos = 0;
dsb->ins_start_offset = 0;
crtc_state->dsb = dsb;
out:
if (!crtc_state->dsb)
drm_info(&i915->drm,
"DSB queue setup failed, will fallback to MMIO for display HW programming\n");
return dsb;
out_put_rpm:
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
kfree(dsb);
out:
drm_info_once(&i915->drm,
"DSB queue setup failed, will fallback to MMIO for display HW programming\n");
return NULL;
}
/**
* intel_dsb_cleanup() - To cleanup DSB context.
* @crtc_state: intel_crtc_state structure to cleanup associated dsb instance.
* @dsb: DSB context
*
* This function cleanup the DSB context by unpinning and releasing
* the VMA object associated with it.
*/
void intel_dsb_cleanup(struct intel_crtc_state *crtc_state)
void intel_dsb_cleanup(struct intel_dsb *dsb)
{
if (!crtc_state->dsb)
return;
i915_vma_unpin_and_release(&crtc_state->dsb->vma, I915_VMA_RELEASE_MAP);
kfree(crtc_state->dsb);
crtc_state->dsb = NULL;
i915_vma_unpin_and_release(&dsb->vma, I915_VMA_RELEASE_MAP);
kfree(dsb);
}

View File

@ -10,14 +10,15 @@
#include "i915_reg_defs.h"
struct intel_crtc_state;
struct intel_crtc;
struct intel_dsb;
void intel_dsb_prepare(struct intel_crtc_state *crtc_state);
void intel_dsb_cleanup(struct intel_crtc_state *crtc_state);
void intel_dsb_reg_write(const struct intel_crtc_state *crtc_state,
struct intel_dsb *intel_dsb_prepare(struct intel_crtc *crtc);
void intel_dsb_cleanup(struct intel_dsb *dsb);
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val);
void intel_dsb_indexed_reg_write(const struct intel_crtc_state *crtc_state,
void intel_dsb_indexed_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val);
void intel_dsb_commit(const struct intel_crtc_state *crtc_state);
void intel_dsb_commit(struct intel_dsb *dsb);
#endif

View File

@ -38,6 +38,7 @@
#include "intel_display_types.h"
#include "intel_dvo.h"
#include "intel_dvo_dev.h"
#include "intel_dvo_regs.h"
#include "intel_gmbus.h"
#include "intel_panel.h"
@ -56,48 +57,42 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
{
.type = INTEL_DVO_CHIP_TMDS,
.name = "sil164",
.dvo_reg = DVOC,
.dvo_srcdim_reg = DVOC_SRCDIM,
.port = PORT_C,
.slave_addr = SIL164_ADDR,
.dev_ops = &sil164_ops,
},
{
.type = INTEL_DVO_CHIP_TMDS,
.name = "ch7xxx",
.dvo_reg = DVOC,
.dvo_srcdim_reg = DVOC_SRCDIM,
.port = PORT_C,
.slave_addr = CH7xxx_ADDR,
.dev_ops = &ch7xxx_ops,
},
{
.type = INTEL_DVO_CHIP_TMDS,
.name = "ch7xxx",
.dvo_reg = DVOC,
.dvo_srcdim_reg = DVOC_SRCDIM,
.port = PORT_C,
.slave_addr = 0x75, /* For some ch7010 */
.dev_ops = &ch7xxx_ops,
},
{
.type = INTEL_DVO_CHIP_LVDS,
.name = "ivch",
.dvo_reg = DVOA,
.dvo_srcdim_reg = DVOA_SRCDIM,
.port = PORT_A,
.slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */
.dev_ops = &ivch_ops,
},
{
.type = INTEL_DVO_CHIP_TMDS,
.name = "tfp410",
.dvo_reg = DVOC,
.dvo_srcdim_reg = DVOC_SRCDIM,
.port = PORT_C,
.slave_addr = TFP410_ADDR,
.dev_ops = &tfp410_ops,
},
{
.type = INTEL_DVO_CHIP_LVDS,
.name = "ch7017",
.dvo_reg = DVOC,
.dvo_srcdim_reg = DVOC_SRCDIM,
.port = PORT_C,
.slave_addr = 0x75,
.gpio = GMBUS_PIN_DPB,
.dev_ops = &ch7017_ops,
@ -105,8 +100,7 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
{
.type = INTEL_DVO_CHIP_LVDS_NO_FIXED,
.name = "ns2501",
.dvo_reg = DVOB,
.dvo_srcdim_reg = DVOB_SRCDIM,
.port = PORT_B,
.slave_addr = NS2501_ADDR,
.dev_ops = &ns2501_ops,
},
@ -118,8 +112,6 @@ struct intel_dvo {
struct intel_dvo_device dev;
struct intel_connector *attached_connector;
bool panel_wants_dither;
};
static struct intel_dvo *enc_to_dvo(struct intel_encoder *encoder)
@ -134,12 +126,13 @@ static struct intel_dvo *intel_attached_dvo(struct intel_connector *connector)
static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_encoder *encoder = intel_attached_encoder(connector);
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
enum port port = encoder->port;
u32 tmp;
tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg);
tmp = intel_de_read(i915, DVO(port));
if (!(tmp & DVO_ENABLE))
return false;
@ -150,13 +143,13 @@ static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum port port = encoder->port;
u32 tmp;
tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg);
tmp = intel_de_read(i915, DVO(port));
*pipe = (tmp & DVO_PIPE_SEL_MASK) >> DVO_PIPE_SEL_SHIFT;
*pipe = REG_FIELD_GET(DVO_PIPE_SEL_MASK, tmp);
return tmp & DVO_ENABLE;
}
@ -164,13 +157,13 @@ static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
static void intel_dvo_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
enum port port = encoder->port;
u32 tmp, flags = 0;
pipe_config->output_types |= BIT(INTEL_OUTPUT_DVO);
tmp = intel_de_read(dev_priv, intel_dvo->dev.dvo_reg);
tmp = intel_de_read(i915, DVO(port));
if (tmp & DVO_HSYNC_ACTIVE_HIGH)
flags |= DRM_MODE_FLAG_PHSYNC;
else
@ -190,14 +183,14 @@ static void intel_disable_dvo(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
u32 temp = intel_de_read(dev_priv, dvo_reg);
enum port port = encoder->port;
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
intel_de_write(dev_priv, dvo_reg, temp & ~DVO_ENABLE);
intel_de_read(dev_priv, dvo_reg);
intel_de_rmw(i915, DVO(port), DVO_ENABLE, 0);
intel_de_posting_read(i915, DVO(port));
}
static void intel_enable_dvo(struct intel_atomic_state *state,
@ -205,30 +198,29 @@ static void intel_enable_dvo(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
u32 temp = intel_de_read(dev_priv, dvo_reg);
enum port port = encoder->port;
intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev,
&pipe_config->hw.mode,
&pipe_config->hw.adjusted_mode);
intel_de_write(dev_priv, dvo_reg, temp | DVO_ENABLE);
intel_de_read(dev_priv, dvo_reg);
intel_de_rmw(i915, DVO(port), 0, DVO_ENABLE);
intel_de_posting_read(i915, DVO(port));
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
}
static enum drm_mode_status
intel_dvo_mode_valid(struct drm_connector *connector,
intel_dvo_mode_valid(struct drm_connector *_connector,
struct drm_display_mode *mode)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector);
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
const struct drm_display_mode *fixed_mode =
intel_panel_fixed_mode(intel_connector, mode);
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
intel_panel_fixed_mode(connector, mode);
int max_dotclk = to_i915(connector->base.dev)->max_dotclk_freq;
int target_clock = mode->clock;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@ -239,7 +231,7 @@ intel_dvo_mode_valid(struct drm_connector *connector,
if (fixed_mode) {
enum drm_mode_status status;
status = intel_panel_mode_valid(intel_connector, mode);
status = intel_panel_mode_valid(connector, mode);
if (status != MODE_OK)
return status;
@ -289,18 +281,17 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
struct intel_dvo *intel_dvo = enc_to_dvo(encoder);
enum port port = encoder->port;
enum pipe pipe = crtc->pipe;
u32 dvo_val;
i915_reg_t dvo_reg = intel_dvo->dev.dvo_reg;
i915_reg_t dvo_srcdim_reg = intel_dvo->dev.dvo_srcdim_reg;
/* Save the data order, since I don't know what it should be set to. */
dvo_val = intel_de_read(dev_priv, dvo_reg) &
(DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
/* Save the active data order, since I don't know what it should be set to. */
dvo_val = intel_de_read(i915, DVO(port)) &
(DVO_DEDICATED_INT_ENABLE |
DVO_PRESERVE_MASK | DVO_ACT_DATA_ORDER_MASK);
dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE |
DVO_BLANK_ACTIVE_HIGH;
@ -311,19 +302,21 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state,
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
dvo_val |= DVO_VSYNC_ACTIVE_HIGH;
intel_de_write(dev_priv, dvo_srcdim_reg,
(adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));
intel_de_write(dev_priv, dvo_reg, dvo_val);
intel_de_write(i915, DVO_SRCDIM(port),
DVO_SRCDIM_HORIZONTAL(adjusted_mode->crtc_hdisplay) |
DVO_SRCDIM_VERTICAL(adjusted_mode->crtc_vdisplay));
intel_de_write(i915, DVO(port), dvo_val);
}
static enum drm_connector_status
intel_dvo_detect(struct drm_connector *connector, bool force)
intel_dvo_detect(struct drm_connector *_connector, bool force)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_dvo *intel_dvo = intel_attached_dvo(to_intel_connector(connector));
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);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n",
connector->base.base.id, connector->base.name);
if (!INTEL_DISPLAY_ENABLED(i915))
return connector_status_disconnected;
@ -331,9 +324,10 @@ intel_dvo_detect(struct drm_connector *connector, bool force)
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
}
static int intel_dvo_get_modes(struct drm_connector *connector)
static int intel_dvo_get_modes(struct drm_connector *_connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int num_modes;
/*
@ -342,12 +336,12 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
* (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case.
*/
num_modes = intel_ddc_get_modes(connector,
intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPC));
num_modes = intel_ddc_get_modes(&connector->base,
intel_gmbus_get_adapter(i915, GMBUS_PIN_DPC));
if (num_modes)
return num_modes;
return intel_panel_get_modes(to_intel_connector(connector));
return intel_panel_get_modes(connector);
}
static const struct drm_connector_funcs intel_dvo_connector_funcs = {
@ -379,165 +373,187 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
.destroy = intel_dvo_enc_destroy,
};
static enum port intel_dvo_port(i915_reg_t dvo_reg)
static int intel_dvo_encoder_type(const struct intel_dvo_device *dvo)
{
if (i915_mmio_reg_equal(dvo_reg, DVOA))
return PORT_A;
else if (i915_mmio_reg_equal(dvo_reg, DVOB))
return PORT_B;
else
return PORT_C;
switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS:
return DRM_MODE_ENCODER_TMDS;
case INTEL_DVO_CHIP_LVDS_NO_FIXED:
case INTEL_DVO_CHIP_LVDS:
return DRM_MODE_ENCODER_LVDS;
default:
MISSING_CASE(dvo->type);
return DRM_MODE_ENCODER_NONE;
}
}
void intel_dvo_init(struct drm_i915_private *dev_priv)
static int intel_dvo_connector_type(const struct intel_dvo_device *dvo)
{
switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS:
return DRM_MODE_CONNECTOR_DVII;
case INTEL_DVO_CHIP_LVDS_NO_FIXED:
case INTEL_DVO_CHIP_LVDS:
return DRM_MODE_CONNECTOR_LVDS;
default:
MISSING_CASE(dvo->type);
return DRM_MODE_CONNECTOR_Unknown;
}
}
static bool intel_dvo_init_dev(struct drm_i915_private *dev_priv,
struct intel_dvo *intel_dvo,
const struct intel_dvo_device *dvo)
{
struct i2c_adapter *i2c;
u32 dpll[I915_MAX_PIPES];
enum pipe pipe;
int gpio;
bool ret;
/*
* Allow the I2C driver info to specify the GPIO to be used in
* special cases, but otherwise default to what's defined
* in the spec.
*/
if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio))
gpio = dvo->gpio;
else if (dvo->type == INTEL_DVO_CHIP_LVDS)
gpio = GMBUS_PIN_SSC;
else
gpio = GMBUS_PIN_DPB;
/*
* Set up the I2C bus necessary for the chip we're probing.
* It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA).
*/
i2c = intel_gmbus_get_adapter(dev_priv, gpio);
intel_dvo->dev = *dvo;
/*
* GMBUS NAK handling seems to be unstable, hence let the
* transmitter detection run in bit banging mode for now.
*/
intel_gmbus_force_bit(i2c, true);
/*
* ns2501 requires the DVO 2x clock before it will
* respond to i2c accesses, so make sure we have
* the clock enabled before we attempt to initialize
* the device.
*/
for_each_pipe(dev_priv, pipe) {
dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe));
intel_de_write(dev_priv, DPLL(pipe),
dpll[pipe] | DPLL_DVO_2X_MODE);
}
ret = dvo->dev_ops->init(&intel_dvo->dev, i2c);
/* restore the DVO 2x clock state to original */
for_each_pipe(dev_priv, pipe) {
intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]);
}
intel_gmbus_force_bit(i2c, false);
return ret;
}
static bool intel_dvo_probe(struct drm_i915_private *i915,
struct intel_dvo *intel_dvo)
{
struct intel_encoder *intel_encoder;
struct intel_dvo *intel_dvo;
struct intel_connector *intel_connector;
int i;
int encoder_type = DRM_MODE_ENCODER_NONE;
/* Now, try to find a controller */
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
if (intel_dvo_init_dev(i915, intel_dvo,
&intel_dvo_devices[i]))
return true;
}
return false;
}
void intel_dvo_init(struct drm_i915_private *i915)
{
struct intel_connector *connector;
struct intel_encoder *encoder;
struct intel_dvo *intel_dvo;
intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL);
if (!intel_dvo)
return;
intel_connector = intel_connector_alloc();
if (!intel_connector) {
connector = intel_connector_alloc();
if (!connector) {
kfree(intel_dvo);
return;
}
intel_dvo->attached_connector = intel_connector;
intel_dvo->attached_connector = connector;
intel_encoder = &intel_dvo->base;
encoder = &intel_dvo->base;
intel_encoder->disable = intel_disable_dvo;
intel_encoder->enable = intel_enable_dvo;
intel_encoder->get_hw_state = intel_dvo_get_hw_state;
intel_encoder->get_config = intel_dvo_get_config;
intel_encoder->compute_config = intel_dvo_compute_config;
intel_encoder->pre_enable = intel_dvo_pre_enable;
intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
/* Now, try to find a controller */
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
struct drm_connector *connector = &intel_connector->base;
const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
struct i2c_adapter *i2c;
int gpio;
bool dvoinit;
enum pipe pipe;
u32 dpll[I915_MAX_PIPES];
enum port port;
/*
* Allow the I2C driver info to specify the GPIO to be used in
* special cases, but otherwise default to what's defined
* in the spec.
*/
if (intel_gmbus_is_valid_pin(dev_priv, dvo->gpio))
gpio = dvo->gpio;
else if (dvo->type == INTEL_DVO_CHIP_LVDS)
gpio = GMBUS_PIN_SSC;
else
gpio = GMBUS_PIN_DPB;
/*
* Set up the I2C bus necessary for the chip we're probing.
* It appears that everything is on GPIOE except for panels
* on i830 laptops, which are on GPIOB (DVOA).
*/
i2c = intel_gmbus_get_adapter(dev_priv, gpio);
intel_dvo->dev = *dvo;
/*
* GMBUS NAK handling seems to be unstable, hence let the
* transmitter detection run in bit banging mode for now.
*/
intel_gmbus_force_bit(i2c, true);
/*
* ns2501 requires the DVO 2x clock before it will
* respond to i2c accesses, so make sure we have
* have the clock enabled before we attempt to
* initialize the device.
*/
for_each_pipe(dev_priv, pipe) {
dpll[pipe] = intel_de_read(dev_priv, DPLL(pipe));
intel_de_write(dev_priv, DPLL(pipe),
dpll[pipe] | DPLL_DVO_2X_MODE);
}
dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c);
/* restore the DVO 2x clock state to original */
for_each_pipe(dev_priv, pipe) {
intel_de_write(dev_priv, DPLL(pipe), dpll[pipe]);
}
intel_gmbus_force_bit(i2c, false);
if (!dvoinit)
continue;
port = intel_dvo_port(dvo->dvo_reg);
drm_encoder_init(&dev_priv->drm, &intel_encoder->base,
&intel_dvo_enc_funcs, encoder_type,
"DVO %c", port_name(port));
intel_encoder->type = INTEL_OUTPUT_DVO;
intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
intel_encoder->port = port;
intel_encoder->pipe_mask = ~0;
if (dvo->type != INTEL_DVO_CHIP_LVDS)
intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) |
BIT(INTEL_OUTPUT_DVO);
switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS:
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
drm_connector_init(&dev_priv->drm, connector,
&intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_DVII);
encoder_type = DRM_MODE_ENCODER_TMDS;
break;
case INTEL_DVO_CHIP_LVDS_NO_FIXED:
case INTEL_DVO_CHIP_LVDS:
drm_connector_init(&dev_priv->drm, connector,
&intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
encoder_type = DRM_MODE_ENCODER_LVDS;
break;
}
drm_connector_helper_add(connector,
&intel_dvo_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
intel_connector_attach_encoder(intel_connector, intel_encoder);
if (dvo->type == INTEL_DVO_CHIP_LVDS) {
/*
* For our LVDS chipsets, we should hopefully be able
* to dig the fixed panel mode out of the BIOS data.
* However, it's in a different format from the BIOS
* data on chipsets with integrated LVDS (stored in AIM
* headers, likely), so for now, just get the current
* mode being output through DVO.
*/
intel_panel_add_encoder_fixed_mode(intel_connector,
intel_encoder);
intel_panel_init(intel_connector);
intel_dvo->panel_wants_dither = true;
}
encoder->disable = intel_disable_dvo;
encoder->enable = intel_enable_dvo;
encoder->get_hw_state = intel_dvo_get_hw_state;
encoder->get_config = intel_dvo_get_config;
encoder->compute_config = intel_dvo_compute_config;
encoder->pre_enable = intel_dvo_pre_enable;
connector->get_hw_state = intel_dvo_connector_get_hw_state;
if (!intel_dvo_probe(i915, intel_dvo)) {
kfree(intel_dvo);
intel_connector_free(connector);
return;
}
kfree(intel_dvo);
kfree(intel_connector);
encoder->type = INTEL_OUTPUT_DVO;
encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
encoder->port = intel_dvo->dev.port;
encoder->pipe_mask = ~0;
if (intel_dvo->dev.type != INTEL_DVO_CHIP_LVDS)
encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) |
BIT(INTEL_OUTPUT_DVO);
drm_encoder_init(&i915->drm, &encoder->base,
&intel_dvo_enc_funcs,
intel_dvo_encoder_type(&intel_dvo->dev),
"DVO %c", port_name(encoder->port));
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] detected %s\n",
encoder->base.base.id, encoder->base.name,
intel_dvo->dev.name);
if (intel_dvo->dev.type == INTEL_DVO_CHIP_TMDS)
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
drm_connector_init(&i915->drm, &connector->base,
&intel_dvo_connector_funcs,
intel_dvo_connector_type(&intel_dvo->dev));
drm_connector_helper_add(&connector->base,
&intel_dvo_connector_helper_funcs);
connector->base.display_info.subpixel_order = SubPixelHorizontalRGB;
intel_connector_attach_encoder(connector, encoder);
if (intel_dvo->dev.type == INTEL_DVO_CHIP_LVDS) {
/*
* For our LVDS chipsets, we should hopefully be able
* to dig the fixed panel mode out of the BIOS data.
* However, it's in a different format from the BIOS
* data on chipsets with integrated LVDS (stored in AIM
* headers, likely), so for now, just get the current
* mode being output through DVO.
*/
intel_panel_add_encoder_fixed_mode(connector, encoder);
intel_panel_init(connector);
}
}

View File

@ -25,6 +25,8 @@
#include "i915_reg_defs.h"
#include "intel_display.h"
enum drm_connector_status;
struct drm_display_mode;
struct i2c_adapter;
@ -32,9 +34,8 @@ struct i2c_adapter;
struct intel_dvo_device {
const char *name;
int type;
/* DVOA/B/C output register */
i915_reg_t dvo_reg;
i915_reg_t dvo_srcdim_reg;
/* DVOA/B/C */
enum port port;
/* GPIO register used for i2c bus to control this device */
u32 gpio;
int slave_addr;

View File

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2022 Intel Corporation
*/
#ifndef __INTEL_DVO_REGS_H__
#define __INTEL_DVO_REGS_H__
#include "intel_display_reg_defs.h"
#define _DVOA 0x61120
#define _DVOB 0x61140
#define _DVOC 0x61160
#define DVO(port) _MMIO_PORT((port), _DVOA, _DVOB)
#define DVO_ENABLE REG_BIT(31)
#define DVO_PIPE_SEL_MASK REG_BIT(30)
#define DVO_PIPE_SEL(pipe) REG_FIELD_PREP(DVO_PIPE_SEL_MASK, (pipe))
#define DVO_PIPE_STALL_MASK REG_GENMASK(29, 28)
#define DVO_PIPE_STALL_UNUSED REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 0)
#define DVO_PIPE_STALL REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 1)
#define DVO_PIPE_STALL_TV REG_FIELD_PREP(DVO_PIPE_STALL_MASK, 2)
#define DVO_INTERRUPT_SELECT REG_BIT(27)
#define DVO_DEDICATED_INT_ENABLE REG_BIT(26)
#define DVO_PRESERVE_MASK REG_GENMASK(25, 24)
#define DVO_USE_VGA_SYNC REG_BIT(15)
#define DVO_DATA_ORDER_MASK REG_BIT(14)
#define DVO_DATA_ORDER_I740 REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 0)
#define DVO_DATA_ORDER_FP REG_FIELD_PREP(DVO_DATA_ORDER_MASK, 1)
#define DVO_VSYNC_DISABLE REG_BIT(11)
#define DVO_HSYNC_DISABLE REG_BIT(10)
#define DVO_VSYNC_TRISTATE REG_BIT(9)
#define DVO_HSYNC_TRISTATE REG_BIT(8)
#define DVO_BORDER_ENABLE REG_BIT(7)
#define DVO_ACT_DATA_ORDER_MASK REG_BIT(6)
#define DVO_ACT_DATA_ORDER_RGGB REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0)
#define DVO_ACT_DATA_ORDER_GBRG REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1)
#define DVO_ACT_DATA_ORDER_GBRG_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 0)
#define DVO_ACT_DATA_ORDER_RGGB_ERRATA REG_FIELD_PREP(DVO_ACT_DATA_ORDER_MASK, 1)
#define DVO_VSYNC_ACTIVE_HIGH REG_BIT(4)
#define DVO_HSYNC_ACTIVE_HIGH REG_BIT(3)
#define DVO_BLANK_ACTIVE_HIGH REG_BIT(2)
#define DVO_OUTPUT_CSTATE_PIXELS REG_BIT(1) /* SDG only */
#define DVO_OUTPUT_SOURCE_SIZE_PIXELS REG_BIT(0) /* SDG only */
#define _DVOA_SRCDIM 0x61124
#define _DVOB_SRCDIM 0x61144
#define _DVOC_SRCDIM 0x61164
#define DVO_SRCDIM(port) _MMIO_PORT((port), _DVOA_SRCDIM, _DVOB_SRCDIM)
#define DVO_SRCDIM_HORIZONTAL_MASK REG_GENMASK(22, 12)
#define DVO_SRCDIM_HORIZONTAL(x) REG_FIELD_PREP(DVO_SRCDIM_HORIZONTAL_MASK, (x))
#define DVO_SRCDIM_VERTICAL_MASK REG_GENMASK(10, 0)
#define DVO_SRCDIM_VERTICAL(x) REG_FIELD_PREP(DVO_SRCDIM_VERTICAL_MASK, (x))
#endif /* __INTEL_DVO_REGS_H__ */

View File

@ -174,7 +174,7 @@ static const struct intel_modifier_desc intel_modifiers[] = {
.plane_caps = INTEL_PLANE_CAP_TILING_4 | INTEL_PLANE_CAP_CCS_RC,
}, {
.modifier = I915_FORMAT_MOD_4_TILED,
.display_ver = { 13, 13 },
.display_ver = { 13, -1 },
.plane_caps = INTEL_PLANE_CAP_TILING_4,
}, {
.modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,

View File

@ -323,10 +323,8 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc)
enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane;
struct drm_i915_private *dev_priv = fbc->i915;
spin_lock_irq(&dev_priv->uncore.lock);
intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
intel_de_read_fw(dev_priv, DSPADDR(i9xx_plane)));
spin_unlock_irq(&dev_priv->uncore.lock);
}
static void i8xx_fbc_program_cfb(struct intel_fbc *fbc)
@ -359,10 +357,8 @@ static void i965_fbc_nuke(struct intel_fbc *fbc)
enum i9xx_plane_id i9xx_plane = fbc_state->plane->i9xx_plane;
struct drm_i915_private *dev_priv = fbc->i915;
spin_lock_irq(&dev_priv->uncore.lock);
intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
intel_de_read_fw(dev_priv, DSPSURF(i9xx_plane)));
spin_unlock_irq(&dev_priv->uncore.lock);
}
static const struct intel_fbc_funcs i965_fbc_funcs = {
@ -815,7 +811,7 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc)
static void intel_fbc_program_workarounds(struct intel_fbc *fbc)
{
/* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp */
/* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp,mtl */
if (DISPLAY_VER(fbc->i915) >= 11 && !IS_DG2(fbc->i915))
intel_de_rmw(fbc->i915, ILK_DPFC_CHICKEN(fbc->id), 0,
DPFC_CHICKEN_FORCE_SLB_INVALIDATION);
@ -1095,7 +1091,9 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state,
}
/* Wa_14016291713 */
if (IS_DISPLAY_VER(i915, 12, 13) && crtc_state->has_psr) {
if ((IS_DISPLAY_VER(i915, 12, 13) ||
IS_MTL_DISPLAY_STEP(i915, STEP_A0, STEP_C0)) &&
crtc_state->has_psr) {
plane_state->no_fbc_reason = "PSR1 enabled (Wa_14016291713)";
return 0;
}

View File

@ -255,14 +255,12 @@ static void bxt_gmbus_clock_gating(struct drm_i915_private *i915,
static u32 get_reserved(struct intel_gmbus *bus)
{
struct drm_i915_private *i915 = bus->i915;
struct intel_uncore *uncore = &i915->uncore;
u32 reserved = 0;
/* On most chips, these bits must be preserved in software. */
if (!IS_I830(i915) && !IS_I845G(i915))
reserved = intel_uncore_read_notrace(uncore, bus->gpio_reg) &
(GPIO_DATA_PULLUP_DISABLE |
GPIO_CLOCK_PULLUP_DISABLE);
reserved = intel_de_read_notrace(i915, bus->gpio_reg) &
(GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE);
return reserved;
}
@ -270,37 +268,31 @@ static u32 get_reserved(struct intel_gmbus *bus)
static int get_clock(void *data)
{
struct intel_gmbus *bus = data;
struct intel_uncore *uncore = &bus->i915->uncore;
struct drm_i915_private *i915 = bus->i915;
u32 reserved = get_reserved(bus);
intel_uncore_write_notrace(uncore,
bus->gpio_reg,
reserved | GPIO_CLOCK_DIR_MASK);
intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved);
intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK);
intel_de_write_notrace(i915, bus->gpio_reg, reserved);
return (intel_uncore_read_notrace(uncore, bus->gpio_reg) &
GPIO_CLOCK_VAL_IN) != 0;
return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0;
}
static int get_data(void *data)
{
struct intel_gmbus *bus = data;
struct intel_uncore *uncore = &bus->i915->uncore;
struct drm_i915_private *i915 = bus->i915;
u32 reserved = get_reserved(bus);
intel_uncore_write_notrace(uncore,
bus->gpio_reg,
reserved | GPIO_DATA_DIR_MASK);
intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved);
intel_de_write_notrace(i915, bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK);
intel_de_write_notrace(i915, bus->gpio_reg, reserved);
return (intel_uncore_read_notrace(uncore, bus->gpio_reg) &
GPIO_DATA_VAL_IN) != 0;
return (intel_de_read_notrace(i915, bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0;
}
static void set_clock(void *data, int state_high)
{
struct intel_gmbus *bus = data;
struct intel_uncore *uncore = &bus->i915->uncore;
struct drm_i915_private *i915 = bus->i915;
u32 reserved = get_reserved(bus);
u32 clock_bits;
@ -310,16 +302,14 @@ static void set_clock(void *data, int state_high)
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
GPIO_CLOCK_VAL_MASK;
intel_uncore_write_notrace(uncore,
bus->gpio_reg,
reserved | clock_bits);
intel_uncore_posting_read(uncore, bus->gpio_reg);
intel_de_write_notrace(i915, bus->gpio_reg, reserved | clock_bits);
intel_de_posting_read(i915, bus->gpio_reg);
}
static void set_data(void *data, int state_high)
{
struct intel_gmbus *bus = data;
struct intel_uncore *uncore = &bus->i915->uncore;
struct drm_i915_private *i915 = bus->i915;
u32 reserved = get_reserved(bus);
u32 data_bits;
@ -329,8 +319,8 @@ static void set_data(void *data, int state_high)
data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
GPIO_DATA_VAL_MASK;
intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved | data_bits);
intel_uncore_posting_read(uncore, bus->gpio_reg);
intel_de_write_notrace(i915, bus->gpio_reg, reserved | data_bits);
intel_de_posting_read(i915, bus->gpio_reg);
}
static int
@ -439,9 +429,7 @@ gmbus_wait_idle(struct drm_i915_private *i915)
add_wait_queue(&i915->display.gmbus.wait_queue, &wait);
intel_de_write_fw(i915, GMBUS4(i915), irq_enable);
ret = intel_wait_for_register_fw(&i915->uncore,
GMBUS2(i915), GMBUS_ACTIVE, 0,
10);
ret = intel_de_wait_for_register_fw(i915, GMBUS2(i915), GMBUS_ACTIVE, 0, 10);
intel_de_write_fw(i915, GMBUS4(i915), 0);
remove_wait_queue(&i915->display.gmbus.wait_queue, &wait);

View File

@ -537,7 +537,8 @@ void hsw_write_infoframe(struct intel_encoder *encoder,
0);
/* Wa_14013475917 */
if (DISPLAY_VER(dev_priv) == 13 && crtc_state->has_psr &&
if ((DISPLAY_VER(dev_priv) == 13 ||
IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)) && crtc_state->has_psr &&
type == DP_SDP_VSC)
return;
@ -767,6 +768,7 @@ intel_hdmi_compute_spd_infoframe(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);
struct hdmi_spd_infoframe *frame = &crtc_state->infoframes.spd.spd;
int ret;
@ -776,7 +778,11 @@ intel_hdmi_compute_spd_infoframe(struct intel_encoder *encoder,
crtc_state->infoframes.enable |=
intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD);
ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx");
if (IS_DGFX(i915))
ret = hdmi_spd_infoframe_init(frame, "Intel", "Discrete gfx");
else
ret = hdmi_spd_infoframe_init(frame, "Intel", "Integrated gfx");
if (drm_WARN_ON(encoder->base.dev, ret))
return false;
@ -1988,9 +1994,6 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state);
bool ycbcr_420_only;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
clock *= 2;
@ -2252,6 +2255,10 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
return -EINVAL;
if (!connector->interlace_allowed &&
adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return -EINVAL;
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
pipe_config->has_hdmi_sink =
intel_has_hdmi_sink(intel_hdmi, conn_state) &&
@ -2953,7 +2960,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
ddc);
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
connector->interlace_allowed = true;
if (DISPLAY_VER(dev_priv) < 12)
connector->interlace_allowed = true;
connector->stereo_allowed = true;
if (DISPLAY_VER(dev_priv) >= 10)

View File

@ -21,6 +21,9 @@ void intel_hti_init(struct drm_i915_private *i915)
bool intel_hti_uses_phy(struct drm_i915_private *i915, enum phy phy)
{
if (drm_WARN_ON(&i915->drm, phy == PHY_NONE))
return false;
return i915->display.hti.state & HDPORT_ENABLED &&
i915->display.hti.state & HDPORT_DDI_USED(phy);
}

View File

@ -964,8 +964,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
}
intel_connector->edid = edid;
intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL,
IS_ERR(edid) ? NULL : edid);
intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL,
IS_ERR(edid) ? NULL : edid);
/* Try EDID first */
intel_panel_add_edid_fixed_modes(intel_connector, true);

View File

@ -661,6 +661,15 @@ intel_panel_mode_valid(struct intel_connector *connector,
return MODE_OK;
}
void intel_panel_init_alloc(struct intel_connector *connector)
{
struct intel_panel *panel = &connector->panel;
connector->panel.vbt.panel_type = -1;
connector->panel.vbt.backlight.controller = -1;
INIT_LIST_HEAD(&panel->fixed_modes);
}
int intel_panel_init(struct intel_connector *connector)
{
struct intel_panel *panel = &connector->panel;

View File

@ -18,6 +18,7 @@ struct intel_connector;
struct intel_crtc_state;
struct intel_encoder;
void intel_panel_init_alloc(struct intel_connector *connector);
int intel_panel_init(struct intel_connector *connector);
void intel_panel_fini(struct intel_connector *connector);
enum drm_connector_status

View File

@ -22,6 +22,40 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
static void pps_init_delays(struct intel_dp *intel_dp);
static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd);
static const char *pps_name(struct drm_i915_private *i915,
struct intel_pps *pps)
{
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
switch (pps->pps_pipe) {
case INVALID_PIPE:
/*
* FIXME would be nice if we can guarantee
* to always have a valid PPS when calling this.
*/
return "PPS <none>";
case PIPE_A:
return "PPS A";
case PIPE_B:
return "PPS B";
default:
MISSING_CASE(pps->pps_pipe);
break;
}
} else {
switch (pps->pps_idx) {
case 0:
return "PPS 0";
case 1:
return "PPS 1";
default:
MISSING_CASE(pps->pps_idx);
break;
}
}
return "PPS <invalid>";
}
intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@ -60,15 +94,15 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
if (drm_WARN(&dev_priv->drm,
intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN,
"skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n",
pipe_name(pipe), dig_port->base.base.base.id,
dig_port->base.base.name))
"skipping %s kick due to [ENCODER:%d:%s] being active\n",
pps_name(dev_priv, &intel_dp->pps),
dig_port->base.base.base.id, dig_port->base.base.name))
return;
drm_dbg_kms(&dev_priv->drm,
"kicking pipe %c power sequencer for [ENCODER:%d:%s]\n",
pipe_name(pipe), dig_port->base.base.base.id,
dig_port->base.base.name);
"kicking %s for [ENCODER:%d:%s]\n",
pps_name(dev_priv, &intel_dp->pps),
dig_port->base.base.base.id, dig_port->base.base.name);
/* Preserve the BIOS-computed detected bit. This is
* supposed to be read-only.
@ -95,7 +129,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) {
drm_err(&dev_priv->drm,
"Failed to force on pll for pipe %c!\n",
"Failed to force on PLL for pipe %c!\n",
pipe_name(pipe));
return;
}
@ -190,10 +224,9 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
intel_dp->pps.pps_pipe = pipe;
drm_dbg_kms(&dev_priv->drm,
"picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
pipe_name(intel_dp->pps.pps_pipe),
dig_port->base.base.base.id,
dig_port->base.base.name);
"picked %s for [ENCODER:%d:%s]\n",
pps_name(dev_priv, &intel_dp->pps),
dig_port->base.base.base.id, dig_port->base.base.name);
/* init power sequencer on this pipe and port */
pps_init_delays(intel_dp);
@ -212,8 +245,7 @@ static int
bxt_power_sequencer_idx(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct intel_connector *connector = intel_dp->attached_connector;
int backlight_controller = connector->panel.vbt.backlight.controller;
int pps_idx = intel_dp->pps.pps_idx;
lockdep_assert_held(&dev_priv->display.pps.mutex);
@ -221,7 +253,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
if (!intel_dp->pps.pps_reset)
return backlight_controller;
return pps_idx;
intel_dp->pps.pps_reset = false;
@ -231,34 +263,29 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
*/
pps_init_registers(intel_dp, false);
return backlight_controller;
return pps_idx;
}
typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
enum pipe pipe);
typedef bool (*pps_check)(struct drm_i915_private *dev_priv, int pps_idx);
static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
enum pipe pipe)
static bool pps_has_pp_on(struct drm_i915_private *dev_priv, int pps_idx)
{
return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON;
return intel_de_read(dev_priv, PP_STATUS(pps_idx)) & PP_ON;
}
static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
enum pipe pipe)
static bool pps_has_vdd_on(struct drm_i915_private *dev_priv, int pps_idx)
{
return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD;
return intel_de_read(dev_priv, PP_CONTROL(pps_idx)) & EDP_FORCE_VDD;
}
static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
enum pipe pipe)
static bool pps_any(struct drm_i915_private *dev_priv, int pps_idx)
{
return true;
}
static enum pipe
vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
enum port port,
vlv_pipe_check pipe_check)
enum port port, pps_check check)
{
enum pipe pipe;
@ -269,7 +296,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
if (port_sel != PANEL_PORT_SELECT_VLV(port))
continue;
if (!pipe_check(dev_priv, pipe))
if (!check(dev_priv, pipe))
continue;
return pipe;
@ -290,30 +317,117 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
/* try to find a pipe with this port selected */
/* first pick one where the panel is on */
intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
vlv_pipe_has_pp_on);
pps_has_pp_on);
/* didn't find one? pick one where vdd is on */
if (intel_dp->pps.pps_pipe == INVALID_PIPE)
intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
vlv_pipe_has_vdd_on);
pps_has_vdd_on);
/* didn't find one? pick one with just the correct port */
if (intel_dp->pps.pps_pipe == INVALID_PIPE)
intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
vlv_pipe_any);
pps_any);
/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
if (intel_dp->pps.pps_pipe == INVALID_PIPE) {
drm_dbg_kms(&dev_priv->drm,
"no initial power sequencer for [ENCODER:%d:%s]\n",
dig_port->base.base.base.id,
dig_port->base.base.name);
"[ENCODER:%d:%s] no initial power sequencer\n",
dig_port->base.base.base.id, dig_port->base.base.name);
return;
}
drm_dbg_kms(&dev_priv->drm,
"initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
dig_port->base.base.base.id,
dig_port->base.base.name,
pipe_name(intel_dp->pps.pps_pipe));
"[ENCODER:%d:%s] initial power sequencer: %s\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
}
static int intel_num_pps(struct drm_i915_private *i915)
{
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
return 2;
if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))
return 2;
if (INTEL_PCH_TYPE(i915) >= PCH_DG1)
return 1;
if (INTEL_PCH_TYPE(i915) >= PCH_ICP)
return 2;
return 1;
}
static bool intel_pps_is_valid(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
if (intel_dp->pps.pps_idx == 1 &&
INTEL_PCH_TYPE(i915) >= PCH_ICP &&
INTEL_PCH_TYPE(i915) < PCH_MTP)
return intel_de_read(i915, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT;
return true;
}
static int
bxt_initial_pps_idx(struct drm_i915_private *i915, pps_check check)
{
int pps_idx, pps_num = intel_num_pps(i915);
for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
if (check(i915, pps_idx))
return pps_idx;
}
return -1;
}
static bool
pps_initial_setup(struct intel_dp *intel_dp)
{
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct intel_connector *connector = intel_dp->attached_connector;
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
lockdep_assert_held(&i915->display.pps.mutex);
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
vlv_initial_power_sequencer_setup(intel_dp);
return true;
}
/* first ask the VBT */
if (intel_num_pps(i915) > 1)
intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller;
else
intel_dp->pps.pps_idx = 0;
if (drm_WARN_ON(&i915->drm, intel_dp->pps.pps_idx >= intel_num_pps(i915)))
intel_dp->pps.pps_idx = -1;
/* VBT wasn't parsed yet? pick one where the panel is on */
if (intel_dp->pps.pps_idx < 0)
intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_has_pp_on);
/* didn't find one? pick one where vdd is on */
if (intel_dp->pps.pps_idx < 0)
intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_has_vdd_on);
/* didn't find one? pick any */
if (intel_dp->pps.pps_idx < 0) {
intel_dp->pps.pps_idx = bxt_initial_pps_idx(i915, pps_any);
drm_dbg_kms(&i915->drm,
"[ENCODER:%d:%s] no initial power sequencer, assuming %s\n",
encoder->base.base.id, encoder->base.name,
pps_name(i915, &intel_dp->pps));
} else {
drm_dbg_kms(&i915->drm,
"[ENCODER:%d:%s] initial power sequencer: %s\n",
encoder->base.base.id, encoder->base.name,
pps_name(i915, &intel_dp->pps));
}
return intel_pps_is_valid(intel_dp);
}
void intel_pps_reset_all(struct drm_i915_private *dev_priv)
@ -364,14 +478,16 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp,
struct pps_registers *regs)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
int pps_idx = 0;
int pps_idx;
memset(regs, 0, sizeof(*regs));
if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
pps_idx = bxt_power_sequencer_idx(intel_dp);
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
pps_idx = vlv_power_sequencer_pipe(intel_dp);
else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
pps_idx = bxt_power_sequencer_idx(intel_dp);
else
pps_idx = intel_dp->pps.pps_idx;
regs->pp_ctrl = PP_CONTROL(pps_idx);
regs->pp_stat = PP_STATUS(pps_idx);
@ -435,21 +551,27 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
void intel_pps_check_power_unlocked(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
if (!intel_dp_is_edp(intel_dp))
return;
if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
drm_WARN(&dev_priv->drm, 1,
"eDP powered off while attempting aux channel communication.\n");
drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n",
"[ENCODER:%d:%s] %s powered off while attempting AUX CH communication.\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
drm_dbg_kms(&dev_priv->drm,
"[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps),
intel_de_read(dev_priv, _pp_stat_reg(intel_dp)),
intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)));
}
}
#define IDLE_ON_MASK (PP_ON | PP_SEQUENCE_MASK | 0 | PP_SEQUENCE_STATE_MASK)
#define IDLE_ON_VALUE (PP_ON | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE)
#define IDLE_ON_VALUE (PP_ON | PP_SEQUENCE_NONE | 0 | PP_SEQUENCE_STATE_ON_IDLE)
#define IDLE_OFF_MASK (PP_ON | PP_SEQUENCE_MASK | 0 | 0)
#define IDLE_OFF_VALUE (0 | PP_SEQUENCE_NONE | 0 | 0)
@ -460,10 +582,10 @@ void intel_pps_check_power_unlocked(struct intel_dp *intel_dp)
static void intel_pps_verify_state(struct intel_dp *intel_dp);
static void wait_panel_status(struct intel_dp *intel_dp,
u32 mask,
u32 value)
u32 mask, u32 value)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
i915_reg_t pp_stat_reg, pp_ctrl_reg;
lockdep_assert_held(&dev_priv->display.pps.mutex);
@ -474,7 +596,9 @@ static void wait_panel_status(struct intel_dp *intel_dp,
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
drm_dbg_kms(&dev_priv->drm,
"mask %08x value %08x status %08x control %08x\n",
"[ENCODER:%d:%s] %s mask: 0x%08x value: 0x%08x PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps),
mask, value,
intel_de_read(dev_priv, pp_stat_reg),
intel_de_read(dev_priv, pp_ctrl_reg));
@ -482,7 +606,9 @@ static void wait_panel_status(struct intel_dp *intel_dp,
if (intel_de_wait_for_register(dev_priv, pp_stat_reg,
mask, value, 5000))
drm_err(&dev_priv->drm,
"Panel status timeout: status %08x control %08x\n",
"[ENCODER:%d:%s] %s panel status timeout: PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps),
intel_de_read(dev_priv, pp_stat_reg),
intel_de_read(dev_priv, pp_ctrl_reg));
@ -492,26 +618,35 @@ static void wait_panel_status(struct intel_dp *intel_dp,
static void wait_panel_on(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
drm_dbg_kms(&i915->drm, "Wait for panel power on\n");
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power on\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(i915, &intel_dp->pps));
wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
}
static void wait_panel_off(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
drm_dbg_kms(&i915->drm, "Wait for panel power off time\n");
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power off time\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(i915, &intel_dp->pps));
wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
}
static void wait_panel_power_cycle(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
ktime_t panel_power_on_time;
s64 panel_power_off_duration;
drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n");
drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] %s wait for panel power cycle\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(i915, &intel_dp->pps));
/* take the difference of current time and panel power off time
* and then make panel wait for t11_t12 if needed. */
@ -598,9 +733,12 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv,
intel_aux_power_domain(dig_port));
drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
dig_port->base.base.base.id,
dig_port->base.base.name);
pp_stat_reg = _pp_stat_reg(intel_dp);
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turning VDD on\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
if (!edp_have_panel_power(intel_dp))
wait_panel_power_cycle(intel_dp);
@ -608,12 +746,11 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
pp = ilk_get_pp_control(intel_dp);
pp |= EDP_FORCE_VDD;
pp_stat_reg = _pp_stat_reg(intel_dp);
pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
intel_de_write(dev_priv, pp_ctrl_reg, pp);
intel_de_posting_read(dev_priv, pp_ctrl_reg);
drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps),
intel_de_read(dev_priv, pp_stat_reg),
intel_de_read(dev_priv, pp_ctrl_reg));
/*
@ -621,9 +758,9 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
*/
if (!edp_have_panel_power(intel_dp)) {
drm_dbg_kms(&dev_priv->drm,
"[ENCODER:%d:%s] panel power wasn't enabled\n",
dig_port->base.base.base.id,
dig_port->base.base.name);
"[ENCODER:%d:%s] %s panel power wasn't enabled\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
msleep(intel_dp->pps.panel_power_up_delay);
}
@ -638,6 +775,7 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
*/
void intel_pps_vdd_on(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
intel_wakeref_t wakeref;
bool vdd;
@ -647,9 +785,10 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp)
vdd = false;
with_intel_pps_lock(intel_dp, wakeref)
vdd = intel_pps_vdd_on_unlocked(intel_dp);
I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] %s VDD already requested on\n",
dp_to_dig_port(intel_dp)->base.base.base.id,
dp_to_dig_port(intel_dp)->base.base.name);
dp_to_dig_port(intel_dp)->base.base.name,
pps_name(i915, &intel_dp->pps));
}
static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
@ -667,9 +806,9 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
if (!edp_have_panel_vdd(intel_dp))
return;
drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n",
dig_port->base.base.base.id,
dig_port->base.base.name);
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turning VDD off\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
pp = ilk_get_pp_control(intel_dp);
pp &= ~EDP_FORCE_VDD;
@ -681,7 +820,9 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
intel_de_posting_read(dev_priv, pp_ctrl_reg);
/* Make sure sequencer is idle before allowing subsequent activity */
drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps),
intel_de_read(dev_priv, pp_stat_reg),
intel_de_read(dev_priv, pp_ctrl_reg));
@ -756,9 +897,10 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
if (!intel_dp_is_edp(intel_dp))
return;
I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] %s VDD not forced on",
dp_to_dig_port(intel_dp)->base.base.base.id,
dp_to_dig_port(intel_dp)->base.base.name);
dp_to_dig_port(intel_dp)->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
intel_dp->pps.want_panel_vdd = false;
@ -779,14 +921,16 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp)
if (!intel_dp_is_edp(intel_dp))
return;
drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n",
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turn panel power on\n",
dp_to_dig_port(intel_dp)->base.base.base.id,
dp_to_dig_port(intel_dp)->base.base.name);
dp_to_dig_port(intel_dp)->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp),
"[ENCODER:%d:%s] panel power already on\n",
"[ENCODER:%d:%s] %s panel power already on\n",
dp_to_dig_port(intel_dp)->base.base.base.id,
dp_to_dig_port(intel_dp)->base.base.name))
dp_to_dig_port(intel_dp)->base.base.name,
pps_name(dev_priv, &intel_dp->pps)))
return;
wait_panel_power_cycle(intel_dp);
@ -840,12 +984,14 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
if (!intel_dp_is_edp(intel_dp))
return;
drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
dig_port->base.base.base.id, dig_port->base.base.name);
drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] %s turn panel power off\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
drm_WARN(&dev_priv->drm, !intel_dp->pps.want_panel_vdd,
"Need [ENCODER:%d:%s] VDD to turn off panel\n",
dig_port->base.base.base.id, dig_port->base.base.name);
"[ENCODER:%d:%s] %s need VDD to turn off panel\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
pp = ilk_get_pp_control(intel_dp);
/* We need to switch off panel power _and_ force vdd, for otherwise some
@ -980,9 +1126,9 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
* from a port.
*/
drm_dbg_kms(&dev_priv->drm,
"detaching pipe %c power sequencer from [ENCODER:%d:%s]\n",
pipe_name(pipe), dig_port->base.base.base.id,
dig_port->base.base.name);
"detaching %s from [ENCODER:%d:%s]\n",
pps_name(dev_priv, &intel_dp->pps),
dig_port->base.base.base.id, dig_port->base.base.name);
intel_de_write(dev_priv, pp_on_reg, 0);
intel_de_posting_read(dev_priv, pp_on_reg);
@ -1000,7 +1146,7 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
drm_WARN(&dev_priv->drm, intel_dp->pps.active_pipe == pipe,
"stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
"stealing PPS %c from active [ENCODER:%d:%s]\n",
pipe_name(pipe), encoder->base.base.id,
encoder->base.name);
@ -1008,7 +1154,7 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
continue;
drm_dbg_kms(&dev_priv->drm,
"stealing pipe %c power sequencer from [ENCODER:%d:%s]\n",
"stealing PPS %c from [ENCODER:%d:%s]\n",
pipe_name(pipe), encoder->base.base.id,
encoder->base.name);
@ -1053,9 +1199,9 @@ void vlv_pps_init(struct intel_encoder *encoder,
intel_dp->pps.pps_pipe = crtc->pipe;
drm_dbg_kms(&dev_priv->drm,
"initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
pipe_name(intel_dp->pps.pps_pipe), encoder->base.base.id,
encoder->base.name);
"initializing %s for [ENCODER:%d:%s]\n",
pps_name(dev_priv, &intel_dp->pps),
encoder->base.base.id, encoder->base.name);
/* init power sequencer on this pipe and port */
pps_init_delays(intel_dp);
@ -1079,7 +1225,9 @@ static void pps_vdd_init(struct intel_dp *intel_dp)
* indefinitely.
*/
drm_dbg_kms(&dev_priv->drm,
"VDD left on by BIOS, adjusting state tracking\n");
"[ENCODER:%d:%s] %s VDD left on by BIOS, adjusting state tracking\n",
dig_port->base.base.base.id, dig_port->base.base.name,
pps_name(dev_priv, &intel_dp->pps));
drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref);
intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv,
intel_aux_power_domain(dig_port));
@ -1432,10 +1580,10 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
}
}
void intel_pps_init(struct intel_dp *intel_dp)
bool intel_pps_init(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
intel_wakeref_t wakeref;
bool ret;
intel_dp->pps.initializing = true;
INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work, edp_panel_vdd_work);
@ -1443,13 +1591,36 @@ void intel_pps_init(struct intel_dp *intel_dp)
pps_init_timestamps(intel_dp);
with_intel_pps_lock(intel_dp, wakeref) {
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
vlv_initial_power_sequencer_setup(intel_dp);
ret = pps_initial_setup(intel_dp);
pps_init_delays(intel_dp);
pps_init_registers(intel_dp, false);
pps_vdd_init(intel_dp);
}
return ret;
}
static void pps_init_late(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct intel_connector *connector = intel_dp->attached_connector;
if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
return;
if (intel_num_pps(i915) < 2)
return;
drm_WARN(&i915->drm, connector->panel.vbt.backlight.controller >= 0 &&
intel_dp->pps.pps_idx != connector->panel.vbt.backlight.controller,
"[ENCODER:%d:%s] power sequencer mismatch: %d (initial) vs. %d (VBT)\n",
encoder->base.base.id, encoder->base.name,
intel_dp->pps.pps_idx, connector->panel.vbt.backlight.controller);
if (connector->panel.vbt.backlight.controller >= 0)
intel_dp->pps.pps_idx = connector->panel.vbt.backlight.controller;
}
void intel_pps_init_late(struct intel_dp *intel_dp)
@ -1458,6 +1629,8 @@ void intel_pps_init_late(struct intel_dp *intel_dp)
with_intel_pps_lock(intel_dp, wakeref) {
/* Reinit delays after per-panel info has been parsed from VBT */
pps_init_late(intel_dp);
memset(&intel_dp->pps.pps_delays, 0, sizeof(intel_dp->pps.pps_delays));
pps_init_delays(intel_dp);
pps_init_registers(intel_dp, false);
@ -1480,10 +1653,7 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
* This w/a is needed at least on CPT/PPT, but to be sure apply it
* everywhere where registers can be write protected.
*/
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
pps_num = 2;
else
pps_num = 1;
pps_num = intel_num_pps(dev_priv);
for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));

View File

@ -40,7 +40,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);
bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp);
void intel_pps_wait_power_cycle(struct intel_dp *intel_dp);
void intel_pps_init(struct intel_dp *intel_dp);
bool intel_pps_init(struct intel_dp *intel_dp);
void intel_pps_init_late(struct intel_dp *intel_dp);
void intel_pps_encoder_reset(struct intel_dp *intel_dp);
void intel_pps_reset_all(struct drm_i915_private *i915);

View File

@ -797,7 +797,7 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp,
return intel_dp->psr.su_y_granularity == 4;
/*
* adl_p and display 14+ platforms has 1 line granularity.
* adl_p and mtl platforms have 1 line granularity.
* For other platforms with SW tracking we can adjust the y coordinates
* to match sink requirement if multiple of 4.
*/
@ -1170,11 +1170,14 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
PSR2_ADD_VERTICAL_LINE_COUNT);
/*
* Wa_16014451276:adlp
* Wa_16014451276:adlp,mtl[a0,b0]
* All supported adlp panels have 1-based X granularity, this may
* cause issues if non-supported panels are used.
*/
if (IS_ALDERLAKE_P(dev_priv))
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(cpu_transcoder), 0,
ADLP_1_BASED_X_GRANULARITY);
else if (IS_ALDERLAKE_P(dev_priv))
intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), 0,
ADLP_1_BASED_X_GRANULARITY);
@ -1185,8 +1188,12 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
TRANS_SET_CONTEXT_LATENCY_MASK,
TRANS_SET_CONTEXT_LATENCY_VALUE(1));
/* Wa_16012604467:adlp */
if (IS_ALDERLAKE_P(dev_priv))
/* Wa_16012604467:adlp,mtl[a0,b0] */
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
intel_de_rmw(dev_priv,
MTL_CLKGATE_DIS_TRANS(cpu_transcoder), 0,
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS);
else if (IS_ALDERLAKE_P(dev_priv))
intel_de_rmw(dev_priv, CLKGATE_DIS_MISC, 0,
CLKGATE_DIS_MISC_DMASC_GATING_DIS);
@ -1362,8 +1369,12 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
TRANS_SET_CONTEXT_LATENCY(intel_dp->psr.transcoder),
TRANS_SET_CONTEXT_LATENCY_MASK, 0);
/* Wa_16012604467:adlp */
if (IS_ALDERLAKE_P(dev_priv))
/* Wa_16012604467:adlp,mtl[a0,b0] */
if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0))
intel_de_rmw(dev_priv,
MTL_CLKGATE_DIS_TRANS(intel_dp->psr.transcoder),
MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS, 0);
else if (IS_ALDERLAKE_P(dev_priv))
intel_de_rmw(dev_priv, CLKGATE_DIS_MISC,
CLKGATE_DIS_MISC_DMASC_GATING_DIS, 0);
@ -1510,7 +1521,8 @@ static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
man_trk_ctl_enable_bit_get(dev_priv) |
man_trk_ctl_partial_frame_bit_get(dev_priv) |
man_trk_ctl_single_full_frame_bit_get(dev_priv));
man_trk_ctl_single_full_frame_bit_get(dev_priv) |
man_trk_ctl_continuos_full_frame(dev_priv));
/*
* Display WA #0884: skl+
@ -1624,11 +1636,8 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
val |= man_trk_ctl_partial_frame_bit_get(dev_priv);
if (full_update) {
/*
* Not applying Wa_14014971508:adlp as we do not support the
* feature that requires this workaround.
*/
val |= man_trk_ctl_single_full_frame_bit_get(dev_priv);
val |= man_trk_ctl_continuos_full_frame(dev_priv);
goto exit;
}
@ -2307,12 +2316,15 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)
/* can we turn CFF off? */
if (intel_dp->psr.busy_frontbuffer_bits == 0) {
u32 val = man_trk_ctl_enable_bit_get(dev_priv) |
man_trk_ctl_partial_frame_bit_get(dev_priv) |
man_trk_ctl_single_full_frame_bit_get(dev_priv);
man_trk_ctl_partial_frame_bit_get(dev_priv) |
man_trk_ctl_single_full_frame_bit_get(dev_priv) |
man_trk_ctl_continuos_full_frame(dev_priv);
/*
* turn continuous full frame off and do a single
* full frame
* Set psr2_sel_fetch_cff_enabled as false to allow selective
* updates. Still keep cff bit enabled as we don't have proper
* SU configuration in case update is sent for any reason after
* sff bit gets cleared by the HW on next vblank.
*/
intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
val);

View File

@ -2886,7 +2886,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type)
if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
goto err;
intel_bios_init_panel(i915, &intel_connector->panel, NULL, NULL);
intel_bios_init_panel_late(i915, &intel_connector->panel, NULL, NULL);
/*
* Fetch modes from VBT. For SDVO prefer the VBT mode since some

View File

@ -44,18 +44,18 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915)
}
}
void intel_snps_phy_update_psr_power_state(struct drm_i915_private *dev_priv,
void intel_snps_phy_update_psr_power_state(struct drm_i915_private *i915,
enum phy phy, bool enable)
{
u32 val;
if (!intel_phy_is_snps(dev_priv, phy))
if (!intel_phy_is_snps(i915, phy))
return;
val = REG_FIELD_PREP(SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR,
enable ? 2 : 3);
intel_uncore_rmw(&dev_priv->uncore, SNPS_PHY_TX_REQ(phy),
SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val);
intel_de_rmw(i915, SNPS_PHY_TX_REQ(phy),
SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, val);
}
void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder,
@ -1785,7 +1785,7 @@ void intel_mpllb_enable(struct intel_encoder *encoder,
*/
/* 5. Software sets DPLL_ENABLE [PLL Enable] to "1". */
intel_uncore_rmw(&dev_priv->uncore, enable_reg, 0, PLL_ENABLE);
intel_de_rmw(dev_priv, enable_reg, 0, PLL_ENABLE);
/*
* 9. Software sets SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "1". This
@ -1830,14 +1830,13 @@ void intel_mpllb_disable(struct intel_encoder *encoder)
*/
/* 2. Software programs DPLL_ENABLE [PLL Enable] to "0" */
intel_uncore_rmw(&i915->uncore, enable_reg, PLL_ENABLE, 0);
intel_de_rmw(i915, enable_reg, PLL_ENABLE, 0);
/*
* 4. Software programs SNPS_PHY_MPLLB_DIV dp_mpllb_force_en to "0".
* This will allow the PLL to stop running.
*/
intel_uncore_rmw(&i915->uncore, SNPS_PHY_MPLLB_DIV(phy),
SNPS_PHY_MPLLB_FORCE_EN, 0);
intel_de_rmw(i915, SNPS_PHY_MPLLB_DIV(phy), SNPS_PHY_MPLLB_FORCE_EN, 0);
/*
* 5. Software polls DPLL_ENABLE [PLL Lock] for PHY acknowledgment

View File

@ -5,6 +5,7 @@
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_power_map.h"
#include "intel_display_types.h"
@ -120,11 +121,9 @@ assert_tc_cold_blocked(struct intel_digital_port *dig_port)
u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
u32 lane_mask;
lane_mask = intel_uncore_read(uncore,
PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff);
assert_tc_cold_blocked(dig_port);
@ -136,11 +135,9 @@ u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
u32 pin_mask;
pin_mask = intel_uncore_read(uncore,
PORT_TX_DFLEXPA1(dig_port->tc_phy_fia));
pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(dig_port->tc_phy_fia));
drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff);
assert_tc_cold_blocked(dig_port);
@ -186,7 +183,6 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
struct intel_uncore *uncore = &i915->uncore;
u32 val;
drm_WARN_ON(&i915->drm,
@ -194,8 +190,7 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
assert_tc_cold_blocked(dig_port);
val = intel_uncore_read(uncore,
PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia));
val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia));
val &= ~DFLEXDPMLE1_DPMLETC_MASK(dig_port->tc_phy_fia_idx);
switch (required_lanes) {
@ -216,8 +211,7 @@ void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
MISSING_CASE(required_lanes);
}
intel_uncore_write(uncore,
PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val);
intel_de_write(i915, PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val);
}
static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
@ -246,13 +240,11 @@ static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin];
u32 mask = 0;
u32 val;
val = intel_uncore_read(uncore,
PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
val = intel_de_read(i915, PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
if (val == 0xffffffff) {
drm_dbg_kms(&i915->drm,
@ -266,7 +258,7 @@ static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port)
if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx))
mask |= BIT(TC_PORT_DP_ALT);
if (intel_uncore_read(uncore, SDEISR) & isr_bit)
if (intel_de_read(i915, SDEISR) & isr_bit)
mask |= BIT(TC_PORT_LEGACY);
/* The sink can be connected only in a single mode. */
@ -281,7 +273,6 @@ static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port)
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin];
struct intel_uncore *uncore = &i915->uncore;
u32 val, mask = 0;
/*
@ -289,13 +280,13 @@ static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port)
* registers in IOM. Note that this doesn't apply to PHY and FIA
* registers.
*/
val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port));
val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port));
if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT)
mask |= BIT(TC_PORT_DP_ALT);
if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT)
mask |= BIT(TC_PORT_TBT_ALT);
if (intel_uncore_read(uncore, SDEISR) & isr_bit)
if (intel_de_read(i915, SDEISR) & isr_bit)
mask |= BIT(TC_PORT_LEGACY);
/* The sink can be connected only in a single mode. */
@ -326,11 +317,9 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
u32 val;
val = intel_uncore_read(uncore,
PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia));
val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia));
if (val == 0xffffffff) {
drm_dbg_kms(&i915->drm,
"Port %s: PHY in TCCOLD, assuming not complete\n",
@ -352,10 +341,9 @@ static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
struct intel_uncore *uncore = &i915->uncore;
u32 val;
val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port));
val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port));
if (val == 0xffffffff) {
drm_dbg_kms(&i915->drm,
"Port %s: PHY in TCCOLD, assuming not complete\n",
@ -380,11 +368,9 @@ static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port,
bool take)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
u32 val;
val = intel_uncore_read(uncore,
PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
if (val == 0xffffffff) {
drm_dbg_kms(&i915->drm,
"Port %s: PHY in TCCOLD, can't %s ownership\n",
@ -397,8 +383,7 @@ static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port,
if (take)
val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
intel_uncore_write(uncore,
PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val);
intel_de_write(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val);
return true;
}
@ -407,11 +392,10 @@ static bool adl_tc_phy_take_ownership(struct intel_digital_port *dig_port,
bool take)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
enum port port = dig_port->base.port;
intel_uncore_rmw(uncore, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP,
take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0);
intel_de_rmw(i915, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP,
take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0);
return true;
}
@ -429,11 +413,9 @@ static bool tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take
static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
u32 val;
val = intel_uncore_read(uncore,
PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
if (val == 0xffffffff) {
drm_dbg_kms(&i915->drm,
"Port %s: PHY in TCCOLD, assume safe mode\n",
@ -447,11 +429,10 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port)
static bool adl_tc_phy_is_owned(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
enum port port = dig_port->base.port;
u32 val;
val = intel_uncore_read(uncore, DDI_BUF_CTL(port));
val = intel_de_read(i915, DDI_BUF_CTL(port));
return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP;
}
@ -907,7 +888,7 @@ tc_has_modular_fia(struct drm_i915_private *i915, struct intel_digital_port *dig
mutex_lock(&dig_port->tc_lock);
wakeref = tc_cold_block(dig_port, &domain);
val = intel_uncore_read(&i915->uncore, PORT_TX_DFLEXDPSP(FIA1));
val = intel_de_read(i915, PORT_TX_DFLEXDPSP(FIA1));
tc_cold_unblock(dig_port, domain, wakeref);
mutex_unlock(&dig_port->tc_lock);

View File

@ -345,16 +345,13 @@ bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state)
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
if (!RUNTIME_INFO(i915)->has_dsc)
if (!HAS_DSC(i915))
return false;
if (DISPLAY_VER(i915) >= 12)
return true;
if (DISPLAY_VER(i915) == 11 && cpu_transcoder == TRANSCODER_A)
return false;
if (DISPLAY_VER(i915) >= 11 && cpu_transcoder != TRANSCODER_A)
return true;
return false;
return true;
}
static bool is_pipe_dsc(struct intel_crtc *crtc, enum transcoder cpu_transcoder)

View File

@ -78,10 +78,10 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *i915 = to_i915(crtc->base.dev);
/* The hw imposes the extra scanline before frame start */
if (DISPLAY_VER(i915) >= 13)
return crtc_state->vrr.guardband + crtc_state->framestart_delay + 1;
return crtc_state->vrr.guardband;
else
/* The hw imposes the extra scanline before frame start */
return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1;
}
@ -151,50 +151,46 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
* number of scan lines. Assuming 0 for no DSB.
*/
crtc_state->vrr.guardband =
crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay;
crtc_state->vrr.vmin + 1 - adjusted_mode->crtc_vdisplay;
} else {
/*
* FIXME: s/4/framestart_delay/ to get consistent
* earliest/latest points for register latching regardless
* of the framestart_delay used?
*
* FIXME: this really needs the extra scanline to provide consistent
* behaviour for all framestart_delay values. Otherwise with
* framestart_delay==4 we will end up extending the min vblank by
* one extra line.
*/
crtc_state->vrr.pipeline_full =
min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay - 4 - 1);
min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay -
crtc_state->framestart_delay - 1);
}
crtc_state->mode_flags |= I915_MODE_FLAG_VRR;
}
static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
if (DISPLAY_VER(i915) >= 13)
return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband);
else
return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) |
VRR_CTL_PIPELINE_FULL_OVERRIDE;
}
void intel_vrr_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
u32 trans_vrr_ctl;
if (!crtc_state->vrr.enable)
return;
if (DISPLAY_VER(dev_priv) >= 13)
trans_vrr_ctl = VRR_CTL_VRR_ENABLE |
VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband);
else
trans_vrr_ctl = VRR_CTL_VRR_ENABLE |
VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN |
VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) |
VRR_CTL_PIPELINE_FULL_OVERRIDE;
intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1);
intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl(crtc_state));
intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder), crtc_state->vrr.flipline - 1);
intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder),
VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state));
}
void intel_vrr_send_push(const struct intel_crtc_state *crtc_state)
@ -231,8 +227,13 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state)
if (!old_crtc_state->vrr.enable)
return;
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder),
trans_vrr_ctl(old_crtc_state));
intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder),
VRR_STATUS_VRR_EN_LIVE, 1000);
intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0);
intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0);
}
void intel_vrr_get_config(struct intel_crtc *crtc,

View File

@ -87,6 +87,10 @@ static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
#define ICL_MAX_SRC_H 4096
#define ICL_MAX_DST_W 5120
#define ICL_MAX_DST_H 4096
#define MTL_MAX_SRC_W 4096
#define MTL_MAX_SRC_H 8192
#define MTL_MAX_DST_W 8192
#define MTL_MAX_DST_H 8192
#define SKL_MIN_YUV_420_SRC_W 16
#define SKL_MIN_YUV_420_SRC_H 16
@ -103,6 +107,8 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int min_src_w, min_src_h, min_dst_w, min_dst_h;
int max_src_w, max_src_h, max_dst_w, max_dst_h;
/*
* Src coordinates are already rotated by 270 degrees for
@ -157,15 +163,33 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
return -EINVAL;
}
min_src_w = SKL_MIN_SRC_W;
min_src_h = SKL_MIN_SRC_H;
min_dst_w = SKL_MIN_DST_W;
min_dst_h = SKL_MIN_DST_H;
if (DISPLAY_VER(dev_priv) < 11) {
max_src_w = SKL_MAX_SRC_W;
max_src_h = SKL_MAX_SRC_H;
max_dst_w = SKL_MAX_DST_W;
max_dst_h = SKL_MAX_DST_H;
} else if (DISPLAY_VER(dev_priv) < 14) {
max_src_w = ICL_MAX_SRC_W;
max_src_h = ICL_MAX_SRC_H;
max_dst_w = ICL_MAX_DST_W;
max_dst_h = ICL_MAX_DST_H;
} else {
max_src_w = MTL_MAX_SRC_W;
max_src_h = MTL_MAX_SRC_H;
max_dst_w = MTL_MAX_DST_W;
max_dst_h = MTL_MAX_DST_H;
}
/* range checks */
if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H ||
dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H ||
(DISPLAY_VER(dev_priv) >= 11 &&
(src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H ||
dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) ||
(DISPLAY_VER(dev_priv) < 11 &&
(src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H ||
dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) {
if (src_w < min_src_w || src_h < min_src_h ||
dst_w < min_dst_w || dst_h < min_dst_h ||
src_w > max_src_w || src_h > max_src_h ||
dst_w > max_dst_w || dst_h > max_dst_h) {
drm_dbg_kms(&dev_priv->drm,
"scaler_user index %u.%u: src %ux%u dst %ux%u "
"size is out of scaler range\n",

View File

@ -45,8 +45,7 @@ u8 intel_enabled_dbuf_slices_mask(struct drm_i915_private *i915)
enum dbuf_slice slice;
for_each_dbuf_slice(i915, slice) {
if (intel_uncore_read(&i915->uncore,
DBUF_CTL_S(slice)) & DBUF_POWER_STATE)
if (intel_de_read(i915, DBUF_CTL_S(slice)) & DBUF_POWER_STATE)
enabled_slices |= BIT(slice);
}
@ -75,7 +74,7 @@ intel_sagv_block_time(struct drm_i915_private *i915)
if (DISPLAY_VER(i915) >= 14) {
u32 val;
val = intel_uncore_read(&i915->uncore, MTL_LATENCY_SAGV);
val = intel_de_read(i915, MTL_LATENCY_SAGV);
return REG_FIELD_GET(MTL_LATENCY_QCLK_SAGV, val);
} else if (DISPLAY_VER(i915) >= 12) {
@ -756,18 +755,18 @@ skl_ddb_get_hw_plane_state(struct drm_i915_private *i915,
/* Cursor doesn't support NV12/planar, so no extra calculation needed */
if (plane_id == PLANE_CURSOR) {
val = intel_uncore_read(&i915->uncore, CUR_BUF_CFG(pipe));
val = intel_de_read(i915, CUR_BUF_CFG(pipe));
skl_ddb_entry_init_from_hw(ddb, val);
return;
}
val = intel_uncore_read(&i915->uncore, PLANE_BUF_CFG(pipe, plane_id));
val = intel_de_read(i915, PLANE_BUF_CFG(pipe, plane_id));
skl_ddb_entry_init_from_hw(ddb, val);
if (DISPLAY_VER(i915) >= 11)
return;
val = intel_uncore_read(&i915->uncore, PLANE_NV12_BUF_CFG(pipe, plane_id));
val = intel_de_read(i915, PLANE_NV12_BUF_CFG(pipe, plane_id));
skl_ddb_entry_init_from_hw(ddb_y, val);
}
@ -2821,36 +2820,32 @@ static void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
for (level = 0; level <= max_level; level++) {
if (plane_id != PLANE_CURSOR)
val = intel_uncore_read(&i915->uncore, PLANE_WM(pipe, plane_id, level));
val = intel_de_read(i915, PLANE_WM(pipe, plane_id, level));
else
val = intel_uncore_read(&i915->uncore, CUR_WM(pipe, level));
val = intel_de_read(i915, CUR_WM(pipe, level));
skl_wm_level_from_reg_val(val, &wm->wm[level]);
}
if (plane_id != PLANE_CURSOR)
val = intel_uncore_read(&i915->uncore, PLANE_WM_TRANS(pipe, plane_id));
val = intel_de_read(i915, PLANE_WM_TRANS(pipe, plane_id));
else
val = intel_uncore_read(&i915->uncore, CUR_WM_TRANS(pipe));
val = intel_de_read(i915, CUR_WM_TRANS(pipe));
skl_wm_level_from_reg_val(val, &wm->trans_wm);
if (HAS_HW_SAGV_WM(i915)) {
if (plane_id != PLANE_CURSOR)
val = intel_uncore_read(&i915->uncore,
PLANE_WM_SAGV(pipe, plane_id));
val = intel_de_read(i915, PLANE_WM_SAGV(pipe, plane_id));
else
val = intel_uncore_read(&i915->uncore,
CUR_WM_SAGV(pipe));
val = intel_de_read(i915, CUR_WM_SAGV(pipe));
skl_wm_level_from_reg_val(val, &wm->sagv.wm0);
if (plane_id != PLANE_CURSOR)
val = intel_uncore_read(&i915->uncore,
PLANE_WM_SAGV_TRANS(pipe, plane_id));
val = intel_de_read(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id));
else
val = intel_uncore_read(&i915->uncore,
CUR_WM_SAGV_TRANS(pipe));
val = intel_de_read(i915, CUR_WM_SAGV_TRANS(pipe));
skl_wm_level_from_reg_val(val, &wm->sagv.trans_wm);
} else if (DISPLAY_VER(i915) >= 12) {
@ -3126,8 +3121,8 @@ void skl_watermark_ipc_update(struct drm_i915_private *i915)
if (!HAS_IPC(i915))
return;
intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL2, DISP_IPC_ENABLE,
skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0);
intel_de_rmw(i915, DISP_ARB_CTL2, DISP_IPC_ENABLE,
skl_watermark_ipc_enabled(i915) ? DISP_IPC_ENABLE : 0);
}
static bool skl_watermark_ipc_can_enable(struct drm_i915_private *i915)
@ -3201,19 +3196,18 @@ adjust_wm_latency(struct drm_i915_private *i915,
static void mtl_read_wm_latency(struct drm_i915_private *i915, u16 wm[])
{
struct intel_uncore *uncore = &i915->uncore;
int max_level = ilk_wm_max_level(i915);
u32 val;
val = intel_uncore_read(uncore, MTL_LATENCY_LP0_LP1);
val = intel_de_read(i915, MTL_LATENCY_LP0_LP1);
wm[0] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val);
wm[1] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val);
val = intel_uncore_read(uncore, MTL_LATENCY_LP2_LP3);
val = intel_de_read(i915, MTL_LATENCY_LP2_LP3);
wm[2] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val);
wm[3] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val);
val = intel_uncore_read(uncore, MTL_LATENCY_LP4_LP5);
val = intel_de_read(i915, MTL_LATENCY_LP4_LP5);
wm[4] = REG_FIELD_GET(MTL_LATENCY_LEVEL_EVEN_MASK, val);
wm[5] = REG_FIELD_GET(MTL_LATENCY_LEVEL_ODD_MASK, val);

View File

@ -1916,7 +1916,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
intel_dsi->panel_power_off_time = ktime_get_boottime();
intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL);
intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL);
if (intel_connector->panel.vbt.dsi.config->dual_link)
intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C);

View File

@ -75,6 +75,8 @@
#include "pxp/intel_pxp_pm.h"
#include "soc/intel_dram.h"
#include "i915_file_private.h"
#include "i915_debugfs.h"
#include "i915_driver.h"
@ -93,7 +95,6 @@
#include "i915_sysfs.h"
#include "i915_utils.h"
#include "i915_vgpu.h"
#include "intel_dram.h"
#include "intel_gvt.h"
#include "intel_memory_region.h"
#include "intel_pci_config.h"

View File

@ -49,6 +49,8 @@
#include "gt/intel_workarounds.h"
#include "gt/uc/intel_uc.h"
#include "soc/intel_pch.h"
#include "i915_drm_client.h"
#include "i915_gem.h"
#include "i915_gpu_error.h"
@ -58,7 +60,6 @@
#include "i915_utils.h"
#include "intel_device_info.h"
#include "intel_memory_region.h"
#include "intel_pch.h"
#include "intel_runtime_pm.h"
#include "intel_step.h"
#include "intel_uncore.h"
@ -466,6 +467,7 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915)
#define INTEL_REVID(dev_priv) (to_pci_dev((dev_priv)->drm.dev)->revision)
#define HAS_DSB(dev_priv) (INTEL_INFO(dev_priv)->display.has_dsb)
#define HAS_DSC(__i915) (RUNTIME_INFO(__i915)->has_dsc)
#define INTEL_DISPLAY_STEP(__i915) (RUNTIME_INFO(__i915)->step.display_step)
#define INTEL_GRAPHICS_STEP(__i915) (RUNTIME_INFO(__i915)->step.graphics_step)
@ -726,6 +728,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
(IS_SUBPLATFORM(__i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_##variant) && \
IS_GRAPHICS_STEP(__i915, since, until))
#define IS_MTL_DISPLAY_STEP(__i915, since, until) \
(IS_METEORLAKE(__i915) && \
IS_DISPLAY_STEP(__i915, since, until))
/*
* DG2 hardware steppings are a bit unusual. The hardware design was forked to
* create three variants (G10, G11, and G12) which each have distinct

View File

@ -2451,8 +2451,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
ret = IRQ_HANDLED;
gen8_de_misc_irq_handler(dev_priv, iir);
} else {
drm_err(&dev_priv->drm,
"The master control interrupt lied (DE MISC)!\n");
drm_err_ratelimited(&dev_priv->drm,
"The master control interrupt lied (DE MISC)!\n");
}
}
@ -2463,8 +2463,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
ret = IRQ_HANDLED;
gen11_hpd_irq_handler(dev_priv, iir);
} else {
drm_err(&dev_priv->drm,
"The master control interrupt lied, (DE HPD)!\n");
drm_err_ratelimited(&dev_priv->drm,
"The master control interrupt lied, (DE HPD)!\n");
}
}
@ -2513,12 +2513,12 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
}
if (!found)
drm_err(&dev_priv->drm,
"Unexpected DE Port interrupt\n");
drm_err_ratelimited(&dev_priv->drm,
"Unexpected DE Port interrupt\n");
}
else
drm_err(&dev_priv->drm,
"The master control interrupt lied (DE PORT)!\n");
drm_err_ratelimited(&dev_priv->drm,
"The master control interrupt lied (DE PORT)!\n");
}
for_each_pipe(dev_priv, pipe) {
@ -2529,8 +2529,8 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
iir = intel_uncore_read(&dev_priv->uncore, GEN8_DE_PIPE_IIR(pipe));
if (!iir) {
drm_err(&dev_priv->drm,
"The master control interrupt lied (DE PIPE)!\n");
drm_err_ratelimited(&dev_priv->drm,
"The master control interrupt lied (DE PIPE)!\n");
continue;
}
@ -2551,10 +2551,10 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
fault_errors = iir & gen8_de_pipe_fault_mask(dev_priv);
if (fault_errors)
drm_err(&dev_priv->drm,
"Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
fault_errors);
drm_err_ratelimited(&dev_priv->drm,
"Fault errors on pipe %c: 0x%08x\n",
pipe_name(pipe),
fault_errors);
}
if (HAS_PCH_SPLIT(dev_priv) && !HAS_PCH_NOP(dev_priv) &&

View File

@ -122,7 +122,7 @@ i915_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400,
"Default: 0");
i915_param_named_unsafe(force_probe, charp, 0400,
"Force probe the driver for specified devices. "
"Force probe options for specified supported devices. "
"See CONFIG_DRM_I915_FORCE_PROBE for details.");
i915_param_named_unsafe(disable_power_well, int, 0400,

View File

@ -132,9 +132,9 @@
[PIPE_D] = TGL_CURSOR_D_OFFSET, \
}
#define I9XX_COLORS \
#define I845_COLORS \
.display.color = { .gamma_lut_size = 256 }
#define I965_COLORS \
#define I9XX_COLORS \
.display.color = { .gamma_lut_size = 129, \
.gamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING, \
}
@ -210,7 +210,7 @@
.dma_mask_size = 32, \
I845_PIPE_OFFSETS, \
I845_CURSOR_OFFSETS, \
I9XX_COLORS, \
I845_COLORS, \
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
@ -341,7 +341,7 @@ static const struct intel_device_info pnv_m_info = {
.dma_mask_size = 36, \
I9XX_PIPE_OFFSETS, \
I9XX_CURSOR_OFFSETS, \
I965_COLORS, \
I9XX_COLORS, \
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
@ -547,7 +547,7 @@ static const struct intel_device_info vlv_info = {
.display.mmio_offset = VLV_DISPLAY_BASE,
I9XX_PIPE_OFFSETS,
I9XX_CURSOR_OFFSETS,
I965_COLORS,
I9XX_COLORS,
GEN_DEFAULT_PAGE_SIZES,
GEN_DEFAULT_REGIONS,
};
@ -889,7 +889,7 @@ static const struct intel_device_info jsl_info = {
TGL_CURSOR_OFFSETS, \
.has_global_mocs = 1, \
.has_pxp = 1, \
.display.has_dsb = 0 /* FIXME: LUT load is broken with DSB */
.display.has_dsb = 1
static const struct intel_device_info tgl_info = {
GEN12_FEATURES,
@ -948,7 +948,7 @@ static const struct intel_device_info adl_s_info = {
#define XE_LPD_FEATURES \
.display.abox_mask = GENMASK(1, 0), \
.display.color = { \
.degamma_lut_size = 128, .gamma_lut_size = 1024, \
.degamma_lut_size = 129, .gamma_lut_size = 1024, \
.degamma_lut_tests = DRM_COLOR_LUT_NON_DECREASING | \
DRM_COLOR_LUT_EQUAL_CHANNELS, \
}, \
@ -1017,6 +1017,7 @@ static const struct intel_device_info adl_p_info = {
.has_3d_pipeline = 1, \
.has_64bit_reloc = 1, \
.has_flat_ccs = 1, \
.has_4tile = 1, \
.has_global_mocs = 1, \
.has_gt_uc = 1, \
.has_llc = 1, \
@ -1061,7 +1062,6 @@ static const struct intel_device_info xehpsdv_info = {
.__runtime.graphics.ip.rel = 55, \
.__runtime.media.ip.rel = 55, \
PLATFORM(INTEL_DG2), \
.has_4tile = 1, \
.has_64k_pages = 1, \
.has_guc_deprivilege = 1, \
.has_heci_pxp = 1, \
@ -1117,6 +1117,7 @@ static const struct intel_device_info pvc_info = {
XE_LPD_FEATURES, \
.__runtime.display.ip.ver = 14, \
.display.has_cdclk_crawl = 1, \
.display.has_cdclk_squash = 1, \
.__runtime.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B)
static const struct intel_gt_definition xelpmp_extra_gt[] = {
@ -1252,7 +1253,7 @@ static void i915_pci_remove(struct pci_dev *pdev)
}
/* is device_id present in comma separated list of ids */
static bool force_probe(u16 device_id, const char *devices)
static bool device_id_in_list(u16 device_id, const char *devices, bool negative)
{
char *s, *p, *tok;
bool ret;
@ -1261,7 +1262,9 @@ static bool force_probe(u16 device_id, const char *devices)
return false;
/* match everything */
if (strcmp(devices, "*") == 0)
if (negative && strcmp(devices, "!*") == 0)
return true;
if (!negative && strcmp(devices, "*") == 0)
return true;
s = kstrdup(devices, GFP_KERNEL);
@ -1271,6 +1274,12 @@ static bool force_probe(u16 device_id, const char *devices)
for (p = s, ret = false; (tok = strsep(&p, ",")) != NULL; ) {
u16 val;
if (negative && tok[0] == '!')
tok++;
else if ((negative && tok[0] != '!') ||
(!negative && tok[0] == '!'))
continue;
if (kstrtou16(tok, 16, &val) == 0 && val == device_id) {
ret = true;
break;
@ -1282,6 +1291,16 @@ static bool force_probe(u16 device_id, const char *devices)
return ret;
}
static bool id_forced(u16 device_id)
{
return device_id_in_list(device_id, i915_modparams.force_probe, false);
}
static bool id_blocked(u16 device_id)
{
return device_id_in_list(device_id, i915_modparams.force_probe, true);
}
bool i915_pci_resource_valid(struct pci_dev *pdev, int bar)
{
if (!pci_resource_flags(pdev, bar))
@ -1307,10 +1326,9 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
(struct intel_device_info *) ent->driver_data;
int err;
if (intel_info->require_force_probe &&
!force_probe(pdev->device, i915_modparams.force_probe)) {
if (intel_info->require_force_probe && !id_forced(pdev->device)) {
dev_info(&pdev->dev,
"Your graphics device %04x is not properly supported by the driver in this\n"
"Your graphics device %04x is not properly supported by i915 in this\n"
"kernel version. To force driver probe anyway, use i915.force_probe=%04x\n"
"module parameter or CONFIG_DRM_I915_FORCE_PROBE=%04x configuration option,\n"
"or (recommended) check for kernel updates.\n",
@ -1318,6 +1336,12 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}
if (id_blocked(pdev->device)) {
dev_info(&pdev->dev, "I915 probe blocked for Device ID %04x.\n",
pdev->device);
return -ENODEV;
}
/* Only bind to function 0 of the device. Early generations
* used function 1 as a placeholder for multi-head. This causes
* us confusion instead, especially on the systems where both

View File

@ -1713,6 +1713,20 @@
#define PALETTE_RED_MASK REG_GENMASK(23, 16)
#define PALETTE_GREEN_MASK REG_GENMASK(15, 8)
#define PALETTE_BLUE_MASK REG_GENMASK(7, 0)
/* pre-i965 10bit interpolated mode ldw */
#define PALETTE_10BIT_RED_LDW_MASK REG_GENMASK(23, 16)
#define PALETTE_10BIT_GREEN_LDW_MASK REG_GENMASK(15, 8)
#define PALETTE_10BIT_BLUE_LDW_MASK REG_GENMASK(7, 0)
/* pre-i965 10bit interpolated mode udw */
#define PALETTE_10BIT_RED_EXP_MASK REG_GENMASK(23, 22)
#define PALETTE_10BIT_RED_MANT_MASK REG_GENMASK(21, 18)
#define PALETTE_10BIT_RED_UDW_MASK REG_GENMASK(17, 16)
#define PALETTE_10BIT_GREEN_EXP_MASK REG_GENMASK(15, 14)
#define PALETTE_10BIT_GREEN_MANT_MASK REG_GENMASK(13, 10)
#define PALETTE_10BIT_GREEN_UDW_MASK REG_GENMASK(9, 8)
#define PALETTE_10BIT_BLUE_EXP_MASK REG_GENMASK(7, 6)
#define PALETTE_10BIT_BLUE_MANT_MASK REG_GENMASK(5, 2)
#define PALETTE_10BIT_BLUE_UDW_MASK REG_GENMASK(1, 0)
#define PALETTE(pipe, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + \
_PICK((pipe), _PALETTE_A, \
_PALETTE_B, _CHV_PALETTE_C) + \
@ -2575,46 +2589,6 @@
#define SDVO_PIPE_SEL_MASK_CHV (3 << 24)
#define SDVO_PIPE_SEL_CHV(pipe) ((pipe) << 24)
/* DVO port control */
#define _DVOA 0x61120
#define DVOA _MMIO(_DVOA)
#define _DVOB 0x61140
#define DVOB _MMIO(_DVOB)
#define _DVOC 0x61160
#define DVOC _MMIO(_DVOC)
#define DVO_ENABLE (1 << 31)
#define DVO_PIPE_SEL_SHIFT 30
#define DVO_PIPE_SEL_MASK (1 << 30)
#define DVO_PIPE_SEL(pipe) ((pipe) << 30)
#define DVO_PIPE_STALL_UNUSED (0 << 28)
#define DVO_PIPE_STALL (1 << 28)
#define DVO_PIPE_STALL_TV (2 << 28)
#define DVO_PIPE_STALL_MASK (3 << 28)
#define DVO_USE_VGA_SYNC (1 << 15)
#define DVO_DATA_ORDER_I740 (0 << 14)
#define DVO_DATA_ORDER_FP (1 << 14)
#define DVO_VSYNC_DISABLE (1 << 11)
#define DVO_HSYNC_DISABLE (1 << 10)
#define DVO_VSYNC_TRISTATE (1 << 9)
#define DVO_HSYNC_TRISTATE (1 << 8)
#define DVO_BORDER_ENABLE (1 << 7)
#define DVO_DATA_ORDER_GBRG (1 << 6)
#define DVO_DATA_ORDER_RGGB (0 << 6)
#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6)
#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6)
#define DVO_VSYNC_ACTIVE_HIGH (1 << 4)
#define DVO_HSYNC_ACTIVE_HIGH (1 << 3)
#define DVO_BLANK_ACTIVE_HIGH (1 << 2)
#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */
#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */
#define DVO_PRESERVE_MASK (0x7 << 24)
#define DVOA_SRCDIM _MMIO(0x61124)
#define DVOB_SRCDIM _MMIO(0x61144)
#define DVOC_SRCDIM _MMIO(0x61164)
#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
#define DVO_SRCDIM_VERTICAL_SHIFT 0
/* LVDS port control */
#define LVDS _MMIO(0x61180)
/*
@ -3646,7 +3620,7 @@
#define _PIPEAGCMAX 0x70010
#define _PIPEBGCMAX 0x71010
#define PIPEGCMAX(pipe, i) _MMIO_PIPE2(pipe, _PIPEAGCMAX + (i) * 4)
#define PIPEGCMAX(pipe, i) _MMIO_PIPE2(pipe, _PIPEAGCMAX + (i) * 4) /* u1.16 */
#define _PIPE_ARB_CTL_A 0x70028 /* icl+ */
#define PIPE_ARB_CTL(pipe) _MMIO_PIPE2(pipe, _PIPE_ARB_CTL_A)
@ -5330,19 +5304,20 @@
#define _PREC_PIPEAGCMAX 0x4d000
#define _PREC_PIPEBGCMAX 0x4d010
#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4)
#define PREC_PIPEGCMAX(pipe, i) _MMIO(_PIPE(pipe, _PIPEAGCMAX, _PIPEBGCMAX) + (i) * 4) /* u1.16 */
#define _GAMMA_MODE_A 0x4a480
#define _GAMMA_MODE_B 0x4ac80
#define GAMMA_MODE(pipe) _MMIO_PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
#define PRE_CSC_GAMMA_ENABLE (1 << 31)
#define POST_CSC_GAMMA_ENABLE (1 << 30)
#define GAMMA_MODE_MODE_MASK (3 << 0)
#define GAMMA_MODE_MODE_8BIT (0 << 0)
#define GAMMA_MODE_MODE_10BIT (1 << 0)
#define GAMMA_MODE_MODE_12BIT (2 << 0)
#define GAMMA_MODE_MODE_SPLIT (3 << 0) /* ivb-bdw */
#define GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED (3 << 0) /* icl + */
#define PRE_CSC_GAMMA_ENABLE REG_BIT(31) /* icl+ */
#define POST_CSC_GAMMA_ENABLE REG_BIT(30) /* icl+ */
#define PALETTE_ANTICOL_DISABLE REG_BIT(15) /* skl+ */
#define GAMMA_MODE_MODE_MASK REG_GENMASK(1, 0)
#define GAMMA_MODE_MODE_8BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 0)
#define GAMMA_MODE_MODE_10BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 1)
#define GAMMA_MODE_MODE_12BIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 2)
#define GAMMA_MODE_MODE_SPLIT REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* ivb-bdw */
#define GAMMA_MODE_MODE_12BIT_MULTI_SEG REG_FIELD_PREP(GAMMA_MODE_MODE_MASK, 3) /* icl-tgl */
/* Display Internal Timeout Register */
#define RM_TIMEOUT _MMIO(0x42060)
@ -6269,6 +6244,7 @@
#define CHASSIS_CLK_REQ_DURATION_MASK (0xf << 8)
#define CHASSIS_CLK_REQ_DURATION(x) ((x) << 8)
#define SBCLK_RUN_REFCLK_DIS (1 << 7)
#define ICP_SECOND_PPS_IO_SELECT REG_BIT(2)
#define SPT_PWM_GRANULARITY (1 << 0)
#define SOUTH_CHICKEN2 _MMIO(0xc2004)
#define FDI_MPHY_IOSFSB_RESET_STATUS (1 << 13)
@ -7557,11 +7533,10 @@ enum skl_power_gate {
#define _PAL_PREC_INDEX_A 0x4A400
#define _PAL_PREC_INDEX_B 0x4AC00
#define _PAL_PREC_INDEX_C 0x4B400
#define PAL_PREC_10_12_BIT (0 << 31)
#define PAL_PREC_SPLIT_MODE (1 << 31)
#define PAL_PREC_AUTO_INCREMENT (1 << 15)
#define PAL_PREC_INDEX_VALUE_MASK (0x3ff << 0)
#define PAL_PREC_INDEX_VALUE(x) ((x) << 0)
#define PAL_PREC_SPLIT_MODE REG_BIT(31)
#define PAL_PREC_AUTO_INCREMENT REG_BIT(15)
#define PAL_PREC_INDEX_VALUE_MASK REG_GENMASK(9, 0)
#define PAL_PREC_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_INDEX_VALUE_MASK, (x))
#define _PAL_PREC_DATA_A 0x4A404
#define _PAL_PREC_DATA_B 0x4AC04
#define _PAL_PREC_DATA_C 0x4B404
@ -7578,14 +7553,16 @@ enum skl_power_gate {
#define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B)
#define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B)
#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4)
#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4)
#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4)
#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) /* u1.16 */
#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) /* u3.16 */
#define PREC_PAL_EXT2_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT2_GC_MAX_A, _PAL_PREC_EXT2_GC_MAX_B) + (i) * 4) /* glk+, u3.16 */
#define _PRE_CSC_GAMC_INDEX_A 0x4A484
#define _PRE_CSC_GAMC_INDEX_B 0x4AC84
#define _PRE_CSC_GAMC_INDEX_C 0x4B484
#define PRE_CSC_GAMC_AUTO_INCREMENT (1 << 10)
#define PRE_CSC_GAMC_AUTO_INCREMENT REG_BIT(10)
#define PRE_CSC_GAMC_INDEX_VALUE_MASK REG_GENMASK(7, 0)
#define PRE_CSC_GAMC_INDEX_VALUE(x) REG_FIELD_PREP(PRE_CSC_GAMC_INDEX_VALUE_MASK, (x))
#define _PRE_CSC_GAMC_DATA_A 0x4A488
#define _PRE_CSC_GAMC_DATA_B 0x4AC88
#define _PRE_CSC_GAMC_DATA_C 0x4B488
@ -7596,8 +7573,9 @@ enum skl_power_gate {
/* ICL Multi segmented gamma */
#define _PAL_PREC_MULTI_SEG_INDEX_A 0x4A408
#define _PAL_PREC_MULTI_SEG_INDEX_B 0x4AC08
#define PAL_PREC_MULTI_SEGMENT_AUTO_INCREMENT REG_BIT(15)
#define PAL_PREC_MULTI_SEGMENT_INDEX_VALUE_MASK REG_GENMASK(4, 0)
#define PAL_PREC_MULTI_SEG_AUTO_INCREMENT REG_BIT(15)
#define PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK REG_GENMASK(4, 0)
#define PAL_PREC_MULTI_SEG_INDEX_VALUE(x) REG_FIELD_PREP(PAL_PREC_MULTI_SEG_INDEX_VALUE_MASK, (x))
#define _PAL_PREC_MULTI_SEG_DATA_A 0x4A40C
#define _PAL_PREC_MULTI_SEG_DATA_B 0x4AC0C

View File

@ -68,11 +68,12 @@ void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags);
* @wf: the wakeref
*
* Acquire a hold on the wakeref. The first user to do so, will acquire
* the runtime pm wakeref and then call the @fn underneath the wakeref
* mutex.
* the runtime pm wakeref and then call the intel_wakeref_ops->get()
* underneath the wakeref mutex.
*
* Note that @fn is allowed to fail, in which case the runtime-pm wakeref
* will be released and the acquisition unwound, and an error reported.
* Note that intel_wakeref_ops->get() is allowed to fail, in which case
* the runtime-pm wakeref will be released and the acquisition unwound,
* and an error reported.
*
* Returns: 0 if the wakeref was acquired successfully, or a negative error
* code otherwise.
@ -130,19 +131,17 @@ intel_wakeref_might_get(struct intel_wakeref *wf)
}
/**
* intel_wakeref_put_flags: Release the wakeref
* __intel_wakeref_put: Release the wakeref
* @wf: the wakeref
* @flags: control flags
*
* Release our hold on the wakeref. When there are no more users,
* the runtime pm wakeref will be released after the @fn callback is called
* underneath the wakeref mutex.
* the runtime pm wakeref will be released after the intel_wakeref_ops->put()
* callback is called underneath the wakeref mutex.
*
* Note that @fn is allowed to fail, in which case the runtime-pm wakeref
* is retained and an error reported.
* Note that intel_wakeref_ops->put() is allowed to fail, in which case the
* runtime-pm wakeref is retained.
*
* Returns: 0 if the wakeref was released successfully, or a negative error
* code otherwise.
*/
static inline void
__intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags)

View File

@ -240,6 +240,8 @@
#define DP_DSC_SUPPORT 0x060 /* DP 1.4 */
# define DP_DSC_DECOMPRESSION_IS_SUPPORTED (1 << 0)
# define DP_DSC_PASSTHROUGH_IS_SUPPORTED (1 << 1)
# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_COMP_TO_COMP (1 << 2)
# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_UNCOMP_TO_COMP (1 << 3)
#define DP_DSC_REV 0x061
# define DP_DSC_MAJOR_MASK (0xf << 0)
@ -278,12 +280,15 @@
#define DP_DSC_BLK_PREDICTION_SUPPORT 0x066
# define DP_DSC_BLK_PREDICTION_IS_SUPPORTED (1 << 0)
# define DP_DSC_RGB_COLOR_CONV_BYPASS_SUPPORT (1 << 1)
#define DP_DSC_MAX_BITS_PER_PIXEL_LOW 0x067 /* eDP 1.4 */
#define DP_DSC_MAX_BITS_PER_PIXEL_HI 0x068 /* eDP 1.4 */
# define DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK (0x3 << 0)
# define DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT 8
# define DP_DSC_MAX_BPP_DELTA_VERSION_MASK 0x06
# define DP_DSC_MAX_BPP_DELTA_AVAILABILITY 0x08
#define DP_DSC_DEC_COLOR_FORMAT_CAP 0x069
# define DP_DSC_RGB (1 << 0)
@ -345,11 +350,13 @@
# define DP_DSC_24_PER_DP_DSC_SINK (1 << 2)
#define DP_DSC_BITS_PER_PIXEL_INC 0x06F
# define DP_DSC_RGB_YCbCr444_MAX_BPP_DELTA_MASK 0x1f
# define DP_DSC_RGB_YCbCr420_MAX_BPP_DELTA_MASK 0xe0
# define DP_DSC_BITS_PER_PIXEL_1_16 0x0
# define DP_DSC_BITS_PER_PIXEL_1_8 0x1
# define DP_DSC_BITS_PER_PIXEL_1_4 0x2
# define DP_DSC_BITS_PER_PIXEL_1_2 0x3
# define DP_DSC_BITS_PER_PIXEL_1 0x4
# define DP_DSC_BITS_PER_PIXEL_1_1 0x4
#define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */
# define DP_PSR_IS_SUPPORTED 1