mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 19:13:47 +02:00
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:
commit
0b45ac1170
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 && \
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
54
drivers/gpu/drm/i915/display/intel_dvo_regs.h
Normal file
54
drivers/gpu/drm/i915/display/intel_dvo_regs.h
Normal 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__ */
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) &&
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user