- 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
This commit is contained in:
Коммит
ca765c731e
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(®->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},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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.
|
||||
*/
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче