1
0
Fork 0

- Display hotplug fix for gen2/gen3 (Chris)

- Remove trailing semicolon (Tom)
 - Suppress display warnings for old ifwi presend on our CI (Chris)
 - OA/Perf related workaround (Lionel)
 - Replace I915_READ/WRITE per new uncore and display read/write functions (Jani)\
 .
 - PSR improvements (Jose)
 - HDR and other color changes on LSPCON (Uma, Ville)
 - FBC fixes for TGL (Uma)
 - Record plane update times for debugging (Chris)
 - Refactor panel backlight control functions (Dave)
 - Display power improvements (Imre)
 - Add VRR register definition (Manasi)
 - Atomic modeset improvements for bigjoiner pipes (Ville)
 - Switch off the scanout during driver unregister (Chris)
 - Clean-up DP's FEW enable (Manasi)
 - Fix VDSCP slice count (Manasi)
 - Fix and clean up around rc_model_size for DSC (Jani)
 - Remove Type-C noisy debug warn message (Sean)
 - Display HPD code clean-up (Ville)
 - Refactor Intel Display (Dave)
 - Start adding support for Intel's eDP backlight controls (Lyude)
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAl/zg+sACgkQ+mJfZA7r
 E8rQxQf+I1sRI+7hyUxJ3V2bYayY1MIlw5W4wMqe2WX+NXd3/1RIQlXKZke9SFz5
 E2Q3XMFa9Q3XWSIW4W4+ro0uoj4uXTpCfwsHY2W7CkkroILlYbLT+pL7TjJ2fkBg
 ZbEScaXnQfwiicVKXmz4zbYud9isQCyQpBHUPteBxhhD01eE6yqABv/mg6+hSujE
 9q4Dhp2ozSL+4YiRO6gQ6rOcqx7fIBKXwNyd9wTNnv7UFw8iRmjkr8eLVwUC7MlM
 h+2uTaFY+hxxnGHPWpwxek6jhrmMk2o9ItxzaBpSVXbvVWRbHoUUSeqeAvGBBvZS
 O5QoufH98Sg07lc5664Dk4nMgeTHYg==
 =zIiA
 -----END PGP SIGNATURE-----

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

- Display hotplug fix for gen2/gen3 (Chris)
- Remove trailing semicolon (Tom)
- Suppress display warnings for old ifwi presend on our CI (Chris)
- OA/Perf related workaround (Lionel)
- Replace I915_READ/WRITE per new uncore and display read/write functions (Jani)
- PSR improvements (Jose)
- HDR and other color changes on LSPCON (Uma, Ville)
- FBC fixes for TGL (Uma)
- Record plane update times for debugging (Chris)
- Refactor panel backlight control functions (Dave)
- Display power improvements (Imre)
- Add VRR register definition (Manasi)
- Atomic modeset improvements for bigjoiner pipes (Ville)
- Switch off the scanout during driver unregister (Chris)
- Clean-up DP's FEW enable (Manasi)
- Fix VDSCP slice count (Manasi)
- Fix and clean up around rc_model_size for DSC (Jani)
- Remove Type-C noisy debug warn message (Sean)
- Display HPD code clean-up (Ville)
- Refactor Intel Display (Dave)
- Start adding support for Intel's eDP backlight controls (Lyude)

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210104211018.GA1094707@intel.com
master
Daniel Vetter 2021-01-07 12:20:28 +01:00
commit ca765c731e
48 changed files with 3185 additions and 3041 deletions

View File

@ -49,6 +49,33 @@ void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header)
}
EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
/**
* drm_dsc_dp_rc_buffer_size - get rc buffer size in bytes
* @rc_buffer_block_size: block size code, according to DPCD offset 62h
* @rc_buffer_size: number of blocks - 1, according to DPCD offset 63h
*
* return:
* buffer size in bytes, or 0 on invalid input
*/
int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size)
{
int size = 1024 * (rc_buffer_size + 1);
switch (rc_buffer_block_size) {
case DP_DSC_RC_BUF_BLK_SIZE_1:
return 1 * size;
case DP_DSC_RC_BUF_BLK_SIZE_4:
return 4 * size;
case DP_DSC_RC_BUF_BLK_SIZE_16:
return 16 * size;
case DP_DSC_RC_BUF_BLK_SIZE_64:
return 64 * size;
default:
return 0;
}
}
EXPORT_SYMBOL(drm_dsc_dp_rc_buffer_size);
/**
* drm_dsc_pps_payload_pack() - Populates the DSC PPS
*
@ -186,8 +213,7 @@ void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_payload,
pps_payload->flatness_max_qp = dsc_cfg->flatness_max_qp;
/* PPS 38, 39 */
pps_payload->rc_model_size =
cpu_to_be16(DSC_RC_MODEL_SIZE_CONST);
pps_payload->rc_model_size = cpu_to_be16(dsc_cfg->rc_model_size);
/* PPS 40 */
pps_payload->rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST;

View File

@ -197,6 +197,7 @@ i915-y += \
display/intel_combo_phy.o \
display/intel_connector.o \
display/intel_csr.o \
display/intel_cursor.o \
display/intel_display.o \
display/intel_display_power.o \
display/intel_dpio_phy.o \
@ -214,7 +215,8 @@ i915-y += \
display/intel_quirks.o \
display/intel_sprite.o \
display/intel_tc.o \
display/intel_vga.o
display/intel_vga.o \
display/i9xx_plane.o
i915-$(CONFIG_ACPI) += \
display/intel_acpi.o \
display/intel_opregion.o

View File

@ -0,0 +1,704 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2020 Intel Corporation
*/
#include <linux/kernel.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
#include "intel_display_types.h"
#include "intel_sprite.h"
#include "i9xx_plane.h"
/* Primary plane formats for gen <= 3 */
static const u32 i8xx_primary_formats[] = {
DRM_FORMAT_C8,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
};
/* Primary plane formats for ivb (no fp16 due to hw issue) */
static const u32 ivb_primary_formats[] = {
DRM_FORMAT_C8,
DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_XBGR2101010,
};
/* Primary plane formats for gen >= 4, except ivb */
static const u32 i965_primary_formats[] = {
DRM_FORMAT_C8,
DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_XBGR2101010,
DRM_FORMAT_XBGR16161616F,
};
/* Primary plane formats for vlv/chv */
static const u32 vlv_primary_formats[] = {
DRM_FORMAT_C8,
DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_XRGB2101010,
DRM_FORMAT_XBGR2101010,
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_ABGR2101010,
DRM_FORMAT_XBGR16161616F,
};
static const u64 i9xx_format_modifiers[] = {
I915_FORMAT_MOD_X_TILED,
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
u32 format, u64 modifier)
{
switch (modifier) {
case DRM_FORMAT_MOD_LINEAR:
case I915_FORMAT_MOD_X_TILED:
break;
default:
return false;
}
switch (format) {
case DRM_FORMAT_C8:
case DRM_FORMAT_RGB565:
case DRM_FORMAT_XRGB1555:
case DRM_FORMAT_XRGB8888:
return modifier == DRM_FORMAT_MOD_LINEAR ||
modifier == I915_FORMAT_MOD_X_TILED;
default:
return false;
}
}
static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
u32 format, u64 modifier)
{
switch (modifier) {
case DRM_FORMAT_MOD_LINEAR:
case I915_FORMAT_MOD_X_TILED:
break;
default:
return false;
}
switch (format) {
case DRM_FORMAT_C8:
case DRM_FORMAT_RGB565:
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ABGR8888:
case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_XBGR2101010:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_XBGR16161616F:
return modifier == DRM_FORMAT_MOD_LINEAR ||
modifier == I915_FORMAT_MOD_X_TILED;
default:
return false;
}
}
static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
enum i9xx_plane_id i9xx_plane)
{
if (!HAS_FBC(dev_priv))
return false;
if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
return i9xx_plane == PLANE_A; /* tied to pipe A */
else if (IS_IVYBRIDGE(dev_priv))
return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
i9xx_plane == PLANE_C;
else if (INTEL_GEN(dev_priv) >= 4)
return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
else
return i9xx_plane == PLANE_A;
}
static bool i9xx_plane_has_windowing(struct intel_plane *plane)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
if (IS_CHERRYVIEW(dev_priv))
return i9xx_plane == PLANE_B;
else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
return false;
else if (IS_GEN(dev_priv, 4))
return i9xx_plane == PLANE_C;
else
return i9xx_plane == PLANE_B ||
i9xx_plane == PLANE_C;
}
static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int rotation = plane_state->hw.rotation;
u32 dspcntr;
dspcntr = DISPLAY_PLANE_ENABLE;
if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
switch (fb->format->format) {
case DRM_FORMAT_C8:
dspcntr |= DISPPLANE_8BPP;
break;
case DRM_FORMAT_XRGB1555:
dspcntr |= DISPPLANE_BGRX555;
break;
case DRM_FORMAT_ARGB1555:
dspcntr |= DISPPLANE_BGRA555;
break;
case DRM_FORMAT_RGB565:
dspcntr |= DISPPLANE_BGRX565;
break;
case DRM_FORMAT_XRGB8888:
dspcntr |= DISPPLANE_BGRX888;
break;
case DRM_FORMAT_XBGR8888:
dspcntr |= DISPPLANE_RGBX888;
break;
case DRM_FORMAT_ARGB8888:
dspcntr |= DISPPLANE_BGRA888;
break;
case DRM_FORMAT_ABGR8888:
dspcntr |= DISPPLANE_RGBA888;
break;
case DRM_FORMAT_XRGB2101010:
dspcntr |= DISPPLANE_BGRX101010;
break;
case DRM_FORMAT_XBGR2101010:
dspcntr |= DISPPLANE_RGBX101010;
break;
case DRM_FORMAT_ARGB2101010:
dspcntr |= DISPPLANE_BGRA101010;
break;
case DRM_FORMAT_ABGR2101010:
dspcntr |= DISPPLANE_RGBA101010;
break;
case DRM_FORMAT_XBGR16161616F:
dspcntr |= DISPPLANE_RGBX161616;
break;
default:
MISSING_CASE(fb->format->format);
return 0;
}
if (INTEL_GEN(dev_priv) >= 4 &&
fb->modifier == I915_FORMAT_MOD_X_TILED)
dspcntr |= DISPPLANE_TILED;
if (rotation & DRM_MODE_ROTATE_180)
dspcntr |= DISPPLANE_ROTATE_180;
if (rotation & DRM_MODE_REFLECT_X)
dspcntr |= DISPPLANE_MIRROR;
return dspcntr;
}
int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
int src_x, src_y, src_w;
u32 offset;
int ret;
ret = intel_plane_compute_gtt(plane_state);
if (ret)
return ret;
if (!plane_state->uapi.visible)
return 0;
src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
src_x = plane_state->uapi.src.x1 >> 16;
src_y = plane_state->uapi.src.y1 >> 16;
/* Undocumented hardware limit on i965/g4x/vlv/chv */
if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048)
return -EINVAL;
intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
if (INTEL_GEN(dev_priv) >= 4)
offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
plane_state, 0);
else
offset = 0;
/*
* Put the final coordinates back so that the src
* coordinate checks will see the right values.
*/
drm_rect_translate_to(&plane_state->uapi.src,
src_x << 16, src_y << 16);
/* HSW/BDW do this automagically in hardware */
if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
unsigned int rotation = plane_state->hw.rotation;
int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
if (rotation & DRM_MODE_ROTATE_180) {
src_x += src_w - 1;
src_y += src_h - 1;
} else if (rotation & DRM_MODE_REFLECT_X) {
src_x += src_w - 1;
}
}
plane_state->color_plane[0].offset = offset;
plane_state->color_plane[0].x = src_x;
plane_state->color_plane[0].y = src_y;
return 0;
}
static int
i9xx_plane_check(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
int ret;
ret = chv_plane_check_rotation(plane_state);
if (ret)
return ret;
ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
i9xx_plane_has_windowing(plane));
if (ret)
return ret;
ret = i9xx_check_plane_surface(plane_state);
if (ret)
return ret;
if (!plane_state->uapi.visible)
return 0;
ret = intel_plane_check_src_coordinates(plane_state);
if (ret)
return ret;
plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
return 0;
}
static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 dspcntr = 0;
if (crtc_state->gamma_enable)
dspcntr |= DISPPLANE_GAMMA_ENABLE;
if (crtc_state->csc_enable)
dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
if (INTEL_GEN(dev_priv) < 5)
dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
return dspcntr;
}
static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state,
unsigned int *num, unsigned int *den)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int cpp = fb->format->cpp[0];
/*
* g4x bspec says 64bpp pixel rate can't exceed 80%
* of cdclk when the sprite plane is enabled on the
* same pipe. ilk/snb bspec says 64bpp pixel rate is
* never allowed to exceed 80% of cdclk. Let's just go
* with the ilk/snb limit always.
*/
if (cpp == 8) {
*num = 10;
*den = 8;
} else {
*num = 1;
*den = 1;
}
}
static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
unsigned int pixel_rate;
unsigned int num, den;
/*
* Note that crtc_state->pixel_rate accounts for both
* horizontal and vertical panel fitter downscaling factors.
* Pre-HSW bspec tells us to only consider the horizontal
* downscaling factor here. We ignore that and just consider
* both for simplicity.
*/
pixel_rate = crtc_state->pixel_rate;
i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
/* two pixels per clock with double wide pipe */
if (crtc_state->double_wide)
den *= 2;
return DIV_ROUND_UP(pixel_rate * num, den);
}
static void i9xx_update_plane(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
u32 linear_offset;
int x = plane_state->color_plane[0].x;
int y = plane_state->color_plane[0].y;
int crtc_x = plane_state->uapi.dst.x1;
int crtc_y = plane_state->uapi.dst.y1;
int crtc_w = drm_rect_width(&plane_state->uapi.dst);
int crtc_h = drm_rect_height(&plane_state->uapi.dst);
unsigned long irqflags;
u32 dspaddr_offset;
u32 dspcntr;
dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
if (INTEL_GEN(dev_priv) >= 4)
dspaddr_offset = plane_state->color_plane[0].offset;
else
dspaddr_offset = linear_offset;
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
plane_state->color_plane[0].stride);
if (INTEL_GEN(dev_priv) < 4) {
/*
* PLANE_A doesn't actually have a full window
* generator but let's assume we still need to
* program whatever is there.
*/
intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
(crtc_y << 16) | crtc_x);
intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
((crtc_h - 1) << 16) | (crtc_w - 1));
} else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
(crtc_y << 16) | crtc_x);
intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
((crtc_h - 1) << 16) | (crtc_w - 1));
intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
}
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
(y << 16) | x);
} else if (INTEL_GEN(dev_priv) >= 4) {
intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
linear_offset);
intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
(y << 16) | x);
}
/*
* The control register self-arms if the plane was previously
* disabled. Try to make the plane enable atomic by writing
* the control register just before the surface register.
*/
intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
if (INTEL_GEN(dev_priv) >= 4)
intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
else
intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void i9xx_disable_plane(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
unsigned long irqflags;
u32 dspcntr;
/*
* DSPCNTR pipe gamma enable on g4x+ and pipe csc
* enable on ilk+ affect the pipe bottom color as
* well, so we must configure them even if the plane
* is disabled.
*
* On pre-g4x there is no way to gamma correct the
* pipe bottom color but we'll keep on doing this
* anyway so that the crtc state readout works correctly.
*/
dspcntr = i9xx_plane_ctl_crtc(crtc_state);
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
if (INTEL_GEN(dev_priv) >= 4)
intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
else
intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum intel_display_power_domain power_domain;
enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
intel_wakeref_t wakeref;
bool ret;
u32 val;
/*
* Not 100% correct for planes that can move between pipes,
* but that's only the case for gen2-4 which don't have any
* display power wells.
*/
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wakeref)
return false;
val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
ret = val & DISPLAY_PLANE_ENABLE;
if (INTEL_GEN(dev_priv) >= 5)
*pipe = plane->pipe;
else
*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
DISPPLANE_SEL_PIPE_SHIFT;
intel_display_power_put(dev_priv, power_domain, wakeref);
return ret;
}
unsigned int
i9xx_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
if (!HAS_GMCH(dev_priv)) {
return 32*1024;
} else if (INTEL_GEN(dev_priv) >= 4) {
if (modifier == I915_FORMAT_MOD_X_TILED)
return 16*1024;
else
return 32*1024;
} else if (INTEL_GEN(dev_priv) >= 3) {
if (modifier == I915_FORMAT_MOD_X_TILED)
return 8*1024;
else
return 16*1024;
} else {
if (plane->i9xx_plane == PLANE_C)
return 4*1024;
else
return 8*1024;
}
}
static const struct drm_plane_funcs i965_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = intel_plane_destroy,
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
.format_mod_supported = i965_plane_format_mod_supported,
};
static const struct drm_plane_funcs i8xx_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = intel_plane_destroy,
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
.format_mod_supported = i8xx_plane_format_mod_supported,
};
struct intel_plane *
intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_plane *plane;
const struct drm_plane_funcs *plane_funcs;
unsigned int supported_rotations;
const u32 *formats;
int num_formats;
int ret, zpos;
if (INTEL_GEN(dev_priv) >= 9)
return skl_universal_plane_create(dev_priv, pipe,
PLANE_PRIMARY);
plane = intel_plane_alloc();
if (IS_ERR(plane))
return plane;
plane->pipe = pipe;
/*
* On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
* port is hooked to pipe B. Hence we want plane A feeding pipe B.
*/
if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
INTEL_NUM_PIPES(dev_priv) == 2)
plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
else
plane->i9xx_plane = (enum i9xx_plane_id) pipe;
plane->id = PLANE_PRIMARY;
plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
if (plane->has_fbc) {
struct intel_fbc *fbc = &dev_priv->fbc;
fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
}
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
formats = vlv_primary_formats;
num_formats = ARRAY_SIZE(vlv_primary_formats);
} else if (INTEL_GEN(dev_priv) >= 4) {
/*
* WaFP16GammaEnabling:ivb
* "Workaround : When using the 64-bit format, the plane
* output on each color channel has one quarter amplitude.
* It can be brought up to full amplitude by using pipe
* gamma correction or pipe color space conversion to
* multiply the plane output by four."
*
* There is no dedicated plane gamma for the primary plane,
* and using the pipe gamma/csc could conflict with other
* planes, so we choose not to expose fp16 on IVB primary
* planes. HSW primary planes no longer have this problem.
*/
if (IS_IVYBRIDGE(dev_priv)) {
formats = ivb_primary_formats;
num_formats = ARRAY_SIZE(ivb_primary_formats);
} else {
formats = i965_primary_formats;
num_formats = ARRAY_SIZE(i965_primary_formats);
}
} else {
formats = i8xx_primary_formats;
num_formats = ARRAY_SIZE(i8xx_primary_formats);
}
if (INTEL_GEN(dev_priv) >= 4)
plane_funcs = &i965_plane_funcs;
else
plane_funcs = &i8xx_plane_funcs;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
plane->min_cdclk = vlv_plane_min_cdclk;
else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
plane->min_cdclk = hsw_plane_min_cdclk;
else if (IS_IVYBRIDGE(dev_priv))
plane->min_cdclk = ivb_plane_min_cdclk;
else
plane->min_cdclk = i9xx_plane_min_cdclk;
plane->max_stride = i9xx_plane_max_stride;
plane->update_plane = i9xx_update_plane;
plane->disable_plane = i9xx_disable_plane;
plane->get_hw_state = i9xx_plane_get_hw_state;
plane->check_plane = i9xx_plane_check;
if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
0, plane_funcs,
formats, num_formats,
i9xx_format_modifiers,
DRM_PLANE_TYPE_PRIMARY,
"primary %c", pipe_name(pipe));
else
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
0, plane_funcs,
formats, num_formats,
i9xx_format_modifiers,
DRM_PLANE_TYPE_PRIMARY,
"plane %c",
plane_name(plane->i9xx_plane));
if (ret)
goto fail;
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
supported_rotations =
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
DRM_MODE_REFLECT_X;
} else if (INTEL_GEN(dev_priv) >= 4) {
supported_rotations =
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
} else {
supported_rotations = DRM_MODE_ROTATE_0;
}
if (INTEL_GEN(dev_priv) >= 4)
drm_plane_create_rotation_property(&plane->base,
DRM_MODE_ROTATE_0,
supported_rotations);
zpos = 0;
drm_plane_create_zpos_immutable_property(&plane->base, zpos);
drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
return plane;
fail:
intel_plane_free(plane);
return ERR_PTR(ret);
}

View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2020 Intel Corporation
*/
#ifndef _I9XX_PLANE_H_
#define _I9XX_PLANE_H_
#include <linux/types.h>
enum pipe;
struct drm_i915_private;
struct intel_plane;
struct intel_plane_state;
unsigned int i9xx_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation);
int i9xx_check_plane_surface(struct intel_plane_state *plane_state);
struct intel_plane *
intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe);
#endif

View File

@ -1535,6 +1535,9 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
vdsc_cfg->convert_rgb = true;
/* FIXME: initialize from VBT */
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
ret = intel_dsc_compute_params(encoder, crtc_state);
if (ret)
return ret;
@ -1616,10 +1619,6 @@ static void gen11_dsi_get_power_domains(struct intel_encoder *encoder,
get_dsi_io_power_domains(i915,
enc_to_intel_dsi(encoder));
if (crtc_state->dsc.compression_enable)
intel_display_power_get(i915,
intel_dsc_power_domain(crtc_state));
}
static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,

View File

@ -312,10 +312,13 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
int ret;
intel_plane_set_invisible(new_crtc_state, new_plane_state);
new_crtc_state->enabled_planes &= ~BIT(plane->id);
if (!new_plane_state->hw.crtc && !old_plane_state->hw.crtc)
return 0;
new_crtc_state->enabled_planes |= BIT(plane->id);
ret = plane->check_plane(new_crtc_state, new_plane_state);
if (ret)
return ret;

View File

@ -2555,16 +2555,11 @@ static void fill_dsc(struct intel_crtc_state *crtc_state,
crtc_state->dsc.slice_count);
/*
* FIXME: Use VBT rc_buffer_block_size and rc_buffer_size for the
* implementation specific physical rate buffer size. Currently we use
* the required rate buffer model size calculated in
* drm_dsc_compute_rc_parameters() according to VESA DSC Annex E.
*
* The VBT rc_buffer_block_size and rc_buffer_size definitions
* correspond to DP 1.4 DPCD offsets 0x62 and 0x63. The DP DSC
* implementation should also use the DPCD (or perhaps VBT for eDP)
* provided value for the buffer size.
* correspond to DP 1.4 DPCD offsets 0x62 and 0x63.
*/
vdsc_cfg->rc_model_size = drm_dsc_dp_rc_buffer_size(dsc->rc_buffer_block_size,
dsc->rc_buffer_size);
/* FIXME: DSI spec says bpc + 1 for this one */
vdsc_cfg->line_buf_depth = VBT_DSC_LINE_BUFFER_DEPTH(dsc->line_buffer_depth);

View File

@ -2415,8 +2415,7 @@ static int intel_modeset_all_pipes(struct intel_atomic_state *state)
if (ret)
return ret;
ret = drm_atomic_add_affected_planes(&state->base,
&crtc->base);
ret = intel_atomic_add_affected_planes(state, crtc);
if (ret)
return ret;
@ -2710,8 +2709,8 @@ static int dg1_rawclk(struct drm_i915_private *dev_priv)
* DG1 always uses a 38.4 MHz rawclk. The bspec tells us
* "Program Numerator=2, Denominator=4, Divider=37 decimal."
*/
I915_WRITE(PCH_RAWCLK_FREQ,
CNP_RAWCLK_DEN(4) | CNP_RAWCLK_DIV(37) | ICP_RAWCLK_NUM(2));
intel_de_write(dev_priv, PCH_RAWCLK_FREQ,
CNP_RAWCLK_DEN(4) | CNP_RAWCLK_DIV(37) | ICP_RAWCLK_NUM(2));
return 38400;
}

View File

@ -427,10 +427,22 @@ static void icl_combo_phys_uninit(struct drm_i915_private *dev_priv)
u32 val;
if (phy == PHY_A &&
!icl_combo_phy_verify_state(dev_priv, phy))
drm_warn(&dev_priv->drm,
"Combo PHY %c HW state changed unexpectedly\n",
phy_name(phy));
!icl_combo_phy_verify_state(dev_priv, phy)) {
if (IS_TIGERLAKE(dev_priv) || IS_DG1(dev_priv)) {
/*
* A known problem with old ifwi:
* https://gitlab.freedesktop.org/drm/intel/-/issues/2411
* Suppress the warning for CI. Remove ASAP!
*/
drm_dbg_kms(&dev_priv->drm,
"Combo PHY %c HW state changed unexpectedly\n",
phy_name(phy));
} else {
drm_warn(&dev_priv->drm,
"Combo PHY %c HW state changed unexpectedly\n",
phy_name(phy));
}
}
if (!has_phy_misc(dev_priv, phy))
goto skip_phy_misc;

View File

@ -279,24 +279,17 @@ intel_attach_aspect_ratio_property(struct drm_connector *connector)
}
void
intel_attach_colorspace_property(struct drm_connector *connector)
intel_attach_hdmi_colorspace_property(struct drm_connector *connector)
{
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
if (drm_mode_create_hdmi_colorspace_property(connector))
return;
break;
case DRM_MODE_CONNECTOR_DisplayPort:
case DRM_MODE_CONNECTOR_eDP:
if (drm_mode_create_dp_colorspace_property(connector))
return;
break;
default:
MISSING_CASE(connector->connector_type);
return;
}
drm_object_attach_property(&connector->base,
connector->colorspace_property, 0);
if (!drm_mode_create_hdmi_colorspace_property(connector))
drm_object_attach_property(&connector->base,
connector->colorspace_property, 0);
}
void
intel_attach_dp_colorspace_property(struct drm_connector *connector)
{
if (!drm_mode_create_dp_colorspace_property(connector))
drm_object_attach_property(&connector->base,
connector->colorspace_property, 0);
}

View File

@ -30,6 +30,7 @@ int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
void intel_attach_force_audio_property(struct drm_connector *connector);
void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
void intel_attach_aspect_ratio_property(struct drm_connector *connector);
void intel_attach_colorspace_property(struct drm_connector *connector);
void intel_attach_hdmi_colorspace_property(struct drm_connector *connector);
void intel_attach_dp_colorspace_property(struct drm_connector *connector);
#endif /* __INTEL_CONNECTOR_H__ */

View File

@ -0,0 +1,806 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2020 Intel Corporation
*/
#include <linux/kernel.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_fourcc.h>
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
#include "intel_cursor.h"
#include "intel_display_types.h"
#include "intel_display.h"
#include "intel_frontbuffer.h"
#include "intel_pm.h"
#include "intel_psr.h"
#include "intel_sprite.h"
/* Cursor formats */
static const u32 intel_cursor_formats[] = {
DRM_FORMAT_ARGB8888,
};
static const u64 cursor_format_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
u32 base;
if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
base = sg_dma_address(obj->mm.pages->sgl);
else
base = intel_plane_ggtt_offset(plane_state);
return base + plane_state->color_plane[0].offset;
}
static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
{
int x = plane_state->uapi.dst.x1;
int y = plane_state->uapi.dst.y1;
u32 pos = 0;
if (x < 0) {
pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
x = -x;
}
pos |= x << CURSOR_X_SHIFT;
if (y < 0) {
pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
y = -y;
}
pos |= y << CURSOR_Y_SHIFT;
return pos;
}
static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
{
const struct drm_mode_config *config =
&plane_state->uapi.plane->dev->mode_config;
int width = drm_rect_width(&plane_state->uapi.dst);
int height = drm_rect_height(&plane_state->uapi.dst);
return width > 0 && width <= config->cursor_width &&
height > 0 && height <= config->cursor_height;
}
static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
unsigned int rotation = plane_state->hw.rotation;
int src_x, src_y;
u32 offset;
int ret;
ret = intel_plane_compute_gtt(plane_state);
if (ret)
return ret;
if (!plane_state->uapi.visible)
return 0;
src_x = plane_state->uapi.src.x1 >> 16;
src_y = plane_state->uapi.src.y1 >> 16;
intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
plane_state, 0);
if (src_x != 0 || src_y != 0) {
drm_dbg_kms(&dev_priv->drm,
"Arbitrary cursor panning not supported\n");
return -EINVAL;
}
/*
* Put the final coordinates back so that the src
* coordinate checks will see the right values.
*/
drm_rect_translate_to(&plane_state->uapi.src,
src_x << 16, src_y << 16);
/* ILK+ do this automagically in hardware */
if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
const struct drm_framebuffer *fb = plane_state->hw.fb;
int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
offset += (src_h * src_w - 1) * fb->format->cpp[0];
}
plane_state->color_plane[0].offset = offset;
plane_state->color_plane[0].x = src_x;
plane_state->color_plane[0].y = src_y;
return 0;
}
static int intel_check_cursor(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
const struct drm_rect src = plane_state->uapi.src;
const struct drm_rect dst = plane_state->uapi.dst;
int ret;
if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
drm_dbg_kms(&i915->drm, "cursor cannot be tiled\n");
return -EINVAL;
}
ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
true);
if (ret)
return ret;
/* Use the unclipped src/dst rectangles, which we program to hw */
plane_state->uapi.src = src;
plane_state->uapi.dst = dst;
ret = intel_cursor_check_surface(plane_state);
if (ret)
return ret;
if (!plane_state->uapi.visible)
return 0;
ret = intel_plane_check_src_coordinates(plane_state);
if (ret)
return ret;
return 0;
}
static unsigned int
i845_cursor_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation)
{
return 2048;
}
static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
u32 cntl = 0;
if (crtc_state->gamma_enable)
cntl |= CURSOR_GAMMA_ENABLE;
return cntl;
}
static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
return CURSOR_ENABLE |
CURSOR_FORMAT_ARGB |
CURSOR_STRIDE(plane_state->color_plane[0].stride);
}
static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
{
int width = drm_rect_width(&plane_state->uapi.dst);
/*
* 845g/865g are only limited by the width of their cursors,
* the height is arbitrary up to the precision of the register.
*/
return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
}
static int i845_check_cursor(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
int ret;
ret = intel_check_cursor(crtc_state, plane_state);
if (ret)
return ret;
/* if we want to turn off the cursor ignore width and height */
if (!fb)
return 0;
/* Check for which cursor types we support */
if (!i845_cursor_size_ok(plane_state)) {
drm_dbg_kms(&i915->drm,
"Cursor dimension %dx%d not supported\n",
drm_rect_width(&plane_state->uapi.dst),
drm_rect_height(&plane_state->uapi.dst));
return -EINVAL;
}
drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
plane_state->color_plane[0].stride != fb->pitches[0]);
switch (fb->pitches[0]) {
case 256:
case 512:
case 1024:
case 2048:
break;
default:
drm_dbg_kms(&i915->drm, "Invalid cursor stride (%u)\n",
fb->pitches[0]);
return -EINVAL;
}
plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
return 0;
}
static void i845_update_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
u32 cntl = 0, base = 0, pos = 0, size = 0;
unsigned long irqflags;
if (plane_state && plane_state->uapi.visible) {
unsigned int width = drm_rect_width(&plane_state->uapi.dst);
unsigned int height = drm_rect_height(&plane_state->uapi.dst);
cntl = plane_state->ctl |
i845_cursor_ctl_crtc(crtc_state);
size = (height << 12) | width;
base = intel_cursor_base(plane_state);
pos = intel_cursor_position(plane_state);
}
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
/* On these chipsets we can only modify the base/size/stride
* whilst the cursor is disabled.
*/
if (plane->cursor.base != base ||
plane->cursor.size != size ||
plane->cursor.cntl != cntl) {
intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), 0);
intel_de_write_fw(dev_priv, CURBASE(PIPE_A), base);
intel_de_write_fw(dev_priv, CURSIZE, size);
intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
intel_de_write_fw(dev_priv, CURCNTR(PIPE_A), cntl);
plane->cursor.base = base;
plane->cursor.size = size;
plane->cursor.cntl = cntl;
} else {
intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos);
}
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void i845_disable_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
i845_update_cursor(plane, crtc_state, NULL);
}
static bool i845_cursor_get_hw_state(struct intel_plane *plane,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
bool ret;
power_domain = POWER_DOMAIN_PIPE(PIPE_A);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wakeref)
return false;
ret = intel_de_read(dev_priv, CURCNTR(PIPE_A)) & CURSOR_ENABLE;
*pipe = PIPE_A;
intel_display_power_put(dev_priv, power_domain, wakeref);
return ret;
}
static unsigned int
i9xx_cursor_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation)
{
return plane->base.dev->mode_config.cursor_width * 4;
}
static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 cntl = 0;
if (INTEL_GEN(dev_priv) >= 11)
return cntl;
if (crtc_state->gamma_enable)
cntl = MCURSOR_GAMMA_ENABLE;
if (crtc_state->csc_enable)
cntl |= MCURSOR_PIPE_CSC_ENABLE;
if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
return cntl;
}
static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
u32 cntl = 0;
if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
switch (drm_rect_width(&plane_state->uapi.dst)) {
case 64:
cntl |= MCURSOR_MODE_64_ARGB_AX;
break;
case 128:
cntl |= MCURSOR_MODE_128_ARGB_AX;
break;
case 256:
cntl |= MCURSOR_MODE_256_ARGB_AX;
break;
default:
MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
return 0;
}
if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
cntl |= MCURSOR_ROTATE_180;
return cntl;
}
static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv =
to_i915(plane_state->uapi.plane->dev);
int width = drm_rect_width(&plane_state->uapi.dst);
int height = drm_rect_height(&plane_state->uapi.dst);
if (!intel_cursor_size_ok(plane_state))
return false;
/* Cursor width is limited to a few power-of-two sizes */
switch (width) {
case 256:
case 128:
case 64:
break;
default:
return false;
}
/*
* IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
* height from 8 lines up to the cursor width, when the
* cursor is not rotated. Everything else requires square
* cursors.
*/
if (HAS_CUR_FBC(dev_priv) &&
plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
if (height < 8 || height > width)
return false;
} else {
if (height != width)
return false;
}
return true;
}
static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
struct intel_plane_state *plane_state)
{
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
const struct drm_framebuffer *fb = plane_state->hw.fb;
enum pipe pipe = plane->pipe;
int ret;
ret = intel_check_cursor(crtc_state, plane_state);
if (ret)
return ret;
/* if we want to turn off the cursor ignore width and height */
if (!fb)
return 0;
/* Check for which cursor types we support */
if (!i9xx_cursor_size_ok(plane_state)) {
drm_dbg(&dev_priv->drm,
"Cursor dimension %dx%d not supported\n",
drm_rect_width(&plane_state->uapi.dst),
drm_rect_height(&plane_state->uapi.dst));
return -EINVAL;
}
drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
plane_state->color_plane[0].stride != fb->pitches[0]);
if (fb->pitches[0] !=
drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
drm_dbg_kms(&dev_priv->drm,
"Invalid cursor stride (%u) (cursor width %d)\n",
fb->pitches[0],
drm_rect_width(&plane_state->uapi.dst));
return -EINVAL;
}
/*
* There's something wrong with the cursor on CHV pipe C.
* If it straddles the left edge of the screen then
* moving it away from the edge or disabling it often
* results in a pipe underrun, and often that can lead to
* dead pipe (constant underrun reported, and it scans
* out just a solid color). To recover from that, the
* display power well must be turned off and on again.
* Refuse the put the cursor into that compromised position.
*/
if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
drm_dbg_kms(&dev_priv->drm,
"CHV cursor C not allowed to straddle the left screen edge\n");
return -EINVAL;
}
plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
return 0;
}
static void i9xx_update_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum pipe pipe = plane->pipe;
u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
unsigned long irqflags;
if (plane_state && plane_state->uapi.visible) {
unsigned width = drm_rect_width(&plane_state->uapi.dst);
unsigned height = drm_rect_height(&plane_state->uapi.dst);
cntl = plane_state->ctl |
i9xx_cursor_ctl_crtc(crtc_state);
if (width != height)
fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
base = intel_cursor_base(plane_state);
pos = intel_cursor_position(plane_state);
}
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
/*
* On some platforms writing CURCNTR first will also
* cause CURPOS to be armed by the CURBASE write.
* Without the CURCNTR write the CURPOS write would
* arm itself. Thus we always update CURCNTR before
* CURPOS.
*
* On other platforms CURPOS always requires the
* CURBASE write to arm the update. Additonally
* a write to any of the cursor register will cancel
* an already armed cursor update. Thus leaving out
* the CURBASE write after CURPOS could lead to a
* cursor that doesn't appear to move, or even change
* shape. Thus we always write CURBASE.
*
* The other registers are armed by by the CURBASE write
* except when the plane is getting enabled at which time
* the CURCNTR write arms the update.
*/
if (INTEL_GEN(dev_priv) >= 9)
skl_write_cursor_wm(plane, crtc_state);
if (!intel_crtc_needs_modeset(crtc_state))
intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
if (plane->cursor.base != base ||
plane->cursor.size != fbc_ctl ||
plane->cursor.cntl != cntl) {
if (HAS_CUR_FBC(dev_priv))
intel_de_write_fw(dev_priv, CUR_FBC_CTL(pipe),
fbc_ctl);
intel_de_write_fw(dev_priv, CURCNTR(pipe), cntl);
intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
intel_de_write_fw(dev_priv, CURBASE(pipe), base);
plane->cursor.base = base;
plane->cursor.size = fbc_ctl;
plane->cursor.cntl = cntl;
} else {
intel_de_write_fw(dev_priv, CURPOS(pipe), pos);
intel_de_write_fw(dev_priv, CURBASE(pipe), base);
}
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
static void i9xx_disable_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
i9xx_update_cursor(plane, crtc_state, NULL);
}
static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
bool ret;
u32 val;
/*
* Not 100% correct for planes that can move between pipes,
* but that's only the case for gen2-3 which don't have any
* display power wells.
*/
power_domain = POWER_DOMAIN_PIPE(plane->pipe);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wakeref)
return false;
val = intel_de_read(dev_priv, CURCNTR(plane->pipe));
ret = val & MCURSOR_MODE;
if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
*pipe = plane->pipe;
else
*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
MCURSOR_PIPE_SELECT_SHIFT;
intel_display_power_put(dev_priv, power_domain, wakeref);
return ret;
}
static bool intel_cursor_format_mod_supported(struct drm_plane *_plane,
u32 format, u64 modifier)
{
return modifier == DRM_FORMAT_MOD_LINEAR &&
format == DRM_FORMAT_ARGB8888;
}
static int
intel_legacy_cursor_update(struct drm_plane *_plane,
struct drm_crtc *_crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
u32 src_x, u32 src_y,
u32 src_w, u32 src_h,
struct drm_modeset_acquire_ctx *ctx)
{
struct intel_plane *plane = to_intel_plane(_plane);
struct intel_crtc *crtc = to_intel_crtc(_crtc);
struct intel_plane_state *old_plane_state =
to_intel_plane_state(plane->base.state);
struct intel_plane_state *new_plane_state;
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
struct intel_crtc_state *new_crtc_state;
int ret;
/*
* When crtc is inactive or there is a modeset pending,
* wait for it to complete in the slowpath
*
* FIXME bigjoiner fastpath would be good
*/
if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
crtc_state->update_pipe || crtc_state->bigjoiner)
goto slow;
/*
* Don't do an async update if there is an outstanding commit modifying
* the plane. This prevents our async update's changes from getting
* overridden by a previous synchronous update's state.
*/
if (old_plane_state->uapi.commit &&
!try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
goto slow;
/*
* If any parameters change that may affect watermarks,
* take the slowpath. Only changing fb or position should be
* in the fastpath.
*/
if (old_plane_state->uapi.crtc != &crtc->base ||
old_plane_state->uapi.src_w != src_w ||
old_plane_state->uapi.src_h != src_h ||
old_plane_state->uapi.crtc_w != crtc_w ||
old_plane_state->uapi.crtc_h != crtc_h ||
!old_plane_state->uapi.fb != !fb)
goto slow;
new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
if (!new_plane_state)
return -ENOMEM;
new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
if (!new_crtc_state) {
ret = -ENOMEM;
goto out_free;
}
drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
new_plane_state->uapi.src_x = src_x;
new_plane_state->uapi.src_y = src_y;
new_plane_state->uapi.src_w = src_w;
new_plane_state->uapi.src_h = src_h;
new_plane_state->uapi.crtc_x = crtc_x;
new_plane_state->uapi.crtc_y = crtc_y;
new_plane_state->uapi.crtc_w = crtc_w;
new_plane_state->uapi.crtc_h = crtc_h;
intel_plane_copy_uapi_to_hw_state(new_plane_state, new_plane_state, crtc);
ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
old_plane_state, new_plane_state);
if (ret)
goto out_free;
ret = intel_plane_pin_fb(new_plane_state);
if (ret)
goto out_free;
intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
ORIGIN_FLIP);
intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
to_intel_frontbuffer(new_plane_state->hw.fb),
plane->frontbuffer_bit);
/* Swap plane state */
plane->base.state = &new_plane_state->uapi;
/*
* We cannot swap crtc_state as it may be in use by an atomic commit or
* page flip that's running simultaneously. If we swap crtc_state and
* destroy the old state, we will cause a use-after-free there.
*
* Only update active_planes, which is needed for our internal
* bookkeeping. Either value will do the right thing when updating
* planes atomically. If the cursor was part of the atomic update then
* we would have taken the slowpath.
*/
crtc_state->active_planes = new_crtc_state->active_planes;
if (new_plane_state->uapi.visible)
intel_update_plane(plane, crtc_state, new_plane_state);
else
intel_disable_plane(plane, crtc_state);
intel_plane_unpin_fb(old_plane_state);
out_free:
if (new_crtc_state)
intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
if (ret)
intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
else
intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
return ret;
slow:
return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h, ctx);
}
static const struct drm_plane_funcs intel_cursor_plane_funcs = {
.update_plane = intel_legacy_cursor_update,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = intel_plane_destroy,
.atomic_duplicate_state = intel_plane_duplicate_state,
.atomic_destroy_state = intel_plane_destroy_state,
.format_mod_supported = intel_cursor_format_mod_supported,
};
struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
struct intel_plane *cursor;
int ret, zpos;
cursor = intel_plane_alloc();
if (IS_ERR(cursor))
return cursor;
cursor->pipe = pipe;
cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
cursor->id = PLANE_CURSOR;
cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
cursor->max_stride = i845_cursor_max_stride;
cursor->update_plane = i845_update_cursor;
cursor->disable_plane = i845_disable_cursor;
cursor->get_hw_state = i845_cursor_get_hw_state;
cursor->check_plane = i845_check_cursor;
} else {
cursor->max_stride = i9xx_cursor_max_stride;
cursor->update_plane = i9xx_update_cursor;
cursor->disable_plane = i9xx_disable_cursor;
cursor->get_hw_state = i9xx_cursor_get_hw_state;
cursor->check_plane = i9xx_check_cursor;
}
cursor->cursor.base = ~0;
cursor->cursor.cntl = ~0;
if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
cursor->cursor.size = ~0;
ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
0, &intel_cursor_plane_funcs,
intel_cursor_formats,
ARRAY_SIZE(intel_cursor_formats),
cursor_format_modifiers,
DRM_PLANE_TYPE_CURSOR,
"cursor %c", pipe_name(pipe));
if (ret)
goto fail;
if (INTEL_GEN(dev_priv) >= 4)
drm_plane_create_rotation_property(&cursor->base,
DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 |
DRM_MODE_ROTATE_180);
zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
if (INTEL_GEN(dev_priv) >= 12)
drm_plane_enable_fb_damage_clips(&cursor->base);
drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
return cursor;
fail:
intel_plane_free(cursor);
return ERR_PTR(ret);
}

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2020 Intel Corporation
*/
#ifndef _INTEL_CURSOR_H_
#define _INTEL_CURSOR_H_
enum pipe;
struct drm_i915_private;
struct intel_plane;
struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe);
#endif

View File

@ -2285,18 +2285,23 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
dig_port = enc_to_dig_port(encoder);
if (!intel_phy_is_tc(dev_priv, phy) ||
dig_port->tc_mode != TC_PORT_TBT_ALT)
intel_display_power_get(dev_priv,
dig_port->ddi_io_power_domain);
dig_port->tc_mode != TC_PORT_TBT_ALT) {
drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
dig_port->ddi_io_power_domain);
}
/*
* AUX power is only needed for (e)DP mode, and for HDMI mode on TC
* ports.
*/
if (intel_crtc_has_dp_encoder(crtc_state) ||
intel_phy_is_tc(dev_priv, phy))
intel_display_power_get(dev_priv,
intel_ddi_main_link_aux_domain(dig_port));
intel_phy_is_tc(dev_priv, phy)) {
drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref);
dig_port->aux_wakeref =
intel_display_power_get(dev_priv,
intel_ddi_main_link_aux_domain(dig_port));
}
}
void intel_ddi_enable_pipe_clock(struct intel_encoder *encoder,
@ -3507,12 +3512,6 @@ static void intel_ddi_enable_fec(struct intel_encoder *encoder,
val = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
val |= DP_TP_CTL_FEC_ENABLE;
intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), val);
if (intel_de_wait_for_set(dev_priv,
dp_tp_status_reg(encoder, crtc_state),
DP_TP_STATUS_FEC_ENABLE_LIVE, 1))
drm_err(&dev_priv->drm,
"Timed out waiting for FEC Enable Status\n");
}
static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
@ -3577,9 +3576,11 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
/* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */
if (!intel_phy_is_tc(dev_priv, phy) ||
dig_port->tc_mode != TC_PORT_TBT_ALT)
intel_display_power_get(dev_priv,
dig_port->ddi_io_power_domain);
dig_port->tc_mode != TC_PORT_TBT_ALT) {
drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
dig_port->ddi_io_power_domain);
}
/* 6. Program DP_MODE */
icl_program_mg_dp_mode(dig_port, crtc_state);
@ -3702,9 +3703,11 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
intel_ddi_clk_select(encoder, crtc_state);
if (!intel_phy_is_tc(dev_priv, phy) ||
dig_port->tc_mode != TC_PORT_TBT_ALT)
intel_display_power_get(dev_priv,
dig_port->ddi_io_power_domain);
dig_port->tc_mode != TC_PORT_TBT_ALT) {
drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
dig_port->ddi_io_power_domain);
}
icl_program_mg_dp_mode(dig_port, crtc_state);
@ -3782,7 +3785,9 @@ static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
intel_ddi_clk_select(encoder, crtc_state);
intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
dig_port->ddi_io_power_domain);
icl_program_mg_dp_mode(dig_port, crtc_state);
@ -3940,8 +3945,9 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
if (!intel_phy_is_tc(dev_priv, phy) ||
dig_port->tc_mode != TC_PORT_TBT_ALT)
intel_display_power_put_unchecked(dev_priv,
dig_port->ddi_io_power_domain);
intel_display_power_put(dev_priv,
dig_port->ddi_io_power_domain,
fetch_and_zero(&dig_port->ddi_io_wakeref));
intel_ddi_clk_disable(encoder);
}
@ -3962,8 +3968,9 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
intel_disable_ddi_buf(encoder, old_crtc_state);
intel_display_power_put_unchecked(dev_priv,
dig_port->ddi_io_power_domain);
intel_display_power_put(dev_priv,
dig_port->ddi_io_power_domain,
fetch_and_zero(&dig_port->ddi_io_wakeref));
intel_ddi_clk_disable(encoder);
@ -4036,8 +4043,9 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
icl_unmap_plls_to_ports(encoder);
if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port)
intel_display_power_put_unchecked(dev_priv,
intel_ddi_main_link_aux_domain(dig_port));
intel_display_power_put(dev_priv,
intel_ddi_main_link_aux_domain(dig_port),
fetch_and_zero(&dig_port->aux_wakeref));
if (is_tc_port)
intel_tc_port_put_link(dig_port);
@ -4122,6 +4130,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
enum port port = encoder->port;
if (port == PORT_A && INTEL_GEN(dev_priv) < 9)
@ -4129,7 +4138,10 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state,
intel_edp_backlight_on(crtc_state, conn_state);
intel_psr_enable(intel_dp, crtc_state, conn_state);
intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
intel_edp_drrs_enable(intel_dp, crtc_state);
if (crtc_state->has_audio)
@ -4372,9 +4384,12 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
if (is_tc_port)
intel_tc_port_get_link(dig_port, crtc_state->lane_count);
if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
intel_display_power_get(dev_priv,
intel_ddi_main_link_aux_domain(dig_port));
if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port) {
drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref);
dig_port->aux_wakeref =
intel_display_power_get(dev_priv,
intel_ddi_main_link_aux_domain(dig_port));
}
if (is_tc_port && dig_port->tc_mode != TC_PORT_TBT_ALT)
/*
@ -4587,6 +4602,7 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
u32 temp, flags = 0;
temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
@ -4661,9 +4677,12 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
pipe_config->fec_enable);
}
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
pipe_config->infoframes.enable |=
intel_lspcon_infoframes_enabled(encoder, pipe_config);
else
pipe_config->infoframes.enable |=
intel_hdmi_infoframes_enabled(encoder, pipe_config);
break;
case TRANS_DDI_MODE_SELECT_DP_MST:
pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);

File diff suppressed because it is too large Load Diff

View File

@ -499,6 +499,8 @@ enum phy_fia {
((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \
(new_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].new_state), 1))
int intel_atomic_add_affected_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc);
u8 intel_calc_active_pipes(struct intel_atomic_state *state,
u8 active_pipes);
void intel_link_compute_m_n(u16 bpp, int nlanes,
@ -628,11 +630,7 @@ u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state);
u32 skl_plane_stride(const struct intel_plane_state *plane_state,
int plane);
int skl_check_plane_surface(struct intel_plane_state *plane_state);
int i9xx_check_plane_surface(struct intel_plane_state *plane_state);
int skl_format_to_fourcc(int format, bool rgb_order, bool alpha);
unsigned int i9xx_plane_max_stride(struct intel_plane *plane,
u32 pixel_format, u64 modifier,
unsigned int rotation);
int bdw_get_pipemisc_bpp(struct intel_crtc *crtc);
unsigned int intel_plane_fence_y_offset(const struct intel_plane_state *plane_state);
@ -645,6 +643,13 @@ bool
intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
uint64_t modifier);
int intel_plane_compute_gtt(struct intel_plane_state *plane_state);
u32 intel_plane_compute_aligned_offset(int *x, int *y,
const struct intel_plane_state *state,
int color_plane);
int intel_plane_pin_fb(struct intel_plane_state *plane_state);
void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
/* modesetting */
void intel_modeset_init_hw(struct drm_i915_private *i915);
int intel_modeset_init_noirq(struct drm_i915_private *i915);

View File

@ -18,6 +18,7 @@
#include "intel_pm.h"
#include "intel_psr.h"
#include "intel_sideband.h"
#include "intel_sprite.h"
static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
{
@ -865,6 +866,110 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc)
}
}
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE)
static void crtc_updates_info(struct seq_file *m,
struct intel_crtc *crtc,
const char *hdr)
{
u64 count;
int row;
count = 0;
for (row = 0; row < ARRAY_SIZE(crtc->debug.vbl.times); row++)
count += crtc->debug.vbl.times[row];
seq_printf(m, "%sUpdates: %llu\n", hdr, count);
if (!count)
return;
for (row = 0; row < ARRAY_SIZE(crtc->debug.vbl.times); row++) {
char columns[80] = " |";
unsigned int x;
if (row & 1) {
const char *units;
if (row > 10) {
x = 1000000;
units = "ms";
} else {
x = 1000;
units = "us";
}
snprintf(columns, sizeof(columns), "%4ld%s |",
DIV_ROUND_CLOSEST(BIT(row + 9), x), units);
}
if (crtc->debug.vbl.times[row]) {
x = ilog2(crtc->debug.vbl.times[row]);
memset(columns + 8, '*', x);
columns[8 + x] = '\0';
}
seq_printf(m, "%s%s\n", hdr, columns);
}
seq_printf(m, "%sMin update: %lluns\n",
hdr, crtc->debug.vbl.min);
seq_printf(m, "%sMax update: %lluns\n",
hdr, crtc->debug.vbl.max);
seq_printf(m, "%sAverage update: %lluns\n",
hdr, div64_u64(crtc->debug.vbl.sum, count));
seq_printf(m, "%sOverruns > %uus: %u\n",
hdr, VBLANK_EVASION_TIME_US, crtc->debug.vbl.over);
}
static int crtc_updates_show(struct seq_file *m, void *data)
{
crtc_updates_info(m, m->private, "");
return 0;
}
static int crtc_updates_open(struct inode *inode, struct file *file)
{
return single_open(file, crtc_updates_show, inode->i_private);
}
static ssize_t crtc_updates_write(struct file *file,
const char __user *ubuf,
size_t len, loff_t *offp)
{
struct seq_file *m = file->private_data;
struct intel_crtc *crtc = m->private;
/* May race with an update. Meh. */
memset(&crtc->debug.vbl, 0, sizeof(crtc->debug.vbl));
return len;
}
static const struct file_operations crtc_updates_fops = {
.owner = THIS_MODULE,
.open = crtc_updates_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = crtc_updates_write
};
static void crtc_updates_add(struct drm_crtc *crtc)
{
debugfs_create_file("i915_update_info", 0644, crtc->debugfs_entry,
to_intel_crtc(crtc), &crtc_updates_fops);
}
#else
static void crtc_updates_info(struct seq_file *m,
struct intel_crtc *crtc,
const char *hdr)
{
}
static void crtc_updates_add(struct drm_crtc *crtc)
{
}
#endif
static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
@ -907,6 +1012,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s\n",
yesno(!crtc->cpu_fifo_underrun_disabled),
yesno(!crtc->pch_fifo_underrun_disabled));
crtc_updates_info(m, crtc, "\t");
}
static int i915_display_info(struct seq_file *m, void *unused)
@ -2278,3 +2385,20 @@ int intel_connector_debugfs_add(struct drm_connector *connector)
return 0;
}
/**
* intel_crtc_debugfs_add - add i915 specific crtc debugfs files
* @crtc: pointer to a drm_crtc
*
* Returns 0 on success, negative error codes on error.
*
* Failure to add debugfs entries should generally be ignored.
*/
int intel_crtc_debugfs_add(struct drm_crtc *crtc)
{
if (!crtc->debugfs_entry)
return -ENODEV;
crtc_updates_add(crtc);
return 0;
}

View File

@ -7,14 +7,17 @@
#define __INTEL_DISPLAY_DEBUGFS_H__
struct drm_connector;
struct drm_crtc;
struct drm_i915_private;
#ifdef CONFIG_DEBUG_FS
void intel_display_debugfs_register(struct drm_i915_private *i915);
int intel_connector_debugfs_add(struct drm_connector *connector);
int intel_crtc_debugfs_add(struct drm_crtc *crtc);
#else
static inline void intel_display_debugfs_register(struct drm_i915_private *i915) {}
static inline int intel_connector_debugfs_add(struct drm_connector *connector) { return 0; }
static inline int intel_crtc_debugfs_add(struct drm_crtc *crtc) { return 0; }
#endif
#endif /* __INTEL_DISPLAY_DEBUGFS_H__ */

View File

@ -2184,26 +2184,6 @@ static void __intel_display_power_put(struct drm_i915_private *dev_priv,
mutex_unlock(&power_domains->lock);
}
/**
* intel_display_power_put_unchecked - release an unchecked power domain reference
* @dev_priv: i915 device instance
* @domain: power domain to reference
*
* This function drops the power domain reference obtained by
* intel_display_power_get() and might power down the corresponding hardware
* block right away if this is the last reference.
*
* This function exists only for historical reasons and should be avoided in
* new code, as the correctness of its use cannot be checked. Always use
* intel_display_power_put() instead.
*/
void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain)
{
__intel_display_power_put(dev_priv, domain);
intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm);
}
static void
queue_async_put_domains_work(struct i915_power_domains *power_domains,
intel_wakeref_t wakeref)
@ -2410,8 +2390,85 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
__intel_display_power_put(dev_priv, domain);
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
}
#else
/**
* intel_display_power_put_unchecked - release an unchecked power domain reference
* @dev_priv: i915 device instance
* @domain: power domain to reference
*
* This function drops the power domain reference obtained by
* intel_display_power_get() and might power down the corresponding hardware
* block right away if this is the last reference.
*
* This function is only for the power domain code's internal use to suppress wakeref
* tracking when the correspondig debug kconfig option is disabled, should not
* be used otherwise.
*/
void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain)
{
__intel_display_power_put(dev_priv, domain);
intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm);
}
#endif
void
intel_display_power_get_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
intel_wakeref_t __maybe_unused wf;
drm_WARN_ON(&i915->drm, power_domain_set->mask & BIT_ULL(domain));
wf = intel_display_power_get(i915, domain);
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
power_domain_set->wakerefs[domain] = wf;
#endif
power_domain_set->mask |= BIT_ULL(domain);
}
bool
intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain)
{
intel_wakeref_t wf;
drm_WARN_ON(&i915->drm, power_domain_set->mask & BIT_ULL(domain));
wf = intel_display_power_get_if_enabled(i915, domain);
if (!wf)
return false;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
power_domain_set->wakerefs[domain] = wf;
#endif
power_domain_set->mask |= BIT_ULL(domain);
return true;
}
void
intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
u64 mask)
{
enum intel_display_power_domain domain;
drm_WARN_ON(&i915->drm, mask & ~power_domain_set->mask);
for_each_power_domain(domain, mask) {
intel_wakeref_t __maybe_unused wf = -1;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
wf = fetch_and_zero(&power_domain_set->wakerefs[domain]);
#endif
intel_display_power_put(i915, domain, wf);
power_domain_set->mask &= ~BIT_ULL(domain);
}
}
#define I830_PIPES_POWER_DOMAINS ( \
BIT_ULL(POWER_DOMAIN_PIPE_A) | \
BIT_ULL(POWER_DOMAIN_PIPE_B) | \
@ -5601,12 +5658,16 @@ void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
* resources powered until display HW readout is complete. We drop
* this reference in intel_power_domains_enable().
*/
power_domains->wakeref =
drm_WARN_ON(&i915->drm, power_domains->init_wakeref);
power_domains->init_wakeref =
intel_display_power_get(i915, POWER_DOMAIN_INIT);
/* Disable power support if the user asked so. */
if (!i915->params.disable_power_well)
intel_display_power_get(i915, POWER_DOMAIN_INIT);
if (!i915->params.disable_power_well) {
drm_WARN_ON(&i915->drm, power_domains->disable_wakeref);
i915->power_domains.disable_wakeref = intel_display_power_get(i915,
POWER_DOMAIN_INIT);
}
intel_power_domains_sync_hw(i915);
power_domains->initializing = false;
@ -5626,11 +5687,12 @@ void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
void intel_power_domains_driver_remove(struct drm_i915_private *i915)
{
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&i915->power_domains.wakeref);
fetch_and_zero(&i915->power_domains.init_wakeref);
/* Remove the refcount we took to keep power well support disabled. */
if (!i915->params.disable_power_well)
intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
intel_display_power_put(i915, POWER_DOMAIN_INIT,
fetch_and_zero(&i915->power_domains.disable_wakeref));
intel_display_power_flush_work_sync(i915);
@ -5655,7 +5717,7 @@ void intel_power_domains_driver_remove(struct drm_i915_private *i915)
void intel_power_domains_enable(struct drm_i915_private *i915)
{
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&i915->power_domains.wakeref);
fetch_and_zero(&i915->power_domains.init_wakeref);
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
intel_power_domains_verify_state(i915);
@ -5672,8 +5734,8 @@ void intel_power_domains_disable(struct drm_i915_private *i915)
{
struct i915_power_domains *power_domains = &i915->power_domains;
drm_WARN_ON(&i915->drm, power_domains->wakeref);
power_domains->wakeref =
drm_WARN_ON(&i915->drm, power_domains->init_wakeref);
power_domains->init_wakeref =
intel_display_power_get(i915, POWER_DOMAIN_INIT);
intel_power_domains_verify_state(i915);
@ -5695,7 +5757,7 @@ void intel_power_domains_suspend(struct drm_i915_private *i915,
{
struct i915_power_domains *power_domains = &i915->power_domains;
intel_wakeref_t wakeref __maybe_unused =
fetch_and_zero(&power_domains->wakeref);
fetch_and_zero(&power_domains->init_wakeref);
intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
@ -5719,7 +5781,8 @@ void intel_power_domains_suspend(struct drm_i915_private *i915,
* power wells if power domains must be deinitialized for suspend.
*/
if (!i915->params.disable_power_well)
intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
intel_display_power_put(i915, POWER_DOMAIN_INIT,
fetch_and_zero(&i915->power_domains.disable_wakeref));
intel_display_power_flush_work(i915);
intel_power_domains_verify_state(i915);
@ -5754,8 +5817,8 @@ void intel_power_domains_resume(struct drm_i915_private *i915)
intel_power_domains_init_hw(i915, true);
power_domains->display_core_suspended = false;
} else {
drm_WARN_ON(&i915->drm, power_domains->wakeref);
power_domains->wakeref =
drm_WARN_ON(&i915->drm, power_domains->init_wakeref);
power_domains->init_wakeref =
intel_display_power_get(i915, POWER_DOMAIN_INIT);
}

View File

@ -212,7 +212,8 @@ struct i915_power_domains {
bool display_core_suspended;
int power_well_count;
intel_wakeref_t wakeref;
intel_wakeref_t init_wakeref;
intel_wakeref_t disable_wakeref;
struct mutex lock;
int domain_use_count[POWER_DOMAIN_NUM];
@ -224,6 +225,13 @@ struct i915_power_domains {
struct i915_power_well *power_wells;
};
struct intel_display_power_domain_set {
u64 mask;
#ifdef CONFIG_DRM_I915_DEBUG_RUNTIME_PM
intel_wakeref_t wakerefs[POWER_DOMAIN_NUM];
#endif
};
#define for_each_power_domain(domain, mask) \
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
for_each_if(BIT_ULL(domain) & (mask))
@ -279,8 +287,6 @@ intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
intel_wakeref_t
intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
void __intel_display_power_put_async(struct drm_i915_private *i915,
enum intel_display_power_domain domain,
intel_wakeref_t wakeref);
@ -297,6 +303,9 @@ intel_display_power_put_async(struct drm_i915_private *i915,
__intel_display_power_put_async(i915, domain, wakeref);
}
#else
void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
static inline void
intel_display_power_put(struct drm_i915_private *i915,
enum intel_display_power_domain domain,
@ -314,6 +323,28 @@ intel_display_power_put_async(struct drm_i915_private *i915,
}
#endif
void
intel_display_power_get_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain);
bool
intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
enum intel_display_power_domain domain);
void
intel_display_power_put_mask_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set,
u64 mask);
static inline void
intel_display_power_put_all_in_set(struct drm_i915_private *i915,
struct intel_display_power_domain_set *power_domain_set)
{
intel_display_power_put_mask_in_set(i915, power_domain_set, power_domain_set->mask);
}
enum dbuf_slice {
DBUF_S1,
DBUF_S2,

View File

@ -225,6 +225,17 @@ struct intel_encoder {
const struct drm_connector *audio_connector;
};
struct intel_panel_bl_funcs {
/* Connector and platform specific backlight functions */
int (*setup)(struct intel_connector *connector, enum pipe pipe);
u32 (*get)(struct intel_connector *connector);
void (*set)(const struct drm_connector_state *conn_state, u32 level);
void (*disable)(const struct drm_connector_state *conn_state, u32 level);
void (*enable)(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state, u32 level);
u32 (*hz_to_pwm)(struct intel_connector *connector, u32 hz);
};
struct intel_panel {
struct drm_display_mode *fixed_mode;
struct drm_display_mode *downclock_mode;
@ -251,14 +262,7 @@ struct intel_panel {
struct backlight_device *device;
/* Connector and platform specific backlight functions */
int (*setup)(struct intel_connector *connector, enum pipe pipe);
u32 (*get)(struct intel_connector *connector);
void (*set)(const struct drm_connector_state *conn_state, u32 level);
void (*disable)(const struct drm_connector_state *conn_state);
void (*enable)(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
u32 (*hz_to_pwm)(struct intel_connector *connector, u32 hz);
const struct intel_panel_bl_funcs *funcs;
void (*power)(struct intel_connector *, bool enable);
} backlight;
};
@ -604,6 +608,8 @@ struct intel_plane_state {
u32 planar_slave;
struct drm_intel_sprite_colorkey ckey;
struct drm_rect psr2_sel_fetch_area;
};
struct intel_initial_plane_config {
@ -1047,7 +1053,10 @@ struct intel_crtc_state {
u32 cgm_mode;
};
/* bitmask of visible planes (enum plane_id) */
/* bitmask of logically enabled planes (enum plane_id) */
u8 enabled_planes;
/* bitmask of actually visible planes (enum plane_id) */
u8 active_planes;
u8 nv12_planes;
u8 c8_planes;
@ -1160,7 +1169,7 @@ struct intel_crtc {
/* I915_MODE_FLAG_* */
u8 mode_flags;
unsigned long long enabled_power_domains;
struct intel_display_power_domain_set enabled_power_domains;
struct intel_overlay *overlay;
struct intel_crtc_state *config;
@ -1186,6 +1195,15 @@ struct intel_crtc {
ktime_t start_vbl_time;
int min_vbl, max_vbl;
int scanline_start;
#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
struct {
u64 min;
u64 max;
u64 sum;
unsigned int over;
unsigned int times[17]; /* [1us, 16ms] */
} vbl;
#endif
} debug;
/* scalers available on this crtc */
@ -1375,6 +1393,7 @@ struct intel_dp {
unsigned long last_power_on;
unsigned long last_backlight_off;
ktime_t panel_power_off_time;
intel_wakeref_t vdd_wakeref;
/*
* Pipe whose power sequencer is currently locked into
@ -1444,6 +1463,9 @@ struct intel_dp {
bool rgb_to_ycbcr;
} dfp;
/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
struct pm_qos_request pm_qos;
/* Display stream compression testing */
bool force_dsc_en;
@ -1460,6 +1482,7 @@ enum lspcon_vendor {
struct intel_lspcon {
bool active;
bool hdr_supported;
enum drm_lspcon_mode mode;
enum lspcon_vendor vendor;
};
@ -1476,6 +1499,8 @@ struct intel_digital_port {
/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
enum aux_ch aux_ch;
enum intel_display_power_domain ddi_io_power_domain;
intel_wakeref_t ddi_io_wakeref;
intel_wakeref_t aux_wakeref;
struct mutex tc_lock; /* protects the TypeC port mode */
intel_wakeref_t tc_lock_wakeref;
int tc_link_refcount;
@ -1765,6 +1790,12 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
(1 << INTEL_OUTPUT_EDP));
}
static inline bool
intel_crtc_needs_modeset(const struct intel_crtc_state *crtc_state)
{
return drm_atomic_crtc_needs_modeset(&crtc_state->uapi);
}
static inline void
intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
{
@ -1787,4 +1818,10 @@ static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
return i915_ggtt_offset(state->vma);
}
static inline struct intel_frontbuffer *
to_intel_frontbuffer(struct drm_framebuffer *fb)
{
return fb ? to_intel_framebuffer(fb)->frontbuffer : NULL;
}
#endif /* __INTEL_DISPLAY_TYPES_H__ */

View File

@ -1512,7 +1512,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
* lowest possible wakeup latency and so prevent the cpu from going into
* deep sleep states.
*/
cpu_latency_qos_update_request(&i915->pm_qos, 0);
cpu_latency_qos_update_request(&intel_dp->pm_qos, 0);
intel_dp_check_edp(intel_dp);
@ -1645,7 +1645,7 @@ done:
ret = recv_bytes;
out:
cpu_latency_qos_update_request(&i915->pm_qos, PM_QOS_DEFAULT_VALUE);
cpu_latency_qos_update_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
if (vdd)
edp_panel_vdd_off(intel_dp, false);
@ -1921,6 +1921,9 @@ static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int index)
static void
intel_dp_aux_fini(struct intel_dp *intel_dp)
{
if (cpu_latency_qos_request_active(&intel_dp->pm_qos))
cpu_latency_qos_remove_request(&intel_dp->pm_qos);
kfree(intel_dp->aux.name);
}
@ -1973,6 +1976,7 @@ intel_dp_aux_init(struct intel_dp *intel_dp)
encoder->base.name);
intel_dp->aux.transfer = intel_dp_aux_transfer;
cpu_latency_qos_add_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
}
bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
@ -2312,6 +2316,14 @@ static int intel_dp_dsc_compute_params(struct intel_encoder *encoder,
u8 line_buf_depth;
int ret;
/*
* RC_MODEL_SIZE is currently a constant across all configurations.
*
* FIXME: Look into using sink defined DPCD DP_DSC_RC_BUF_BLK_SIZE and
* DP_DSC_RC_BUF_SIZE for this.
*/
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
ret = intel_dsc_compute_params(encoder, crtc_state);
if (ret)
return ret;
@ -3117,8 +3129,9 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
if (edp_have_panel_vdd(intel_dp))
return need_to_disable;
intel_display_power_get(dev_priv,
intel_aux_power_domain(dig_port));
drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
intel_dp->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,
@ -3211,8 +3224,9 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
if ((pp & PANEL_POWER_ON) == 0)
intel_dp->panel_power_off_time = ktime_get_boottime();
intel_display_power_put_unchecked(dev_priv,
intel_aux_power_domain(dig_port));
intel_display_power_put(dev_priv,
intel_aux_power_domain(dig_port),
fetch_and_zero(&intel_dp->vdd_wakeref));
}
static void edp_panel_vdd_work(struct work_struct *__work)
@ -3364,7 +3378,9 @@ static void edp_panel_off(struct intel_dp *intel_dp)
intel_dp->panel_power_off_time = ktime_get_boottime();
/* We got a reference when we enabled the VDD. */
intel_display_power_put_unchecked(dev_priv, intel_aux_power_domain(dig_port));
intel_display_power_put(dev_priv,
intel_aux_power_domain(dig_port),
fetch_and_zero(&intel_dp->vdd_wakeref));
}
void intel_edp_panel_off(struct intel_dp *intel_dp)
@ -3602,6 +3618,29 @@ void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
enable ? "enable" : "disable");
}
static void
intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 oui[] = { 0x00, 0xaa, 0x01 };
u8 buf[3] = { 0 };
/*
* During driver init, we want to be careful and avoid changing the source OUI if it's
* already set to what we want, so as to avoid clearing any state by accident
*/
if (careful) {
if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0)
drm_err(&i915->drm, "Failed to read source OUI\n");
if (memcmp(oui, buf, sizeof(oui)) == 0)
return;
}
if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0)
drm_err(&i915->drm, "Failed to write source OUI\n");
}
/* If the device supports it, try to set the power state appropriately */
void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
{
@ -3623,6 +3662,10 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
lspcon_resume(dp_to_dig_port(intel_dp));
/* Write the source OUI as early as possible */
if (intel_dp_is_edp(intel_dp))
intel_edp_init_source_oui(intel_dp, false);
/*
* When turning on, we need to retry for 1ms to give the sink
* time to wake up.
@ -5197,6 +5240,12 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
intel_dp_get_dsc_sink_cap(intel_dp);
/*
* If needed, program our source OUI so we can make various Intel-specific AUX services
* available (such as HDR backlight controls)
*/
intel_edp_init_source_oui(intel_dp, true);
return true;
}
@ -7177,6 +7226,8 @@ intel_dp_connector_register(struct drm_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->dev);
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct intel_lspcon *lspcon = &dig_port->lspcon;
int ret;
ret = intel_connector_register(connector);
@ -7190,6 +7241,22 @@ intel_dp_connector_register(struct drm_connector *connector)
ret = drm_dp_aux_register(&intel_dp->aux);
if (!ret)
drm_dp_cec_register_connector(&intel_dp->aux, connector);
if (!intel_bios_is_lspcon_present(i915, dig_port->base.port))
return ret;
/*
* ToDo: Clean this up to handle lspcon init and resume more
* efficiently and streamlined.
*/
if (lspcon_init(dig_port)) {
lspcon_detect_hdr_capability(lspcon);
if (lspcon->hdr_supported)
drm_object_attach_property(&connector->base,
connector->dev->mode_config.hdr_output_metadata_property,
0);
}
return ret;
}
@ -7279,7 +7346,9 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
*/
drm_dbg_kms(&dev_priv->drm,
"VDD left on by BIOS, adjusting state tracking\n");
intel_display_power_get(dev_priv, intel_aux_power_domain(dig_port));
drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
intel_aux_power_domain(dig_port));
edp_panel_vdd_schedule_off(intel_dp);
}
@ -7578,7 +7647,13 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
else if (INTEL_GEN(dev_priv) >= 5)
drm_connector_attach_max_bpc_property(connector, 6, 12);
intel_attach_colorspace_property(connector);
/* Register HDMI colorspace for case of lspcon */
if (intel_bios_is_lspcon_present(dev_priv, port)) {
drm_connector_attach_content_type_property(connector);
intel_attach_hdmi_colorspace_property(connector);
} else {
intel_attach_dp_colorspace_property(connector);
}
if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 11)
drm_object_attach_property(&connector->base,

View File

@ -25,7 +25,60 @@
#include "intel_display_types.h"
#include "intel_dp_aux_backlight.h"
static void set_aux_backlight_enable(struct intel_dp *intel_dp, bool enable)
/*
* DP AUX registers for Intel's proprietary HDR backlight interface. We define
* them here since we'll likely be the only driver to ever use these.
*/
#define INTEL_EDP_HDR_TCON_CAP0 0x340
#define INTEL_EDP_HDR_TCON_CAP1 0x341
# define INTEL_EDP_HDR_TCON_2084_DECODE_CAP BIT(0)
# define INTEL_EDP_HDR_TCON_2020_GAMUT_CAP BIT(1)
# define INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP BIT(2)
# define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP BIT(3)
# define INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP BIT(4)
# define INTEL_EDP_HDR_TCON_OPTIMIZATION_CAP BIT(5)
# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP BIT(6)
# define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_CONVERSION_CAP BIT(7)
#define INTEL_EDP_HDR_TCON_CAP2 0x342
# define INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP BIT(0)
#define INTEL_EDP_HDR_TCON_CAP3 0x343
#define INTEL_EDP_HDR_GETSET_CTRL_PARAMS 0x344
# define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE BIT(0)
# define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE BIT(1)
# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-TGL+ */
# define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE BIT(3)
# define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4)
# define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLE BIT(5)
/* Bit 6 is reserved */
# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLE BIT(7)
#define INTEL_EDP_HDR_CONTENT_LUMINANCE 0x346 /* Pre-TGL+ */
#define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A
#define INTEL_EDP_SDR_LUMINANCE_LEVEL 0x352
#define INTEL_EDP_BRIGHTNESS_NITS_LSB 0x354
#define INTEL_EDP_BRIGHTNESS_NITS_MSB 0x355
#define INTEL_EDP_BRIGHTNESS_DELAY_FRAMES 0x356
#define INTEL_EDP_BRIGHTNESS_PER_FRAME_STEPS 0x357
#define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_0 0x358
# define INTEL_EDP_TCON_USAGE_MASK GENMASK(0, 3)
# define INTEL_EDP_TCON_USAGE_UNKNOWN 0x0
# define INTEL_EDP_TCON_USAGE_DESKTOP 0x1
# define INTEL_EDP_TCON_USAGE_FULL_SCREEN_MEDIA 0x2
# define INTEL_EDP_TCON_USAGE_FULL_SCREEN_GAMING 0x3
# define INTEL_EDP_TCON_POWER_MASK BIT(4)
# define INTEL_EDP_TCON_POWER_DC (0 << 4)
# define INTEL_EDP_TCON_POWER_AC (1 << 4)
# define INTEL_EDP_TCON_OPTIMIZATION_STRENGTH_MASK GENMASK(5, 7)
#define INTEL_EDP_BRIGHTNESS_OPTIMIZATION_1 0x359
/* VESA backlight callbacks */
static void set_vesa_backlight_enable(struct intel_dp *intel_dp, bool enable)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
u8 reg_val = 0;
@ -52,7 +105,7 @@ static void set_aux_backlight_enable(struct intel_dp *intel_dp, bool enable)
}
}
static bool intel_dp_aux_backlight_dpcd_mode(struct intel_connector *connector)
static bool intel_dp_aux_vesa_backlight_dpcd_mode(struct intel_connector *connector)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@ -75,7 +128,7 @@ static bool intel_dp_aux_backlight_dpcd_mode(struct intel_connector *connector)
* Read the current backlight value from DPCD register(s) based
* on if 8-bit(MSB) or 16-bit(MSB and LSB) values are supported
*/
static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@ -86,7 +139,7 @@ static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
* If we're not in DPCD control mode yet, the programmed brightness
* value is meaningless and we should assume max brightness
*/
if (!intel_dp_aux_backlight_dpcd_mode(connector))
if (!intel_dp_aux_vesa_backlight_dpcd_mode(connector))
return connector->panel.backlight.max;
if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
@ -107,7 +160,8 @@ static u32 intel_dp_aux_get_backlight(struct intel_connector *connector)
* 8-bit or 16 bit value (MSB and LSB)
*/
static void
intel_dp_aux_set_backlight(const struct drm_connector_state *conn_state, u32 level)
intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state,
u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
@ -137,7 +191,7 @@ intel_dp_aux_set_backlight(const struct drm_connector_state *conn_state, u32 lev
* - Where P = 2^Pn, where Pn is the value programmed by field 4:0 of the
* EDP_PWMGEN_BIT_COUNT register (DPCD Address 00724h)
*/
static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector)
static bool intel_dp_aux_vesa_set_pwm_freq(struct intel_connector *connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_dp *intel_dp = intel_attached_dp(connector);
@ -173,8 +227,9 @@ static bool intel_dp_aux_set_pwm_freq(struct intel_connector *connector)
return true;
}
static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
static void
intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
@ -214,7 +269,7 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
}
if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_FREQ_AUX_SET_CAP)
if (intel_dp_aux_set_pwm_freq(connector))
if (intel_dp_aux_vesa_set_pwm_freq(connector))
new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE;
if (new_dpcd_buf != dpcd_buf) {
@ -225,18 +280,18 @@ static void intel_dp_aux_enable_backlight(const struct intel_crtc_state *crtc_st
}
}
intel_dp_aux_set_backlight(conn_state,
connector->panel.backlight.level);
set_aux_backlight_enable(intel_dp, true);
intel_dp_aux_vesa_set_backlight(conn_state, level);
set_vesa_backlight_enable(intel_dp, true);
}
static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old_conn_state)
static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state *old_conn_state,
u32 level)
{
set_aux_backlight_enable(enc_to_intel_dp(to_intel_encoder(old_conn_state->best_encoder)),
false);
set_vesa_backlight_enable(enc_to_intel_dp(to_intel_encoder(old_conn_state->best_encoder)),
false);
}
static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector)
static u32 intel_dp_aux_vesa_calc_max_backlight(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_dp *intel_dp = intel_attached_dp(connector);
@ -316,25 +371,25 @@ static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector)
return max_backlight;
}
static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
enum pipe pipe)
static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector,
enum pipe pipe)
{
struct intel_panel *panel = &connector->panel;
panel->backlight.max = intel_dp_aux_calc_max_backlight(connector);
panel->backlight.max = intel_dp_aux_vesa_calc_max_backlight(connector);
if (!panel->backlight.max)
return -ENODEV;
panel->backlight.min = 0;
panel->backlight.level = intel_dp_aux_get_backlight(connector);
panel->backlight.enabled = intel_dp_aux_backlight_dpcd_mode(connector) &&
panel->backlight.level = intel_dp_aux_vesa_get_backlight(connector);
panel->backlight.enabled = intel_dp_aux_vesa_backlight_dpcd_mode(connector) &&
panel->backlight.level != 0;
return 0;
}
static bool
intel_dp_aux_display_control_capable(struct intel_connector *connector)
intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@ -350,6 +405,14 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector)
return false;
}
static const struct intel_panel_bl_funcs intel_dp_vesa_bl_funcs = {
.setup = intel_dp_aux_vesa_setup_backlight,
.enable = intel_dp_aux_vesa_enable_backlight,
.disable = intel_dp_aux_vesa_disable_backlight,
.set = intel_dp_aux_vesa_set_backlight,
.get = intel_dp_aux_vesa_get_backlight,
};
int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
{
struct intel_panel *panel = &intel_connector->panel;
@ -357,7 +420,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
if (i915->params.enable_dpcd_backlight == 0 ||
!intel_dp_aux_display_control_capable(intel_connector))
!intel_dp_aux_supports_vesa_backlight(intel_connector))
return -ENODEV;
/*
@ -379,11 +442,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
return -ENODEV;
}
panel->backlight.setup = intel_dp_aux_setup_backlight;
panel->backlight.enable = intel_dp_aux_enable_backlight;
panel->backlight.disable = intel_dp_aux_disable_backlight;
panel->backlight.set = intel_dp_aux_set_backlight;
panel->backlight.get = intel_dp_aux_get_backlight;
panel->backlight.funcs = &intel_dp_vesa_bl_funcs;
return 0;
}

View File

@ -77,7 +77,7 @@ static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32
}
}
static void dcs_disable_backlight(const struct drm_connector_state *conn_state)
static void dcs_disable_backlight(const struct drm_connector_state *conn_state, u32 level)
{
struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
struct mipi_dsi_device *dsi_device;
@ -111,10 +111,9 @@ static void dcs_disable_backlight(const struct drm_connector_state *conn_state)
}
static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
struct mipi_dsi_device *dsi_device;
enum port port;
@ -142,7 +141,7 @@ static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state,
&cabc, sizeof(cabc));
}
dcs_set_backlight(conn_state, panel->backlight.level);
dcs_set_backlight(conn_state, level);
}
static int dcs_setup_backlight(struct intel_connector *connector,
@ -156,6 +155,14 @@ static int dcs_setup_backlight(struct intel_connector *connector,
return 0;
}
static const struct intel_panel_bl_funcs dcs_bl_funcs = {
.setup = dcs_setup_backlight,
.enable = dcs_enable_backlight,
.disable = dcs_disable_backlight,
.set = dcs_set_backlight,
.get = dcs_get_backlight,
};
int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector)
{
struct drm_device *dev = intel_connector->base.dev;
@ -169,11 +176,7 @@ int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector)
if (drm_WARN_ON(dev, encoder->type != INTEL_OUTPUT_DSI))
return -EINVAL;
panel->backlight.setup = dcs_setup_backlight;
panel->backlight.enable = dcs_enable_backlight;
panel->backlight.disable = dcs_disable_backlight;
panel->backlight.set = dcs_set_backlight;
panel->backlight.get = dcs_get_backlight;
panel->backlight.funcs = &dcs_bl_funcs;
return 0;
}

View File

@ -301,12 +301,8 @@ 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;
/*I915_WRITE(DVOB_SRCDIM,
(adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
(adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
intel_de_write(dev_priv, dvo_srcdim_reg,
(adjusted_mode->crtc_hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) | (adjusted_mode->crtc_vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));
/*I915_WRITE(DVOB, dvo_val);*/
intel_de_write(dev_priv, dvo_reg, dvo_val);
}

View File

@ -742,6 +742,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
cache->fence_id = plane_state->vma->fence->id;
else
cache->fence_id = -1;
cache->psr2_active = crtc_state->has_psr2;
}
static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv)
@ -914,6 +916,16 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
return false;
}
/*
* Tigerlake is not supporting FBC with PSR2.
* Recommendation is to keep this combination disabled
* Bspec: 50422 HSD: 14010260002
*/
if (fbc->state_cache.psr2_active && IS_TIGERLAKE(dev_priv)) {
fbc->no_fbc_reason = "not supported with PSR2";
return false;
}
return true;
}
@ -1433,13 +1445,6 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
if (!HAS_FBC(dev_priv))
return 0;
/*
* Fbc is causing random underruns in CI execution on TGL platforms.
* Disabling the same while the problem is being debugged and analyzed.
*/
if (IS_TIGERLAKE(dev_priv))
return 0;
if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
return 1;

View File

@ -518,10 +518,10 @@ static u32 vlv_infoframes_enabled(struct intel_encoder *encoder,
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP);
}
static void hsw_write_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type,
const void *frame, ssize_t len)
void hsw_write_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type,
const void *frame, ssize_t len)
{
const u32 *data = frame;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@ -555,10 +555,9 @@ static void hsw_write_infoframe(struct intel_encoder *encoder,
intel_de_posting_read(dev_priv, ctl_reg);
}
static void hsw_read_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type,
void *frame, ssize_t len)
void hsw_read_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type, void *frame, ssize_t len)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
@ -2950,21 +2949,12 @@ static void
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_digital_port *dig_port =
hdmi_to_dig_port(intel_hdmi);
intel_attach_force_audio_property(connector);
intel_attach_broadcast_rgb_property(connector);
intel_attach_aspect_ratio_property(connector);
/*
* Attach Colorspace property for Non LSPCON based device
* ToDo: This needs to be extended for LSPCON implementation
* as well. Will be implemented separately.
*/
if (!dig_port->lspcon.active)
intel_attach_colorspace_property(connector);
intel_attach_hdmi_colorspace_property(connector);
drm_connector_attach_content_type_property(connector);
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))

View File

@ -30,11 +30,15 @@
#include "intel_display_types.h"
#include "intel_dp.h"
#include "intel_lspcon.h"
#include "intel_hdmi.h"
/* LSPCON OUI Vendor ID(signatures) */
#define LSPCON_VENDOR_PARADE_OUI 0x001CF8
#define LSPCON_VENDOR_MCA_OUI 0x0060AD
#define DPCD_MCA_LSPCON_HDR_STATUS 0x70003
#define DPCD_PARADE_LSPCON_HDR_STATUS 0x00511
/* AUX addresses to write MCA AVI IF */
#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
@ -104,6 +108,35 @@ static bool lspcon_detect_vendor(struct intel_lspcon *lspcon)
return true;
}
static u32 get_hdr_status_reg(struct intel_lspcon *lspcon)
{
if (lspcon->vendor == LSPCON_VENDOR_MCA)
return DPCD_MCA_LSPCON_HDR_STATUS;
else
return DPCD_PARADE_LSPCON_HDR_STATUS;
}
void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon)
{
struct intel_digital_port *dig_port =
container_of(lspcon, struct intel_digital_port, lspcon);
struct drm_device *dev = dig_port->base.base.dev;
struct intel_dp *dp = lspcon_to_intel_dp(lspcon);
u8 hdr_caps;
int ret;
ret = drm_dp_dpcd_read(&dp->aux, get_hdr_status_reg(lspcon),
&hdr_caps, 1);
if (ret < 0) {
drm_dbg_kms(dev, "HDR capability detection failed\n");
lspcon->hdr_supported = false;
} else if (hdr_caps & 0x1) {
drm_dbg_kms(dev, "LSPCON capable of HDR\n");
lspcon->hdr_supported = true;
}
}
static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
{
enum drm_lspcon_mode current_mode;
@ -418,27 +451,32 @@ void lspcon_write_infoframe(struct intel_encoder *encoder,
unsigned int type,
const void *frame, ssize_t len)
{
bool ret;
bool ret = true;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
/* LSPCON only needs AVI IF */
if (type != HDMI_INFOFRAME_TYPE_AVI)
return;
if (lspcon->vendor == LSPCON_VENDOR_MCA)
ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
frame, len);
else
ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux,
frame, len);
if (!ret) {
DRM_ERROR("Failed to write AVI infoframes\n");
switch (type) {
case HDMI_INFOFRAME_TYPE_AVI:
if (lspcon->vendor == LSPCON_VENDOR_MCA)
ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
frame, len);
else
ret = _lspcon_write_avi_infoframe_parade(&intel_dp->aux,
frame, len);
break;
case HDMI_PACKET_TYPE_GAMUT_METADATA:
drm_dbg_kms(encoder->base.dev, "Update HDR metadata for lspcon\n");
/* It uses the legacy hsw implementation for the same */
hsw_write_infoframe(encoder, crtc_state, type, frame, len);
break;
default:
return;
}
DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
if (!ret) {
DRM_ERROR("Failed to write infoframes\n");
return;
}
}
void lspcon_read_infoframe(struct intel_encoder *encoder,
@ -446,7 +484,10 @@ void lspcon_read_infoframe(struct intel_encoder *encoder,
unsigned int type,
void *frame, ssize_t len)
{
/* FIXME implement this */
/* FIXME implement for AVI Infoframe as well */
if (type == HDMI_PACKET_TYPE_GAMUT_METADATA)
hsw_read_infoframe(encoder, crtc_state, type,
frame, len);
}
void lspcon_set_infoframes(struct intel_encoder *encoder,
@ -491,12 +532,26 @@ void lspcon_set_infoframes(struct intel_encoder *encoder,
else
frame.avi.colorspace = HDMI_COLORSPACE_RGB;
drm_hdmi_avi_infoframe_quant_range(&frame.avi,
conn_state->connector,
adjusted_mode,
crtc_state->limited_color_range ?
HDMI_QUANTIZATION_RANGE_LIMITED :
HDMI_QUANTIZATION_RANGE_FULL);
/* Set the Colorspace as per the HDMI spec */
drm_hdmi_avi_infoframe_colorspace(&frame.avi, conn_state);
/* nonsense combination */
drm_WARN_ON(encoder->base.dev, crtc_state->limited_color_range &&
crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_RGB) {
drm_hdmi_avi_infoframe_quant_range(&frame.avi,
conn_state->connector,
adjusted_mode,
crtc_state->limited_color_range ?
HDMI_QUANTIZATION_RANGE_LIMITED :
HDMI_QUANTIZATION_RANGE_FULL);
} else {
frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
frame.avi.ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
}
drm_hdmi_avi_infoframe_content_type(&frame.avi, conn_state);
ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf));
if (ret < 0) {
@ -508,11 +563,64 @@ void lspcon_set_infoframes(struct intel_encoder *encoder,
buf, ret);
}
static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux)
{
int ret;
u32 val = 0;
u16 reg = LSPCON_MCA_AVI_IF_CTRL;
ret = drm_dp_dpcd_read(aux, reg, &val, 1);
if (ret < 0) {
DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
return false;
}
return val & LSPCON_MCA_AVI_IF_KICKOFF;
}
static bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux)
{
int ret;
u32 val = 0;
u16 reg = LSPCON_PARADE_AVI_IF_CTRL;
ret = drm_dp_dpcd_read(aux, reg, &val, 1);
if (ret < 0) {
DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
return false;
}
return val & LSPCON_PARADE_AVI_IF_KICKOFF;
}
u32 lspcon_infoframes_enabled(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config)
{
/* FIXME actually read this from the hw */
return 0;
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
bool infoframes_enabled;
u32 val = 0;
u32 mask, tmp;
if (lspcon->vendor == LSPCON_VENDOR_MCA)
infoframes_enabled = _lspcon_read_avi_infoframe_enabled_mca(&intel_dp->aux);
else
infoframes_enabled = _lspcon_read_avi_infoframe_enabled_parade(&intel_dp->aux);
if (infoframes_enabled)
val |= intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI);
if (lspcon->hdr_supported) {
tmp = intel_de_read(dev_priv,
HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder));
mask = VIDEO_DIP_ENABLE_GMP_HSW;
if (tmp & mask)
val |= intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA);
}
return val;
}
void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon)
@ -520,7 +628,7 @@ void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon)
lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON);
}
static bool lspcon_init(struct intel_digital_port *dig_port)
bool lspcon_init(struct intel_digital_port *dig_port)
{
struct intel_dp *dp = &dig_port->dp;
struct intel_lspcon *lspcon = &dig_port->lspcon;
@ -550,6 +658,14 @@ static bool lspcon_init(struct intel_digital_port *dig_port)
return true;
}
u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config)
{
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
return dig_port->infoframes_enabled(encoder, pipe_config);
}
void lspcon_resume(struct intel_digital_port *dig_port)
{
struct intel_lspcon *lspcon = &dig_port->lspcon;

View File

@ -15,6 +15,8 @@ struct intel_digital_port;
struct intel_encoder;
struct intel_lspcon;
bool lspcon_init(struct intel_digital_port *dig_port);
void lspcon_detect_hdr_capability(struct intel_lspcon *lspcon);
void lspcon_resume(struct intel_digital_port *dig_port);
void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
void lspcon_write_infoframe(struct intel_encoder *encoder,
@ -31,5 +33,15 @@ void lspcon_set_infoframes(struct intel_encoder *encoder,
const struct drm_connector_state *conn_state);
u32 lspcon_infoframes_enabled(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config);
u32 intel_lspcon_infoframes_enabled(struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config);
void hsw_write_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type,
const void *frame, ssize_t len);
void hsw_read_infoframe(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
unsigned int type,
void *frame, ssize_t len);
#endif /* __INTEL_LSPCON_H__ */

View File

@ -589,7 +589,7 @@ static u32 bxt_get_backlight(struct intel_connector *connector)
BXT_BLC_PWM_DUTY(panel->backlight.controller));
}
static u32 pwm_get_backlight(struct intel_connector *connector)
static u32 ext_pwm_get_backlight(struct intel_connector *connector)
{
struct intel_panel *panel = &connector->panel;
struct pwm_state state;
@ -666,7 +666,7 @@ static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32
BXT_BLC_PWM_DUTY(panel->backlight.controller), level);
}
static void pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level)
static void ext_pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level)
{
struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
@ -684,7 +684,7 @@ intel_panel_actually_set_backlight(const struct drm_connector_state *conn_state,
drm_dbg_kms(&i915->drm, "set backlight PWM = %d\n", level);
level = intel_panel_compute_brightness(connector, level);
panel->backlight.set(conn_state, level);
panel->backlight.funcs->set(conn_state, level);
}
/* set backlight brightness to level in range [0..max], assuming hw min is
@ -726,13 +726,13 @@ void intel_panel_set_backlight_acpi(const struct drm_connector_state *conn_state
mutex_unlock(&dev_priv->backlight_lock);
}
static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state)
static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
u32 tmp;
intel_panel_actually_set_backlight(old_conn_state, 0);
intel_panel_actually_set_backlight(old_conn_state, level);
/*
* Although we don't support or enable CPU PWM with LPT/SPT based
@ -754,13 +754,13 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta
intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
}
static void pch_disable_backlight(const struct drm_connector_state *old_conn_state)
static void pch_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
{
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
u32 tmp;
intel_panel_actually_set_backlight(old_conn_state, 0);
intel_panel_actually_set_backlight(old_conn_state, val);
tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2);
intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
@ -769,44 +769,44 @@ static void pch_disable_backlight(const struct drm_connector_state *old_conn_sta
intel_de_write(dev_priv, BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
}
static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state)
static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
{
intel_panel_actually_set_backlight(old_conn_state, 0);
intel_panel_actually_set_backlight(old_conn_state, val);
}
static void i965_disable_backlight(const struct drm_connector_state *old_conn_state)
static void i965_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
{
struct drm_i915_private *dev_priv = to_i915(old_conn_state->connector->dev);
u32 tmp;
intel_panel_actually_set_backlight(old_conn_state, 0);
intel_panel_actually_set_backlight(old_conn_state, val);
tmp = intel_de_read(dev_priv, BLC_PWM_CTL2);
intel_de_write(dev_priv, BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
}
static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state)
static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
{
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
enum pipe pipe = to_intel_crtc(old_conn_state->crtc)->pipe;
u32 tmp;
intel_panel_actually_set_backlight(old_conn_state, 0);
intel_panel_actually_set_backlight(old_conn_state, val);
tmp = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe));
intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe),
tmp & ~BLM_PWM_ENABLE);
}
static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state)
static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
{
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_panel *panel = &connector->panel;
u32 tmp, val;
u32 tmp;
intel_panel_actually_set_backlight(old_conn_state, 0);
intel_panel_actually_set_backlight(old_conn_state, val);
tmp = intel_de_read(dev_priv,
BXT_BLC_PWM_CTL(panel->backlight.controller));
@ -820,14 +820,14 @@ static void bxt_disable_backlight(const struct drm_connector_state *old_conn_sta
}
}
static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state)
static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
{
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_panel *panel = &connector->panel;
u32 tmp;
intel_panel_actually_set_backlight(old_conn_state, 0);
intel_panel_actually_set_backlight(old_conn_state, val);
tmp = intel_de_read(dev_priv,
BXT_BLC_PWM_CTL(panel->backlight.controller));
@ -835,7 +835,7 @@ static void cnp_disable_backlight(const struct drm_connector_state *old_conn_sta
tmp & ~BXT_BLC_PWM_ENABLE);
}
static void pwm_disable_backlight(const struct drm_connector_state *old_conn_state)
static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct intel_panel *panel = &connector->panel;
@ -870,13 +870,13 @@ void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_st
if (panel->backlight.device)
panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
panel->backlight.enabled = false;
panel->backlight.disable(old_conn_state);
panel->backlight.funcs->disable(old_conn_state, 0);
mutex_unlock(&dev_priv->backlight_lock);
}
static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -923,11 +923,11 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
pch_ctl1 | BLM_PCH_PWM_ENABLE);
/* This won't stick until the above enable. */
intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
intel_panel_actually_set_backlight(conn_state, level);
}
static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -958,7 +958,7 @@ static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
intel_de_write(dev_priv, BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
/* This won't stick until the above enable. */
intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
intel_panel_actually_set_backlight(conn_state, level);
pch_ctl2 = panel->backlight.max << 16;
intel_de_write(dev_priv, BLC_PWM_PCH_CTL2, pch_ctl2);
@ -974,7 +974,7 @@ static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
}
static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -1001,7 +1001,7 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state,
intel_de_posting_read(dev_priv, BLC_PWM_CTL);
/* XXX: combine this into above write? */
intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
intel_panel_actually_set_backlight(conn_state, level);
/*
* Needed to enable backlight on some 855gm models. BLC_HIST_CTL is
@ -1013,7 +1013,7 @@ static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state,
}
static void i965_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -1044,11 +1044,11 @@ static void i965_enable_backlight(const struct intel_crtc_state *crtc_state,
intel_de_posting_read(dev_priv, BLC_PWM_CTL2);
intel_de_write(dev_priv, BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
intel_panel_actually_set_backlight(conn_state, level);
}
static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -1067,7 +1067,7 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state,
intel_de_write(dev_priv, VLV_BLC_PWM_CTL(pipe), ctl);
/* XXX: combine this into above write? */
intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
intel_panel_actually_set_backlight(conn_state, level);
ctl2 = 0;
if (panel->backlight.active_low_pwm)
@ -1079,7 +1079,7 @@ static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state,
}
static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -1118,7 +1118,7 @@ static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state,
BXT_BLC_PWM_FREQ(panel->backlight.controller),
panel->backlight.max);
intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
intel_panel_actually_set_backlight(conn_state, level);
pwm_ctl = 0;
if (panel->backlight.active_low_pwm)
@ -1133,7 +1133,7 @@ static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state,
}
static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -1154,7 +1154,7 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state,
BXT_BLC_PWM_FREQ(panel->backlight.controller),
panel->backlight.max);
intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
intel_panel_actually_set_backlight(conn_state, level);
pwm_ctl = 0;
if (panel->backlight.active_low_pwm)
@ -1168,12 +1168,11 @@ static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state,
pwm_ctl | BXT_BLC_PWM_ENABLE);
}
static void pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
static void ext_pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state, u32 level)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct intel_panel *panel = &connector->panel;
int level = panel->backlight.level;
level = intel_panel_compute_brightness(connector, level);
pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100);
@ -1198,7 +1197,7 @@ static void __intel_panel_enable_backlight(const struct intel_crtc_state *crtc_s
panel->backlight.device->props.max_brightness);
}
panel->backlight.enable(crtc_state, conn_state);
panel->backlight.funcs->enable(crtc_state, conn_state, panel->backlight.level);
panel->backlight.enabled = true;
if (panel->backlight.device)
panel->backlight.device->props.power = FB_BLANK_UNBLANK;
@ -1234,7 +1233,7 @@ static u32 intel_panel_get_backlight(struct intel_connector *connector)
mutex_lock(&dev_priv->backlight_lock);
if (panel->backlight.enabled) {
val = panel->backlight.get(connector);
val = panel->backlight.funcs->get(connector);
val = intel_panel_compute_brightness(connector, val);
}
@ -1567,13 +1566,13 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector)
u16 pwm_freq_hz = get_vbt_pwm_freq(dev_priv);
u32 pwm;
if (!panel->backlight.hz_to_pwm) {
if (!panel->backlight.funcs->hz_to_pwm) {
drm_dbg_kms(&dev_priv->drm,
"backlight frequency conversion not supported\n");
return 0;
}
pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz);
pwm = panel->backlight.funcs->hz_to_pwm(connector, pwm_freq_hz);
if (!pwm) {
drm_dbg_kms(&dev_priv->drm,
"backlight frequency conversion failed\n");
@ -1890,8 +1889,8 @@ cnp_setup_backlight(struct intel_connector *connector, enum pipe unused)
return 0;
}
static int pwm_setup_backlight(struct intel_connector *connector,
enum pipe pipe)
static int ext_pwm_setup_backlight(struct intel_connector *connector,
enum pipe pipe)
{
struct drm_device *dev = connector->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
@ -1981,12 +1980,12 @@ int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
}
/* ensure intel_panel has been initialized first */
if (drm_WARN_ON(&dev_priv->drm, !panel->backlight.setup))
if (drm_WARN_ON(&dev_priv->drm, !panel->backlight.funcs))
return -ENODEV;
/* set level and max in panel struct */
mutex_lock(&dev_priv->backlight_lock);
ret = panel->backlight.setup(intel_connector, pipe);
ret = panel->backlight.funcs->setup(intel_connector, pipe);
mutex_unlock(&dev_priv->backlight_lock);
if (ret) {
@ -2016,6 +2015,86 @@ static void intel_panel_destroy_backlight(struct intel_panel *panel)
panel->backlight.present = false;
}
static const struct intel_panel_bl_funcs bxt_funcs = {
.setup = bxt_setup_backlight,
.enable = bxt_enable_backlight,
.disable = bxt_disable_backlight,
.set = bxt_set_backlight,
.get = bxt_get_backlight,
.hz_to_pwm = bxt_hz_to_pwm,
};
static const struct intel_panel_bl_funcs cnp_funcs = {
.setup = cnp_setup_backlight,
.enable = cnp_enable_backlight,
.disable = cnp_disable_backlight,
.set = bxt_set_backlight,
.get = bxt_get_backlight,
.hz_to_pwm = cnp_hz_to_pwm,
};
static const struct intel_panel_bl_funcs lpt_funcs = {
.setup = lpt_setup_backlight,
.enable = lpt_enable_backlight,
.disable = lpt_disable_backlight,
.set = lpt_set_backlight,
.get = lpt_get_backlight,
.hz_to_pwm = lpt_hz_to_pwm,
};
static const struct intel_panel_bl_funcs spt_funcs = {
.setup = lpt_setup_backlight,
.enable = lpt_enable_backlight,
.disable = lpt_disable_backlight,
.set = lpt_set_backlight,
.get = lpt_get_backlight,
.hz_to_pwm = spt_hz_to_pwm,
};
static const struct intel_panel_bl_funcs pch_funcs = {
.setup = pch_setup_backlight,
.enable = pch_enable_backlight,
.disable = pch_disable_backlight,
.set = pch_set_backlight,
.get = pch_get_backlight,
.hz_to_pwm = pch_hz_to_pwm,
};
static const struct intel_panel_bl_funcs ext_pwm_funcs = {
.setup = ext_pwm_setup_backlight,
.enable = ext_pwm_enable_backlight,
.disable = ext_pwm_disable_backlight,
.set = ext_pwm_set_backlight,
.get = ext_pwm_get_backlight,
};
static const struct intel_panel_bl_funcs vlv_funcs = {
.setup = vlv_setup_backlight,
.enable = vlv_enable_backlight,
.disable = vlv_disable_backlight,
.set = vlv_set_backlight,
.get = vlv_get_backlight,
.hz_to_pwm = vlv_hz_to_pwm,
};
static const struct intel_panel_bl_funcs i965_funcs = {
.setup = i965_setup_backlight,
.enable = i965_enable_backlight,
.disable = i965_disable_backlight,
.set = i9xx_set_backlight,
.get = i9xx_get_backlight,
.hz_to_pwm = i965_hz_to_pwm,
};
static const struct intel_panel_bl_funcs i9xx_funcs = {
.setup = i9xx_setup_backlight,
.enable = i9xx_enable_backlight,
.disable = i9xx_disable_backlight,
.set = i9xx_set_backlight,
.get = i9xx_get_backlight,
.hz_to_pwm = i9xx_hz_to_pwm,
};
/* Set up chip specific backlight functions */
static void
intel_panel_init_backlight_funcs(struct intel_panel *panel)
@ -2033,65 +2112,26 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
return;
if (IS_GEN9_LP(dev_priv)) {
panel->backlight.setup = bxt_setup_backlight;
panel->backlight.enable = bxt_enable_backlight;
panel->backlight.disable = bxt_disable_backlight;
panel->backlight.set = bxt_set_backlight;
panel->backlight.get = bxt_get_backlight;
panel->backlight.hz_to_pwm = bxt_hz_to_pwm;
panel->backlight.funcs = &bxt_funcs;
} else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) {
panel->backlight.setup = cnp_setup_backlight;
panel->backlight.enable = cnp_enable_backlight;
panel->backlight.disable = cnp_disable_backlight;
panel->backlight.set = bxt_set_backlight;
panel->backlight.get = bxt_get_backlight;
panel->backlight.hz_to_pwm = cnp_hz_to_pwm;
panel->backlight.funcs = &cnp_funcs;
} else if (INTEL_PCH_TYPE(dev_priv) >= PCH_LPT) {
panel->backlight.setup = lpt_setup_backlight;
panel->backlight.enable = lpt_enable_backlight;
panel->backlight.disable = lpt_disable_backlight;
panel->backlight.set = lpt_set_backlight;
panel->backlight.get = lpt_get_backlight;
if (HAS_PCH_LPT(dev_priv))
panel->backlight.hz_to_pwm = lpt_hz_to_pwm;
panel->backlight.funcs = &lpt_funcs;
else
panel->backlight.hz_to_pwm = spt_hz_to_pwm;
panel->backlight.funcs = &spt_funcs;
} else if (HAS_PCH_SPLIT(dev_priv)) {
panel->backlight.setup = pch_setup_backlight;
panel->backlight.enable = pch_enable_backlight;
panel->backlight.disable = pch_disable_backlight;
panel->backlight.set = pch_set_backlight;
panel->backlight.get = pch_get_backlight;
panel->backlight.hz_to_pwm = pch_hz_to_pwm;
panel->backlight.funcs = &pch_funcs;
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
panel->backlight.setup = pwm_setup_backlight;
panel->backlight.enable = pwm_enable_backlight;
panel->backlight.disable = pwm_disable_backlight;
panel->backlight.set = pwm_set_backlight;
panel->backlight.get = pwm_get_backlight;
panel->backlight.funcs = &ext_pwm_funcs;
} else {
panel->backlight.setup = vlv_setup_backlight;
panel->backlight.enable = vlv_enable_backlight;
panel->backlight.disable = vlv_disable_backlight;
panel->backlight.set = vlv_set_backlight;
panel->backlight.get = vlv_get_backlight;
panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
panel->backlight.funcs = &vlv_funcs;
}
} else if (IS_GEN(dev_priv, 4)) {
panel->backlight.setup = i965_setup_backlight;
panel->backlight.enable = i965_enable_backlight;
panel->backlight.disable = i965_disable_backlight;
panel->backlight.set = i9xx_set_backlight;
panel->backlight.get = i9xx_get_backlight;
panel->backlight.hz_to_pwm = i965_hz_to_pwm;
panel->backlight.funcs = &i965_funcs;
} else {
panel->backlight.setup = i9xx_setup_backlight;
panel->backlight.enable = i9xx_enable_backlight;
panel->backlight.disable = i9xx_disable_backlight;
panel->backlight.set = i9xx_set_backlight;
panel->backlight.get = i9xx_get_backlight;
panel->backlight.hz_to_pwm = i9xx_hz_to_pwm;
panel->backlight.funcs = &i9xx_funcs;
}
}

View File

@ -1185,6 +1185,7 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
{
struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
enum pipe pipe = plane->pipe;
const struct drm_rect *clip;
u32 val;
if (!crtc_state->enable_psr2_sel_fetch)
@ -1196,16 +1197,20 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
if (!val || plane->id == PLANE_CURSOR)
return;
val = plane_state->uapi.dst.y1 << 16 | plane_state->uapi.dst.x1;
clip = &plane_state->psr2_sel_fetch_area;
val = (clip->y1 + plane_state->uapi.dst.y1) << 16;
val |= plane_state->uapi.dst.x1;
intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_POS(pipe, plane->id), val);
val = plane_state->color_plane[color_plane].y << 16;
/* TODO: consider tiling and auxiliary surfaces */
val = (clip->y1 + plane_state->color_plane[color_plane].y) << 16;
val |= plane_state->color_plane[color_plane].x;
intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_OFFSET(pipe, plane->id),
val);
/* Sizes are 0 based */
val = ((drm_rect_height(&plane_state->uapi.src) >> 16) - 1) << 16;
val = (drm_rect_height(clip) - 1) << 16;
val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1;
intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_SIZE(pipe, plane->id), val);
}
@ -1279,7 +1284,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
new_plane_state, i) {
struct drm_rect temp;
struct drm_rect *sel_fetch_area, temp;
if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc)
continue;
@ -1302,8 +1307,13 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
* For now doing a selective fetch in the whole plane area,
* optimizations will come in the future.
*/
temp.y1 = new_plane_state->uapi.dst.y1;
temp.y2 = new_plane_state->uapi.dst.y2;
sel_fetch_area = &new_plane_state->psr2_sel_fetch_area;
sel_fetch_area->y1 = new_plane_state->uapi.src.y1 >> 16;
sel_fetch_area->y2 = new_plane_state->uapi.src.y2 >> 16;
temp = *sel_fetch_area;
temp.y1 += new_plane_state->uapi.dst.y1;
temp.y2 += new_plane_state->uapi.dst.y2;
clip_area_update(&pipe_clip, &temp);
}

View File

@ -49,6 +49,7 @@
#include "intel_psr.h"
#include "intel_dsi.h"
#include "intel_sprite.h"
#include "i9xx_plane.h"
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs)
@ -61,14 +62,6 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
1000 * adjusted_mode->crtc_htotal);
}
/* FIXME: We should instead only take spinlocks once for the entire update
* instead of once per mmio. */
#if IS_ENABLED(CONFIG_PROVE_LOCKING)
#define VBLANK_EVASION_TIME_US 250
#else
#define VBLANK_EVASION_TIME_US 100
#endif
/**
* intel_pipe_update_start() - start update of a set of display registers
* @new_crtc_state: the new crtc state
@ -187,6 +180,36 @@ irq_disable:
local_irq_disable();
}
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE)
static void dbg_vblank_evade(struct intel_crtc *crtc, ktime_t end)
{
u64 delta = ktime_to_ns(ktime_sub(end, crtc->debug.start_vbl_time));
unsigned int h;
h = ilog2(delta >> 9);
if (h >= ARRAY_SIZE(crtc->debug.vbl.times))
h = ARRAY_SIZE(crtc->debug.vbl.times) - 1;
crtc->debug.vbl.times[h]++;
crtc->debug.vbl.sum += delta;
if (!crtc->debug.vbl.min || delta < crtc->debug.vbl.min)
crtc->debug.vbl.min = delta;
if (delta > crtc->debug.vbl.max)
crtc->debug.vbl.max = delta;
if (delta > 1000 * VBLANK_EVASION_TIME_US) {
drm_dbg_kms(crtc->base.dev,
"Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
pipe_name(crtc->pipe),
div_u64(delta, 1000),
VBLANK_EVASION_TIME_US);
crtc->debug.vbl.over++;
}
}
#else
static void dbg_vblank_evade(struct intel_crtc *crtc, ktime_t end) {}
#endif
/**
* intel_pipe_update_end() - end update of a set of display registers
* @new_crtc_state: the new crtc state
@ -249,15 +272,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
crtc->debug.min_vbl, crtc->debug.max_vbl,
crtc->debug.scanline_start, scanline_end);
}
#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
VBLANK_EVASION_TIME_US)
drm_warn(&dev_priv->drm,
"Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
pipe_name(pipe),
ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
VBLANK_EVASION_TIME_US);
#endif
dbg_vblank_evade(crtc, end_vbl_time);
}
int intel_plane_check_stride(const struct intel_plane_state *plane_state)

View File

@ -17,6 +17,16 @@ struct drm_i915_private;
struct intel_crtc_state;
struct intel_plane_state;
/*
* FIXME: We should instead only take spinlocks once for the entire update
* instead of once per mmio.
*/
#if IS_ENABLED(CONFIG_PROVE_LOCKING)
#define VBLANK_EVASION_TIME_US 250
#else
#define VBLANK_EVASION_TIME_US 100
#endif
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
int usecs);
struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,

View File

@ -262,7 +262,7 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
mask |= BIT(TC_PORT_LEGACY);
/* The sink can be connected only in a single mode. */
if (!drm_WARN_ON(&i915->drm, hweight32(mask) > 1))
if (!drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1))
tc_port_fixup_legacy_flag(dig_port, mask);
return mask;

View File

@ -454,8 +454,6 @@ int intel_dsc_compute_params(struct intel_encoder *encoder,
else if (vdsc_cfg->bits_per_component == 12)
vdsc_cfg->mux_word_size = DSC_MUX_WORD_SIZE_12_BPC;
/* RC_MODEL_SIZE is a constant across all configurations */
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
/* InitialScaleValue is a 6 bit value with 3 fractional bits (U3.3) */
vdsc_cfg->initial_scale_value = (vdsc_cfg->rc_model_size << 3) /
(vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset);
@ -741,7 +739,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state)
/* Populate PICTURE_PARAMETER_SET_9 registers */
pps_val = 0;
pps_val |= DSC_RC_MODEL_SIZE(DSC_RC_MODEL_SIZE_CONST) |
pps_val |= DSC_RC_MODEL_SIZE(vdsc_cfg->rc_model_size) |
DSC_RC_EDGE_FACTOR(DSC_RC_EDGE_FACTOR_CONST);
drm_info(&dev_priv->drm, "PPS9 = 0x%08x\n", pps_val);
if (!is_pipe_dsc(crtc_state)) {

View File

@ -3693,7 +3693,7 @@ static inline int mmio_pm_restore_handler(struct intel_gvt *gvt,
struct drm_i915_private *dev_priv = gvt->gt->i915;
if (gvt->mmio.mmio_attribute[offset >> 2] & F_PM_SAVE)
I915_WRITE(_MMIO(offset), vgpu_vreg(vgpu, offset));
intel_uncore_write(&dev_priv->uncore, _MMIO(offset), vgpu_vreg(vgpu, offset));
return 0;
}

View File

@ -378,308 +378,6 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
return 0;
}
static void gen8_display_interrupt_info(struct seq_file *m)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
enum pipe pipe;
for_each_pipe(dev_priv, pipe) {
enum intel_display_power_domain power_domain;
intel_wakeref_t wakeref;
power_domain = POWER_DOMAIN_PIPE(pipe);
wakeref = intel_display_power_get_if_enabled(dev_priv,
power_domain);
if (!wakeref) {
seq_printf(m, "Pipe %c power disabled\n",
pipe_name(pipe));
continue;
}
seq_printf(m, "Pipe %c IMR:\t%08x\n",
pipe_name(pipe),
I915_READ(GEN8_DE_PIPE_IMR(pipe)));
seq_printf(m, "Pipe %c IIR:\t%08x\n",
pipe_name(pipe),
I915_READ(GEN8_DE_PIPE_IIR(pipe)));
seq_printf(m, "Pipe %c IER:\t%08x\n",
pipe_name(pipe),
I915_READ(GEN8_DE_PIPE_IER(pipe)));
intel_display_power_put(dev_priv, power_domain, wakeref);
}
seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
I915_READ(GEN8_DE_PORT_IMR));
seq_printf(m, "Display Engine port interrupt identity:\t%08x\n",
I915_READ(GEN8_DE_PORT_IIR));
seq_printf(m, "Display Engine port interrupt enable:\t%08x\n",
I915_READ(GEN8_DE_PORT_IER));
seq_printf(m, "Display Engine misc interrupt mask:\t%08x\n",
I915_READ(GEN8_DE_MISC_IMR));
seq_printf(m, "Display Engine misc interrupt identity:\t%08x\n",
I915_READ(GEN8_DE_MISC_IIR));
seq_printf(m, "Display Engine misc interrupt enable:\t%08x\n",
I915_READ(GEN8_DE_MISC_IER));
seq_printf(m, "PCU interrupt mask:\t%08x\n",
I915_READ(GEN8_PCU_IMR));
seq_printf(m, "PCU interrupt identity:\t%08x\n",
I915_READ(GEN8_PCU_IIR));
seq_printf(m, "PCU interrupt enable:\t%08x\n",
I915_READ(GEN8_PCU_IER));
}
static int i915_interrupt_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_engine_cs *engine;
intel_wakeref_t wakeref;
int i, pipe;
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
if (IS_CHERRYVIEW(dev_priv)) {
intel_wakeref_t pref;
seq_printf(m, "Master Interrupt Control:\t%08x\n",
I915_READ(GEN8_MASTER_IRQ));
seq_printf(m, "Display IER:\t%08x\n",
I915_READ(VLV_IER));
seq_printf(m, "Display IIR:\t%08x\n",
I915_READ(VLV_IIR));
seq_printf(m, "Display IIR_RW:\t%08x\n",
I915_READ(VLV_IIR_RW));
seq_printf(m, "Display IMR:\t%08x\n",
I915_READ(VLV_IMR));
for_each_pipe(dev_priv, pipe) {
enum intel_display_power_domain power_domain;
power_domain = POWER_DOMAIN_PIPE(pipe);
pref = intel_display_power_get_if_enabled(dev_priv,
power_domain);
if (!pref) {
seq_printf(m, "Pipe %c power disabled\n",
pipe_name(pipe));
continue;
}
seq_printf(m, "Pipe %c stat:\t%08x\n",
pipe_name(pipe),
I915_READ(PIPESTAT(pipe)));
intel_display_power_put(dev_priv, power_domain, pref);
}
pref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
seq_printf(m, "Port hotplug:\t%08x\n",
I915_READ(PORT_HOTPLUG_EN));
seq_printf(m, "DPFLIPSTAT:\t%08x\n",
I915_READ(VLV_DPFLIPSTAT));
seq_printf(m, "DPINVGTT:\t%08x\n",
I915_READ(DPINVGTT));
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, pref);
for (i = 0; i < 4; i++) {
seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
i, I915_READ(GEN8_GT_IMR(i)));
seq_printf(m, "GT Interrupt IIR %d:\t%08x\n",
i, I915_READ(GEN8_GT_IIR(i)));
seq_printf(m, "GT Interrupt IER %d:\t%08x\n",
i, I915_READ(GEN8_GT_IER(i)));
}
seq_printf(m, "PCU interrupt mask:\t%08x\n",
I915_READ(GEN8_PCU_IMR));
seq_printf(m, "PCU interrupt identity:\t%08x\n",
I915_READ(GEN8_PCU_IIR));
seq_printf(m, "PCU interrupt enable:\t%08x\n",
I915_READ(GEN8_PCU_IER));
} else if (INTEL_GEN(dev_priv) >= 11) {
if (HAS_MASTER_UNIT_IRQ(dev_priv))
seq_printf(m, "Master Unit Interrupt Control: %08x\n",
I915_READ(DG1_MSTR_UNIT_INTR));
seq_printf(m, "Master Interrupt Control: %08x\n",
I915_READ(GEN11_GFX_MSTR_IRQ));
seq_printf(m, "Render/Copy Intr Enable: %08x\n",
I915_READ(GEN11_RENDER_COPY_INTR_ENABLE));
seq_printf(m, "VCS/VECS Intr Enable: %08x\n",
I915_READ(GEN11_VCS_VECS_INTR_ENABLE));
seq_printf(m, "GUC/SG Intr Enable:\t %08x\n",
I915_READ(GEN11_GUC_SG_INTR_ENABLE));
seq_printf(m, "GPM/WGBOXPERF Intr Enable: %08x\n",
I915_READ(GEN11_GPM_WGBOXPERF_INTR_ENABLE));
seq_printf(m, "Crypto Intr Enable:\t %08x\n",
I915_READ(GEN11_CRYPTO_RSVD_INTR_ENABLE));
seq_printf(m, "GUnit/CSME Intr Enable:\t %08x\n",
I915_READ(GEN11_GUNIT_CSME_INTR_ENABLE));
seq_printf(m, "Display Interrupt Control:\t%08x\n",
I915_READ(GEN11_DISPLAY_INT_CTL));
gen8_display_interrupt_info(m);
} else if (INTEL_GEN(dev_priv) >= 8) {
seq_printf(m, "Master Interrupt Control:\t%08x\n",
I915_READ(GEN8_MASTER_IRQ));
for (i = 0; i < 4; i++) {
seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
i, I915_READ(GEN8_GT_IMR(i)));
seq_printf(m, "GT Interrupt IIR %d:\t%08x\n",
i, I915_READ(GEN8_GT_IIR(i)));
seq_printf(m, "GT Interrupt IER %d:\t%08x\n",
i, I915_READ(GEN8_GT_IER(i)));
}
gen8_display_interrupt_info(m);
} else if (IS_VALLEYVIEW(dev_priv)) {
intel_wakeref_t pref;
seq_printf(m, "Display IER:\t%08x\n",
I915_READ(VLV_IER));
seq_printf(m, "Display IIR:\t%08x\n",
I915_READ(VLV_IIR));
seq_printf(m, "Display IIR_RW:\t%08x\n",
I915_READ(VLV_IIR_RW));
seq_printf(m, "Display IMR:\t%08x\n",
I915_READ(VLV_IMR));
for_each_pipe(dev_priv, pipe) {
enum intel_display_power_domain power_domain;
power_domain = POWER_DOMAIN_PIPE(pipe);
pref = intel_display_power_get_if_enabled(dev_priv,
power_domain);
if (!pref) {
seq_printf(m, "Pipe %c power disabled\n",
pipe_name(pipe));
continue;
}
seq_printf(m, "Pipe %c stat:\t%08x\n",
pipe_name(pipe),
I915_READ(PIPESTAT(pipe)));
intel_display_power_put(dev_priv, power_domain, pref);
}
seq_printf(m, "Master IER:\t%08x\n",
I915_READ(VLV_MASTER_IER));
seq_printf(m, "Render IER:\t%08x\n",
I915_READ(GTIER));
seq_printf(m, "Render IIR:\t%08x\n",
I915_READ(GTIIR));
seq_printf(m, "Render IMR:\t%08x\n",
I915_READ(GTIMR));
seq_printf(m, "PM IER:\t\t%08x\n",
I915_READ(GEN6_PMIER));
seq_printf(m, "PM IIR:\t\t%08x\n",
I915_READ(GEN6_PMIIR));
seq_printf(m, "PM IMR:\t\t%08x\n",
I915_READ(GEN6_PMIMR));
pref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
seq_printf(m, "Port hotplug:\t%08x\n",
I915_READ(PORT_HOTPLUG_EN));
seq_printf(m, "DPFLIPSTAT:\t%08x\n",
I915_READ(VLV_DPFLIPSTAT));
seq_printf(m, "DPINVGTT:\t%08x\n",
I915_READ(DPINVGTT));
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, pref);
} else if (!HAS_PCH_SPLIT(dev_priv)) {
seq_printf(m, "Interrupt enable: %08x\n",
I915_READ(GEN2_IER));
seq_printf(m, "Interrupt identity: %08x\n",
I915_READ(GEN2_IIR));
seq_printf(m, "Interrupt mask: %08x\n",
I915_READ(GEN2_IMR));
for_each_pipe(dev_priv, pipe)
seq_printf(m, "Pipe %c stat: %08x\n",
pipe_name(pipe),
I915_READ(PIPESTAT(pipe)));
} else {
seq_printf(m, "North Display Interrupt enable: %08x\n",
I915_READ(DEIER));
seq_printf(m, "North Display Interrupt identity: %08x\n",
I915_READ(DEIIR));
seq_printf(m, "North Display Interrupt mask: %08x\n",
I915_READ(DEIMR));
seq_printf(m, "South Display Interrupt enable: %08x\n",
I915_READ(SDEIER));
seq_printf(m, "South Display Interrupt identity: %08x\n",
I915_READ(SDEIIR));
seq_printf(m, "South Display Interrupt mask: %08x\n",
I915_READ(SDEIMR));
seq_printf(m, "Graphics Interrupt enable: %08x\n",
I915_READ(GTIER));
seq_printf(m, "Graphics Interrupt identity: %08x\n",
I915_READ(GTIIR));
seq_printf(m, "Graphics Interrupt mask: %08x\n",
I915_READ(GTIMR));
}
if (INTEL_GEN(dev_priv) >= 11) {
seq_printf(m, "RCS Intr Mask:\t %08x\n",
I915_READ(GEN11_RCS0_RSVD_INTR_MASK));
seq_printf(m, "BCS Intr Mask:\t %08x\n",
I915_READ(GEN11_BCS_RSVD_INTR_MASK));
seq_printf(m, "VCS0/VCS1 Intr Mask:\t %08x\n",
I915_READ(GEN11_VCS0_VCS1_INTR_MASK));
seq_printf(m, "VCS2/VCS3 Intr Mask:\t %08x\n",
I915_READ(GEN11_VCS2_VCS3_INTR_MASK));
seq_printf(m, "VECS0/VECS1 Intr Mask:\t %08x\n",
I915_READ(GEN11_VECS0_VECS1_INTR_MASK));
seq_printf(m, "GUC/SG Intr Mask:\t %08x\n",
I915_READ(GEN11_GUC_SG_INTR_MASK));
seq_printf(m, "GPM/WGBOXPERF Intr Mask: %08x\n",
I915_READ(GEN11_GPM_WGBOXPERF_INTR_MASK));
seq_printf(m, "Crypto Intr Mask:\t %08x\n",
I915_READ(GEN11_CRYPTO_RSVD_INTR_MASK));
seq_printf(m, "Gunit/CSME Intr Mask:\t %08x\n",
I915_READ(GEN11_GUNIT_CSME_INTR_MASK));
} else if (INTEL_GEN(dev_priv) >= 6) {
for_each_uabi_engine(engine, dev_priv) {
seq_printf(m,
"Graphics Interrupt mask (%s): %08x\n",
engine->name, ENGINE_READ(engine, RING_IMR));
}
}
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
return 0;
}
static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
unsigned int i;
seq_printf(m, "Total fences = %d\n", i915->ggtt.num_fences);
rcu_read_lock();
for (i = 0; i < i915->ggtt.num_fences; i++) {
struct i915_fence_reg *reg = &i915->ggtt.fence_regs[i];
struct i915_vma *vma = reg->vma;
seq_printf(m, "Fence %d, pin count = %d, object = ",
i, atomic_read(&reg->pin_count));
if (!vma)
seq_puts(m, "unused");
else
i915_debugfs_describe_obj(m, vma->obj);
seq_putc(m, '\n');
}
rcu_read_unlock();
return 0;
}
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
static ssize_t gpu_state_read(struct file *file, char __user *ubuf,
size_t count, loff_t *pos)
@ -802,7 +500,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
u32 rpmodectl, freq_sts;
rpmodectl = I915_READ(GEN6_RP_CONTROL);
rpmodectl = intel_uncore_read(&dev_priv->uncore, GEN6_RP_CONTROL);
seq_printf(m, "Video Turbo Mode: %s\n",
yesno(rpmodectl & GEN6_RP_MEDIA_TURBO));
seq_printf(m, "HW control enabled: %s\n",
@ -847,19 +545,19 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
u32 pm_ier, pm_imr, pm_isr, pm_iir, pm_mask;
int max_freq;
rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
rp_state_limits = intel_uncore_read(&dev_priv->uncore, GEN6_RP_STATE_LIMITS);
if (IS_GEN9_LP(dev_priv)) {
rp_state_cap = I915_READ(BXT_RP_STATE_CAP);
gt_perf_status = I915_READ(BXT_GT_PERF_STATUS);
rp_state_cap = intel_uncore_read(&dev_priv->uncore, BXT_RP_STATE_CAP);
gt_perf_status = intel_uncore_read(&dev_priv->uncore, BXT_GT_PERF_STATUS);
} else {
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
rp_state_cap = intel_uncore_read(&dev_priv->uncore, GEN6_RP_STATE_CAP);
gt_perf_status = intel_uncore_read(&dev_priv->uncore, GEN6_GT_PERF_STATUS);
}
/* RPSTAT1 is in the GT power well */
intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);
reqf = I915_READ(GEN6_RPNSWREQ);
reqf = intel_uncore_read(&dev_priv->uncore, GEN6_RPNSWREQ);
if (INTEL_GEN(dev_priv) >= 9)
reqf >>= 23;
else {
@ -871,24 +569,24 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
}
reqf = intel_gpu_freq(rps, reqf);
rpmodectl = I915_READ(GEN6_RP_CONTROL);
rpinclimit = I915_READ(GEN6_RP_UP_THRESHOLD);
rpdeclimit = I915_READ(GEN6_RP_DOWN_THRESHOLD);
rpmodectl = intel_uncore_read(&dev_priv->uncore, GEN6_RP_CONTROL);
rpinclimit = intel_uncore_read(&dev_priv->uncore, GEN6_RP_UP_THRESHOLD);
rpdeclimit = intel_uncore_read(&dev_priv->uncore, GEN6_RP_DOWN_THRESHOLD);
rpstat = I915_READ(GEN6_RPSTAT1);
rpupei = I915_READ(GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK;
rpcurup = I915_READ(GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK;
rpprevup = I915_READ(GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK;
rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
rpcurdown = I915_READ(GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
rpprevdown = I915_READ(GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
rpstat = intel_uncore_read(&dev_priv->uncore, GEN6_RPSTAT1);
rpupei = intel_uncore_read(&dev_priv->uncore, GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK;
rpcurup = intel_uncore_read(&dev_priv->uncore, GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK;
rpprevup = intel_uncore_read(&dev_priv->uncore, GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK;
rpdownei = intel_uncore_read(&dev_priv->uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
rpcurdown = intel_uncore_read(&dev_priv->uncore, GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
rpprevdown = intel_uncore_read(&dev_priv->uncore, GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
cagf = intel_rps_read_actual_frequency(rps);
intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
if (INTEL_GEN(dev_priv) >= 11) {
pm_ier = I915_READ(GEN11_GPM_WGBOXPERF_INTR_ENABLE);
pm_imr = I915_READ(GEN11_GPM_WGBOXPERF_INTR_MASK);
pm_ier = intel_uncore_read(&dev_priv->uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE);
pm_imr = intel_uncore_read(&dev_priv->uncore, GEN11_GPM_WGBOXPERF_INTR_MASK);
/*
* The equivalent to the PM ISR & IIR cannot be read
* without affecting the current state of the system
@ -896,17 +594,17 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
pm_isr = 0;
pm_iir = 0;
} else if (INTEL_GEN(dev_priv) >= 8) {
pm_ier = I915_READ(GEN8_GT_IER(2));
pm_imr = I915_READ(GEN8_GT_IMR(2));
pm_isr = I915_READ(GEN8_GT_ISR(2));
pm_iir = I915_READ(GEN8_GT_IIR(2));
pm_ier = intel_uncore_read(&dev_priv->uncore, GEN8_GT_IER(2));
pm_imr = intel_uncore_read(&dev_priv->uncore, GEN8_GT_IMR(2));
pm_isr = intel_uncore_read(&dev_priv->uncore, GEN8_GT_ISR(2));
pm_iir = intel_uncore_read(&dev_priv->uncore, GEN8_GT_IIR(2));
} else {
pm_ier = I915_READ(GEN6_PMIER);
pm_imr = I915_READ(GEN6_PMIMR);
pm_isr = I915_READ(GEN6_PMISR);
pm_iir = I915_READ(GEN6_PMIIR);
pm_ier = intel_uncore_read(&dev_priv->uncore, GEN6_PMIER);
pm_imr = intel_uncore_read(&dev_priv->uncore, GEN6_PMIMR);
pm_isr = intel_uncore_read(&dev_priv->uncore, GEN6_PMISR);
pm_iir = intel_uncore_read(&dev_priv->uncore, GEN6_PMIIR);
}
pm_mask = I915_READ(GEN6_PMINTRMSK);
pm_mask = intel_uncore_read(&dev_priv->uncore, GEN6_PMINTRMSK);
seq_printf(m, "Video Turbo Mode: %s\n",
yesno(rpmodectl & GEN6_RP_MEDIA_TURBO));
@ -1011,111 +709,6 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
return 0;
}
static int i915_ring_freq_table(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
struct intel_rps *rps = &dev_priv->gt.rps;
unsigned int max_gpu_freq, min_gpu_freq;
intel_wakeref_t wakeref;
int gpu_freq, ia_freq;
if (!HAS_LLC(dev_priv))
return -ENODEV;
min_gpu_freq = rps->min_freq;
max_gpu_freq = rps->max_freq;
if (IS_GEN9_BC(dev_priv) || INTEL_GEN(dev_priv) >= 10) {
/* Convert GT frequency to 50 HZ units */
min_gpu_freq /= GEN9_FREQ_SCALER;
max_gpu_freq /= GEN9_FREQ_SCALER;
}
seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n");
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
for (gpu_freq = min_gpu_freq; gpu_freq <= max_gpu_freq; gpu_freq++) {
ia_freq = gpu_freq;
sandybridge_pcode_read(dev_priv,
GEN6_PCODE_READ_MIN_FREQ_TABLE,
&ia_freq, NULL);
seq_printf(m, "%d\t\t%d\t\t\t\t%d\n",
intel_gpu_freq(rps,
(gpu_freq *
(IS_GEN9_BC(dev_priv) ||
INTEL_GEN(dev_priv) >= 10 ?
GEN9_FREQ_SCALER : 1))),
((ia_freq >> 0) & 0xff) * 100,
((ia_freq >> 8) & 0xff) * 100);
}
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
return 0;
}
static void describe_ctx_ring(struct seq_file *m, struct intel_ring *ring)
{
seq_printf(m, " (ringbuffer, space: %d, head: %u, tail: %u, emit: %u)",
ring->space, ring->head, ring->tail, ring->emit);
}
static int i915_context_status(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
struct i915_gem_context *ctx, *cn;
spin_lock(&i915->gem.contexts.lock);
list_for_each_entry_safe(ctx, cn, &i915->gem.contexts.list, link) {
struct i915_gem_engines_iter it;
struct intel_context *ce;
if (!kref_get_unless_zero(&ctx->ref))
continue;
spin_unlock(&i915->gem.contexts.lock);
seq_puts(m, "HW context ");
if (ctx->pid) {
struct task_struct *task;
task = get_pid_task(ctx->pid, PIDTYPE_PID);
if (task) {
seq_printf(m, "(%s [%d]) ",
task->comm, task->pid);
put_task_struct(task);
}
} else if (IS_ERR(ctx->file_priv)) {
seq_puts(m, "(deleted) ");
} else {
seq_puts(m, "(kernel) ");
}
seq_putc(m, ctx->remap_slice ? 'R' : 'r');
seq_putc(m, '\n');
for_each_gem_engine(ce,
i915_gem_context_lock_engines(ctx), it) {
if (intel_context_pin_if_active(ce)) {
seq_printf(m, "%s: ", ce->engine->name);
if (ce->state)
i915_debugfs_describe_obj(m, ce->state->obj);
describe_ctx_ring(m, ce->ring);
seq_putc(m, '\n');
intel_context_unpin(ce);
}
}
i915_gem_context_unlock_engines(ctx);
seq_putc(m, '\n');
spin_lock(&i915->gem.contexts.lock);
list_safe_reset_next(ctx, cn, link);
i915_gem_context_put(ctx);
}
spin_unlock(&i915->gem.contexts.lock);
return 0;
}
static const char *swizzle_string(unsigned swizzle)
{
switch (swizzle) {
@ -1193,20 +786,6 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
return 0;
}
static const char *rps_power_to_str(unsigned int power)
{
static const char * const strings[] = {
[LOW_POWER] = "low power",
[BETWEEN] = "mixed",
[HIGH_POWER] = "high power",
};
if (power >= ARRAY_SIZE(strings) || !strings[power])
return "unknown";
return strings[power];
}
static int i915_rps_boost_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
@ -1233,41 +812,6 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
seq_printf(m, "Wait boosts: %d\n", atomic_read(&rps->boosts));
if (INTEL_GEN(dev_priv) >= 6 && intel_rps_is_active(rps)) {
u32 rpup, rpupei;
u32 rpdown, rpdownei;
intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);
rpup = I915_READ_FW(GEN6_RP_CUR_UP) & GEN6_RP_EI_MASK;
rpupei = I915_READ_FW(GEN6_RP_CUR_UP_EI) & GEN6_RP_EI_MASK;
rpdown = I915_READ_FW(GEN6_RP_CUR_DOWN) & GEN6_RP_EI_MASK;
rpdownei = I915_READ_FW(GEN6_RP_CUR_DOWN_EI) & GEN6_RP_EI_MASK;
intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
seq_printf(m, "\nRPS Autotuning (current \"%s\" window):\n",
rps_power_to_str(rps->power.mode));
seq_printf(m, " Avg. up: %d%% [above threshold? %d%%]\n",
rpup && rpupei ? 100 * rpup / rpupei : 0,
rps->power.up_threshold);
seq_printf(m, " Avg. down: %d%% [below threshold? %d%%]\n",
rpdown && rpdownei ? 100 * rpdown / rpdownei : 0,
rps->power.down_threshold);
} else {
seq_puts(m, "\nRPS Autotuning inactive\n");
}
return 0;
}
static int i915_llc(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
const bool edram = INTEL_GEN(dev_priv) > 8;
seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(dev_priv)));
seq_printf(m, "%s: %uMB\n", edram ? "eDRAM" : "eLLC",
dev_priv->edram_size_mb);
return 0;
}
@ -1280,7 +824,7 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
seq_puts(m, "Runtime power management not supported\n");
seq_printf(m, "Runtime power status: %s\n",
enableddisabled(!dev_priv->power_domains.wakeref));
enableddisabled(!dev_priv->power_domains.init_wakeref));
seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->gt.awake));
seq_printf(m, "IRQs disabled: %s\n",
@ -1328,16 +872,6 @@ static int i915_engine_info(struct seq_file *m, void *unused)
return 0;
}
static int i915_shrinker_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
seq_printf(m, "seeks = %d\n", i915->mm.shrinker.seeks);
seq_printf(m, "batch = %lu\n", i915->mm.shrinker.batch);
return 0;
}
static int i915_wa_registers(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
@ -1529,55 +1063,6 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_drop_caches_fops,
i915_drop_caches_get, i915_drop_caches_set,
"0x%08llx\n");
static int
i915_cache_sharing_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
intel_wakeref_t wakeref;
u32 snpcr = 0;
if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
return -ENODEV;
with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
return 0;
}
static int
i915_cache_sharing_set(void *data, u64 val)
{
struct drm_i915_private *dev_priv = data;
intel_wakeref_t wakeref;
if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
return -ENODEV;
if (val > 3)
return -EINVAL;
drm_dbg(&dev_priv->drm,
"Manually setting uncore sharing to %llu\n", val);
with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref) {
u32 snpcr;
/* Update the cache sharing policy here as well */
snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
snpcr &= ~GEN6_MBC_SNPCR_MASK;
snpcr |= val << GEN6_MBC_SNPCR_SHIFT;
I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
}
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops,
i915_cache_sharing_get, i915_cache_sharing_set,
"%llu\n");
static int i915_sseu_status(struct seq_file *m, void *unused)
{
struct drm_i915_private *i915 = node_to_i915(m->private);
@ -1621,16 +1106,10 @@ static const struct file_operations i915_forcewake_fops = {
static const struct drm_info_list i915_debugfs_list[] = {
{"i915_capabilities", i915_capabilities, 0},
{"i915_gem_objects", i915_gem_object_info, 0},
{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
{"i915_gem_interrupt", i915_interrupt_info, 0},
{"i915_frequency_info", i915_frequency_info, 0},
{"i915_ring_freq_table", i915_ring_freq_table, 0},
{"i915_context_status", i915_context_status, 0},
{"i915_swizzle_info", i915_swizzle_info, 0},
{"i915_llc", i915_llc, 0},
{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
{"i915_engine_info", i915_engine_info, 0},
{"i915_shrinker_info", i915_shrinker_info, 0},
{"i915_wa_registers", i915_wa_registers, 0},
{"i915_sseu_status", i915_sseu_status, 0},
{"i915_rps_boost_info", i915_rps_boost_info, 0},
@ -1643,7 +1122,6 @@ static const struct i915_debugfs_files {
} i915_debugfs_files[] = {
{"i915_perf_noa_delay", &i915_perf_noa_delay_fops},
{"i915_wedged", &i915_wedged_fops},
{"i915_cache_sharing", &i915_cache_sharing_fops},
{"i915_gem_drop_caches", &i915_drop_caches_fops},
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
{"i915_error_state", &i915_error_state_fops},

View File

@ -578,8 +578,6 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
pci_set_master(pdev);
cpu_latency_qos_add_request(&dev_priv->pm_qos, PM_QOS_DEFAULT_VALUE);
intel_gt_init_workarounds(dev_priv);
/* On the 945G/GM, the chipset reports the MSI capability on the
@ -626,7 +624,6 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv)
err_msi:
if (pdev->msi_enabled)
pci_disable_msi(pdev);
cpu_latency_qos_remove_request(&dev_priv->pm_qos);
err_mem_regions:
intel_memory_regions_driver_release(dev_priv);
err_ggtt:
@ -648,8 +645,6 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
if (pdev->msi_enabled)
pci_disable_msi(pdev);
cpu_latency_qos_remove_request(&dev_priv->pm_qos);
}
/**
@ -738,6 +733,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
* events.
*/
drm_kms_helper_poll_fini(&dev_priv->drm);
drm_atomic_helper_shutdown(&dev_priv->drm);
intel_gt_driver_unregister(&dev_priv->gt);
acpi_video_unregister();
@ -940,8 +936,6 @@ void i915_driver_remove(struct drm_i915_private *i915)
i915_gem_suspend(i915);
drm_atomic_helper_shutdown(&i915->drm);
intel_gvt_driver_remove(i915);
intel_modeset_driver_remove(i915);

View File

@ -416,6 +416,7 @@ struct intel_fbc {
u16 gen9_wa_cfb_stride;
u16 interval;
s8 fence_id;
bool psr2_active;
} state_cache;
/*
@ -891,9 +892,6 @@ struct drm_i915_private {
bool display_irqs_enabled;
/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
struct pm_qos_request pm_qos;
/* Sideband mailbox protection */
struct mutex sb_lock;
struct pm_qos_request sb_qos;
@ -1970,43 +1968,6 @@ mkwrite_device_info(struct drm_i915_private *dev_priv)
int i915_reg_read_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
#define __I915_REG_OP(op__, dev_priv__, ...) \
intel_uncore_##op__(&(dev_priv__)->uncore, __VA_ARGS__)
#define I915_READ(reg__) __I915_REG_OP(read, dev_priv, (reg__))
#define I915_WRITE(reg__, val__) __I915_REG_OP(write, dev_priv, (reg__), (val__))
#define POSTING_READ(reg__) __I915_REG_OP(posting_read, dev_priv, (reg__))
/* These are untraced mmio-accessors that are only valid to be used inside
* critical sections, such as inside IRQ handlers, where forcewake is explicitly
* controlled.
*
* Think twice, and think again, before using these.
*
* As an example, these accessors can possibly be used between:
*
* spin_lock_irq(&dev_priv->uncore.lock);
* intel_uncore_forcewake_get__locked();
*
* and
*
* intel_uncore_forcewake_put__locked();
* spin_unlock_irq(&dev_priv->uncore.lock);
*
*
* Note: some registers may not need forcewake held, so
* intel_uncore_forcewake_{get,put} can be omitted, see
* intel_uncore_forcewake_for_reg().
*
* Certain architectures will die if the same cacheline is concurrently accessed
* by different clients (e.g. on Ivybridge). Access to registers should
* therefore generally be serialised, by either the dev_priv->uncore.lock or
* a more localised lock guarding all access to that bank of registers.
*/
#define I915_READ_FW(reg__) __I915_REG_OP(read_fw, dev_priv, (reg__))
#define I915_WRITE_FW(reg__, val__) __I915_REG_OP(write_fw, dev_priv, (reg__), (val__))
/* i915_mm.c */
int remap_io_mapping(struct vm_area_struct *vma,
unsigned long addr, unsigned long pfn, unsigned long size,

File diff suppressed because it is too large Load Diff

View File

@ -4352,6 +4352,7 @@ enum {
#define VRR_CTL_IGN_MAX_SHIFT REG_BIT(30)
#define VRR_CTL_FLIP_LINE_EN REG_BIT(29)
#define VRR_CTL_LINE_COUNT_MASK REG_GENMASK(10, 3)
#define VRR_CTL_LINE_COUNT(x) REG_FIELD_PREP(VRR_CTL_LINE_COUNT_MASK, (x))
#define VRR_CTL_SW_FULLLINE_COUNT REG_BIT(0)
#define _TRANS_VRR_VMAX_A 0x60424
@ -10851,8 +10852,10 @@ enum skl_power_gate {
#define CNL_DRAM_RANK_3 (0x2 << 9)
#define CNL_DRAM_RANK_4 (0x3 << 9)
/* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
* since on HSW we can't write to it using I915_WRITE. */
/*
* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
* since on HSW we can't write to it using intel_uncore_write.
*/
#define D_COMP_HSW _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
#define D_COMP_BDW _MMIO(0x138144)
#define D_COMP_RCOMP_IN_PROGRESS (1 << 9)

View File

@ -24,6 +24,7 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "display/intel_de.h"
#include "display/intel_fbc.h"
#include "display/intel_gmbus.h"
#include "display/intel_vga.h"
@ -39,21 +40,21 @@ static void intel_save_swf(struct drm_i915_private *dev_priv)
/* Scratch space */
if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) {
for (i = 0; i < 7; i++) {
dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv, SWF0(i));
dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, SWF1(i));
}
for (i = 0; i < 3; i++)
dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv, SWF3(i));
} else if (IS_GEN(dev_priv, 2)) {
for (i = 0; i < 7; i++)
dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, SWF1(i));
} else if (HAS_GMCH(dev_priv)) {
for (i = 0; i < 16; i++) {
dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
dev_priv->regfile.saveSWF0[i] = intel_de_read(dev_priv, SWF0(i));
dev_priv->regfile.saveSWF1[i] = intel_de_read(dev_priv, SWF1(i));
}
for (i = 0; i < 3; i++)
dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
dev_priv->regfile.saveSWF3[i] = intel_de_read(dev_priv, SWF3(i));
}
}
@ -64,21 +65,21 @@ static void intel_restore_swf(struct drm_i915_private *dev_priv)
/* Scratch space */
if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) {
for (i = 0; i < 7; i++) {
I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
intel_de_write(dev_priv, SWF0(i), dev_priv->regfile.saveSWF0[i]);
intel_de_write(dev_priv, SWF1(i), dev_priv->regfile.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
intel_de_write(dev_priv, SWF3(i), dev_priv->regfile.saveSWF3[i]);
} else if (IS_GEN(dev_priv, 2)) {
for (i = 0; i < 7; i++)
I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
intel_de_write(dev_priv, SWF1(i), dev_priv->regfile.saveSWF1[i]);
} else if (HAS_GMCH(dev_priv)) {
for (i = 0; i < 16; i++) {
I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
intel_de_write(dev_priv, SWF0(i), dev_priv->regfile.saveSWF0[i]);
intel_de_write(dev_priv, SWF1(i), dev_priv->regfile.saveSWF1[i]);
}
for (i = 0; i < 3; i++)
I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
intel_de_write(dev_priv, SWF3(i), dev_priv->regfile.saveSWF3[i]);
}
}
@ -88,7 +89,7 @@ void i915_save_display(struct drm_i915_private *dev_priv)
/* Display arbitration control */
if (INTEL_GEN(dev_priv) <= 4)
dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
dev_priv->regfile.saveDSPARB = intel_de_read(dev_priv, DSPARB);
if (IS_GEN(dev_priv, 4))
pci_read_config_word(pdev, GCDGMBUS,
@ -109,7 +110,7 @@ void i915_restore_display(struct drm_i915_private *dev_priv)
/* Display arbitration */
if (INTEL_GEN(dev_priv) <= 4)
I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
intel_de_write(dev_priv, DSPARB, dev_priv->regfile.saveDSPARB);
/* only restore FBC info on the platform that supports FBC*/
intel_fbc_global_disable(dev_priv);

View File

@ -104,7 +104,7 @@ void intel_device_info_print_static(const struct intel_device_info *info,
drm_printf(p, "ppgtt-type: %d\n", info->ppgtt_type);
drm_printf(p, "dma_mask_size: %u\n", info->dma_mask_size);
#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name));
#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name))
DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
#undef PRINT_FLAG

File diff suppressed because it is too large Load Diff

View File

@ -404,8 +404,8 @@ static int __sandybridge_pcode_rw(struct drm_i915_private *i915,
lockdep_assert_held(&i915->sb_lock);
/*
* GEN6_PCODE_* are outside of the forcewake domain, we can
* use te fw I915_READ variants to reduce the amount of work
* GEN6_PCODE_* are outside of the forcewake domain, we can use
* intel_uncore_read/write_fw variants to reduce the amount of work
* required when reading/writing.
*/

View File

@ -2070,7 +2070,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
* This routine waits until the target register @reg contains the expected
* @value after applying the @mask, i.e. it waits until ::
*
* (I915_READ_FW(reg) & mask) == value
* (intel_uncore_read_fw(uncore, reg) & mask) == value
*
* Otherwise, the wait will timeout after @slow_timeout_ms milliseconds.
* For atomic context @slow_timeout_ms must be zero and @fast_timeout_us
@ -2126,7 +2126,7 @@ int __intel_wait_for_register_fw(struct intel_uncore *uncore,
* This routine waits until the target register @reg contains the expected
* @value after applying the @mask, i.e. it waits until ::
*
* (I915_READ(reg) & mask) == value
* (intel_uncore_read(uncore, reg) & mask) == value
*
* Otherwise, the wait will timeout after @timeout_ms milliseconds.
*

View File

@ -216,7 +216,7 @@ void intel_uncore_forcewake_flush(struct intel_uncore *uncore,
/*
* Like above but the caller must manage the uncore.lock itself.
* Must be used with I915_READ_FW and friends.
* Must be used with intel_uncore_read_fw() and friends.
*/
void intel_uncore_forcewake_get__locked(struct intel_uncore *uncore,
enum forcewake_domains domains);
@ -318,8 +318,8 @@ __uncore_write(write_notrace, 32, l, false)
* will be implemented using 2 32-bit writes in an arbitrary order with
* an arbitrary delay between them. This can cause the hardware to
* act upon the intermediate value, possibly leading to corruption and
* machine death. For this reason we do not support I915_WRITE64, or
* uncore->funcs.mmio_writeq.
* machine death. For this reason we do not support intel_uncore_write64,
* or uncore->funcs.mmio_writeq.
*
* When reading a 64-bit value as two 32-bit values, the delay may cause
* the two reads to mismatch, e.g. a timestamp overflowing. Also note that

View File

@ -603,6 +603,7 @@ struct drm_dsc_pps_infoframe {
} __packed;
void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header);
int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size);
void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp,
const struct drm_dsc_config *dsc_cfg);
int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg);