mirror of
https://github.com/ukui/kernel.git
synced 2026-03-09 10:07:04 -07:00
Merge tag 'drm-intel-next-2021-11-30' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
drm/i915 feature pull for v5.17: Features and functionality: - Implement per-lane DP drive settings for ICL+ (Ville) - Enable runtime pm autosuspend by default (Tilak Tangudu) - ADL-P DSI support (Vandita) - Add support for pipe C and D DMC firmware (Anusha) - Implement (near)atomic gamma LUT updates via vblank workers (Ville) - Split plane updates to noarm+arm phases (Ville) - Remove the CCS FB stride restrictions on ADL-P (Imre) - Add PSR selective fetch support for biplanar formats (Jouni) - Add support for display audio codec keepalive (Kai) - VRR platform support for display 11 (Manasi) Refactoring and cleanups: - FBC refactoring and cleanups preparing for multiple FBC instances (Ville) - PCH modeset refactoring, move to its own file (Ville) - Refactor and simplify handling of modifiers (Imre) - PXP cleanups (Ville) - Display header and include refactoring (Jani) - Some register macro cleanups (Ville) - Refactor DP HDMI DFP limit code (Ville) Fixes: - Disable DSB usage for now due to incorrect gamma LUT updates (Ville) - Check async flip state of every crtc and plane only once (José) - Fix DPT FB suspend/resume (Imre) - Fix black screen on reboot due to disabled DP++ TMDS output buffers (Ville) - Don't request GMBUS to generate irqs when called while irqs are off (Ville) - Fix type1 DVI DP dual mode adapter heuristics for modern platforms (Ville) - Fix fix integer overflow in 128b/132b data rate calculation (Jani) - Fix bigjoiner state readout (Ville) - Build fix for non-x86 (Siva) - PSR fixes (José, Jouni, Ville) - Disable ADL-P underrun recovery (José) - Fix DP link parameter usage before valid DPCD (Imre) - VRR vblank and frame counter fixes (Ville) - Fix fastsets on TypeC ports following a non-blocking modeset (Imre) - Compiler warning fixes (Nathan Chancellor) - Fix DSI HS mode commands (William Tseng) - Error return fixes (Dan Carpenter) - Update memory bandwidth calculations (Radhakrishna) - Implement WM0 cursor WA for DG2 (Stan) - Fix DSI Double pixelclock on read-back for dual-link panels (Hans de Goede) - HDMI 2.1 PCON FRL configuration fixes (Ankit) Merges: - DP link training delay helpers, via topic branch (Jani) - Backmerge drm-next (Jani) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/87v909it0t.fsf@intel.com
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/agp_backend.h>
|
||||
#include <linux/intel-iommu.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/smp.h>
|
||||
#include "agp.h"
|
||||
|
||||
@@ -21,7 +21,7 @@ config DRM_I915
|
||||
select ACPI_VIDEO if ACPI
|
||||
select ACPI_BUTTON if ACPI
|
||||
select SYNC_FILE
|
||||
select IOSF_MBI
|
||||
select IOSF_MBI if X86
|
||||
select CRC32
|
||||
select SND_HDA_I915 if SND_HDA_CORE
|
||||
select CEC_CORE if CEC_NOTIFIER
|
||||
|
||||
@@ -30,7 +30,7 @@ subdir-ccflags-y += -I$(srctree)/$(src)
|
||||
# Please keep these build lists sorted!
|
||||
|
||||
# core driver code
|
||||
i915-y += i915_drv.o \
|
||||
i915-y += i915_driver.o \
|
||||
i915_config.o \
|
||||
i915_irq.o \
|
||||
i915_getparam.o \
|
||||
@@ -226,6 +226,8 @@ i915-y += \
|
||||
display/intel_hotplug.o \
|
||||
display/intel_lpe_audio.o \
|
||||
display/intel_overlay.o \
|
||||
display/intel_pch_display.o \
|
||||
display/intel_pch_refclk.o \
|
||||
display/intel_plane_initial.o \
|
||||
display/intel_psr.o \
|
||||
display/intel_quirks.o \
|
||||
|
||||
@@ -60,22 +60,11 @@ static const u32 vlv_primary_formats[] = {
|
||||
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:
|
||||
if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case DRM_FORMAT_C8:
|
||||
@@ -92,13 +81,8 @@ static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
|
||||
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:
|
||||
if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case DRM_FORMAT_C8:
|
||||
@@ -272,7 +256,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
|
||||
u32 alignment = intel_surf_alignment(fb, 0);
|
||||
int cpp = fb->format->cpp[0];
|
||||
|
||||
while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].stride) {
|
||||
while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
|
||||
if (offset == 0) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Unable to find suitable display surface offset due to X-tiling\n");
|
||||
@@ -418,22 +402,49 @@ static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
|
||||
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)
|
||||
static void i9xx_plane_update_noarm(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;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
|
||||
plane_state->view.color_plane[0].mapping_stride);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) < 4) {
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i9xx_plane_update_arm(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->view.color_plane[0].x;
|
||||
int y = plane_state->view.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);
|
||||
u32 dspcntr, dspaddr_offset, linear_offset;
|
||||
unsigned long irqflags;
|
||||
u32 dspaddr_offset;
|
||||
u32 dspcntr;
|
||||
|
||||
dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
|
||||
|
||||
@@ -446,20 +457,12 @@ static void i9xx_update_plane(struct intel_plane *plane,
|
||||
|
||||
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
|
||||
|
||||
intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
|
||||
plane_state->view.color_plane[0].stride);
|
||||
if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
|
||||
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);
|
||||
|
||||
if (DISPLAY_VER(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),
|
||||
@@ -493,8 +496,22 @@ static void i9xx_update_plane(struct intel_plane *plane,
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i9xx_disable_plane(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
static void i830_plane_update_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
/*
|
||||
* On i830/i845 all registers are self-arming [ALM040].
|
||||
*
|
||||
* Additional breakage on i830 causes register reads to return
|
||||
* the last latched value instead of the last written value [ALM026].
|
||||
*/
|
||||
i9xx_plane_update_noarm(plane, crtc_state, plane_state);
|
||||
i9xx_plane_update_arm(plane, crtc_state, plane_state);
|
||||
}
|
||||
|
||||
static void i9xx_plane_disable_arm(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;
|
||||
@@ -768,6 +785,7 @@ 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 u64 *modifiers;
|
||||
const u32 *formats;
|
||||
int num_formats;
|
||||
int ret, zpos;
|
||||
@@ -789,12 +807,10 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe 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 (i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane))
|
||||
plane->fbc = &dev_priv->fbc;
|
||||
if (plane->fbc)
|
||||
plane->fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
formats = vlv_primary_formats;
|
||||
@@ -851,8 +867,13 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
plane->max_stride = ilk_primary_max_stride;
|
||||
}
|
||||
|
||||
plane->update_plane = i9xx_update_plane;
|
||||
plane->disable_plane = i9xx_disable_plane;
|
||||
if (IS_I830(dev_priv) || IS_I845G(dev_priv)) {
|
||||
plane->update_arm = i830_plane_update_arm;
|
||||
} else {
|
||||
plane->update_noarm = i9xx_plane_update_noarm;
|
||||
plane->update_arm = i9xx_plane_update_arm;
|
||||
}
|
||||
plane->disable_arm = i9xx_plane_disable_arm;
|
||||
plane->get_hw_state = i9xx_plane_get_hw_state;
|
||||
plane->check_plane = i9xx_plane_check;
|
||||
|
||||
@@ -875,21 +896,26 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
plane->disable_flip_done = ilk_primary_disable_flip_done;
|
||||
}
|
||||
|
||||
modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
|
||||
|
||||
if (DISPLAY_VER(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,
|
||||
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,
|
||||
modifiers,
|
||||
DRM_PLANE_TYPE_PRIMARY,
|
||||
"plane %c",
|
||||
plane_name(plane->i9xx_plane));
|
||||
|
||||
kfree(modifiers);
|
||||
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
|
||||
#include "icl_dsi.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_backlight.h"
|
||||
#include "intel_combo_phy.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_dsi_vbt.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_vdsc.h"
|
||||
#include "skl_scaler.h"
|
||||
@@ -183,6 +185,8 @@ static int dsi_send_pkt_hdr(struct intel_dsi_host *host,
|
||||
|
||||
if (enable_lpdt)
|
||||
tmp |= LP_DATA_TRANSFER;
|
||||
else
|
||||
tmp &= ~LP_DATA_TRANSFER;
|
||||
|
||||
tmp &= ~(PARAM_WC_MASK | VC_MASK | DT_MASK);
|
||||
tmp |= ((packet->header[0] & VC_MASK) << VC_SHIFT);
|
||||
@@ -1226,7 +1230,9 @@ static void gen11_dsi_pre_enable(struct intel_atomic_state *state,
|
||||
/* step5: program and powerup panel */
|
||||
gen11_dsi_powerup_panel(encoder);
|
||||
|
||||
intel_dsc_enable(encoder, pipe_config);
|
||||
intel_dsc_dsi_pps_write(encoder, pipe_config);
|
||||
|
||||
intel_dsc_enable(pipe_config);
|
||||
|
||||
/* step6c: configure transcoder timings */
|
||||
gen11_dsi_set_transcoder_timings(encoder, pipe_config);
|
||||
@@ -1623,7 +1629,7 @@ static int gen11_dsi_dsc_compute_config(struct intel_encoder *encoder,
|
||||
/* FIXME: initialize from VBT */
|
||||
vdsc_cfg->rc_model_size = DSC_RC_MODEL_SIZE_CONST;
|
||||
|
||||
ret = intel_dsc_compute_params(encoder, crtc_state);
|
||||
ret = intel_dsc_compute_params(crtc_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __ICL_DSI_H__
|
||||
#define __ICL_DSI_H__
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_crtc_state;
|
||||
|
||||
void icl_dsi_init(struct drm_i915_private *i915);
|
||||
void icl_dsi_frame_update(struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __ICL_DSI_H__ */
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "intel_atomic_plane.h"
|
||||
#include "intel_cdclk.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fb.h"
|
||||
#include "intel_fb_pin.h"
|
||||
#include "intel_pm.h"
|
||||
#include "intel_sprite.h"
|
||||
@@ -469,31 +470,72 @@ skl_next_plane_to_commit(struct intel_atomic_state *state,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void intel_update_plane(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
void intel_plane_update_noarm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
trace_intel_update_plane(&plane->base, crtc);
|
||||
trace_intel_plane_update_noarm(&plane->base, crtc);
|
||||
|
||||
if (plane->update_noarm)
|
||||
plane->update_noarm(plane, crtc_state, plane_state);
|
||||
}
|
||||
|
||||
void intel_plane_update_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
trace_intel_plane_update_arm(&plane->base, crtc);
|
||||
|
||||
if (crtc_state->uapi.async_flip && plane->async_flip)
|
||||
plane->async_flip(plane, crtc_state, plane_state, true);
|
||||
else
|
||||
plane->update_plane(plane, crtc_state, plane_state);
|
||||
plane->update_arm(plane, crtc_state, plane_state);
|
||||
}
|
||||
|
||||
void intel_disable_plane(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
void intel_plane_disable_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
trace_intel_disable_plane(&plane->base, crtc);
|
||||
plane->disable_plane(plane, crtc_state);
|
||||
trace_intel_plane_disable_arm(&plane->base, crtc);
|
||||
plane->disable_arm(plane, crtc_state);
|
||||
}
|
||||
|
||||
void skl_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
void intel_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
u32 update_mask = new_crtc_state->update_planes;
|
||||
struct intel_plane_state *new_plane_state;
|
||||
struct intel_plane *plane;
|
||||
int i;
|
||||
|
||||
if (new_crtc_state->uapi.async_flip)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Since we only write non-arming registers here,
|
||||
* the order does not matter even for skl+.
|
||||
*/
|
||||
for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
|
||||
if (crtc->pipe != plane->pipe ||
|
||||
!(update_mask & BIT(plane->id)))
|
||||
continue;
|
||||
|
||||
/* TODO: for mailbox updates this should be skipped */
|
||||
if (new_plane_state->uapi.visible ||
|
||||
new_plane_state->planar_slave)
|
||||
intel_plane_update_noarm(plane, new_crtc_state, new_plane_state);
|
||||
}
|
||||
}
|
||||
|
||||
void skl_arm_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc_state *old_crtc_state =
|
||||
intel_atomic_get_old_crtc_state(state, crtc);
|
||||
@@ -515,17 +557,20 @@ void skl_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_plane_state *new_plane_state =
|
||||
intel_atomic_get_new_plane_state(state, plane);
|
||||
|
||||
/*
|
||||
* TODO: for mailbox updates intel_plane_update_noarm()
|
||||
* would have to be called here as well.
|
||||
*/
|
||||
if (new_plane_state->uapi.visible ||
|
||||
new_plane_state->planar_slave) {
|
||||
intel_update_plane(plane, new_crtc_state, new_plane_state);
|
||||
} else {
|
||||
intel_disable_plane(plane, new_crtc_state);
|
||||
}
|
||||
new_plane_state->planar_slave)
|
||||
intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
|
||||
else
|
||||
intel_plane_disable_arm(plane, new_crtc_state);
|
||||
}
|
||||
}
|
||||
|
||||
void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
void i9xx_arm_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc_state *new_crtc_state =
|
||||
intel_atomic_get_new_crtc_state(state, crtc);
|
||||
@@ -539,10 +584,14 @@ void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
!(update_mask & BIT(plane->id)))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* TODO: for mailbox updates intel_plane_update_noarm()
|
||||
* would have to be called here as well.
|
||||
*/
|
||||
if (new_plane_state->uapi.visible)
|
||||
intel_update_plane(plane, new_crtc_state, new_plane_state);
|
||||
intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
|
||||
else
|
||||
intel_disable_plane(plane, new_crtc_state);
|
||||
intel_plane_disable_arm(plane, new_crtc_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,20 +30,25 @@ void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_plane_copy_hw_state(struct intel_plane_state *plane_state,
|
||||
const struct intel_plane_state *from_plane_state);
|
||||
void intel_update_plane(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void intel_disable_plane(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_plane_update_noarm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void intel_plane_update_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void intel_plane_disable_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
struct intel_plane *intel_plane_alloc(void);
|
||||
void intel_plane_free(struct intel_plane *plane);
|
||||
struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
|
||||
void intel_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
void skl_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void intel_update_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void skl_arm_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
void i9xx_arm_planes_on_crtc(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *old_plane_state,
|
||||
|
||||
@@ -62,6 +62,15 @@
|
||||
* struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver.
|
||||
*/
|
||||
|
||||
struct intel_audio_funcs {
|
||||
void (*audio_codec_enable)(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
void (*audio_codec_disable)(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *old_crtc_state,
|
||||
const struct drm_connector_state *old_conn_state);
|
||||
};
|
||||
|
||||
/* DP N/M table */
|
||||
#define LC_810M 810000
|
||||
#define LC_540M 540000
|
||||
@@ -388,7 +397,7 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
struct i915_audio_component *acomp = dev_priv->audio.component;
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum port port = encoder->port;
|
||||
const struct dp_aud_n_m *nm;
|
||||
@@ -436,7 +445,7 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
struct i915_audio_component *acomp = dev_priv->audio.component;
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum port port = encoder->port;
|
||||
int n, rate;
|
||||
@@ -494,7 +503,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
|
||||
drm_dbg_kms(&dev_priv->drm, "Disable audio codec on transcoder %s\n",
|
||||
transcoder_name(cpu_transcoder));
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
|
||||
/* Disable timestamps */
|
||||
tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder));
|
||||
@@ -512,7 +521,7 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
|
||||
tmp &= ~AUDIO_OUTPUT_ENABLE(cpu_transcoder);
|
||||
intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
mutex_unlock(&dev_priv->audio.mutex);
|
||||
}
|
||||
|
||||
static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder,
|
||||
@@ -641,7 +650,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
|
||||
"Enable audio codec on transcoder %s, %u bytes ELD\n",
|
||||
transcoder_name(cpu_transcoder), drm_eld_size(eld));
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
|
||||
/* Enable Audio WA for 4k DSC usecases */
|
||||
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP))
|
||||
@@ -679,7 +688,7 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
|
||||
/* Enable timestamps */
|
||||
hsw_audio_config_update(encoder, crtc_state);
|
||||
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
mutex_unlock(&dev_priv->audio.mutex);
|
||||
}
|
||||
|
||||
static void ilk_audio_codec_disable(struct intel_encoder *encoder,
|
||||
@@ -826,7 +835,7 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
struct i915_audio_component *acomp = dev_priv->audio.component;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
@@ -848,17 +857,17 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
|
||||
|
||||
connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
|
||||
|
||||
if (dev_priv->audio_funcs)
|
||||
dev_priv->audio_funcs->audio_codec_enable(encoder,
|
||||
if (dev_priv->audio.funcs)
|
||||
dev_priv->audio.funcs->audio_codec_enable(encoder,
|
||||
crtc_state,
|
||||
conn_state);
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
encoder->audio_connector = connector;
|
||||
|
||||
/* referred in audio callbacks */
|
||||
dev_priv->av_enc_map[pipe] = encoder;
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
dev_priv->audio.encoder_map[pipe] = encoder;
|
||||
mutex_unlock(&dev_priv->audio.mutex);
|
||||
|
||||
if (acomp && acomp->base.audio_ops &&
|
||||
acomp->base.audio_ops->pin_eld_notify) {
|
||||
@@ -888,20 +897,20 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
struct i915_audio_component *acomp = dev_priv->audio.component;
|
||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
|
||||
enum port port = encoder->port;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
if (dev_priv->audio_funcs)
|
||||
dev_priv->audio_funcs->audio_codec_disable(encoder,
|
||||
if (dev_priv->audio.funcs)
|
||||
dev_priv->audio.funcs->audio_codec_disable(encoder,
|
||||
old_crtc_state,
|
||||
old_conn_state);
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
encoder->audio_connector = NULL;
|
||||
dev_priv->av_enc_map[pipe] = NULL;
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
dev_priv->audio.encoder_map[pipe] = NULL;
|
||||
mutex_unlock(&dev_priv->audio.mutex);
|
||||
|
||||
if (acomp && acomp->base.audio_ops &&
|
||||
acomp->base.audio_ops->pin_eld_notify) {
|
||||
@@ -931,19 +940,53 @@ static const struct intel_audio_funcs hsw_audio_funcs = {
|
||||
};
|
||||
|
||||
/**
|
||||
* intel_init_audio_hooks - Set up chip specific audio hooks
|
||||
* intel_audio_hooks_init - Set up chip specific audio hooks
|
||||
* @dev_priv: device private
|
||||
*/
|
||||
void intel_init_audio_hooks(struct drm_i915_private *dev_priv)
|
||||
void intel_audio_hooks_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_G4X(dev_priv)) {
|
||||
dev_priv->audio_funcs = &g4x_audio_funcs;
|
||||
dev_priv->audio.funcs = &g4x_audio_funcs;
|
||||
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
||||
dev_priv->audio_funcs = &ilk_audio_funcs;
|
||||
dev_priv->audio.funcs = &ilk_audio_funcs;
|
||||
} else if (IS_HASWELL(dev_priv) || DISPLAY_VER(dev_priv) >= 8) {
|
||||
dev_priv->audio_funcs = &hsw_audio_funcs;
|
||||
dev_priv->audio.funcs = &hsw_audio_funcs;
|
||||
} else if (HAS_PCH_SPLIT(dev_priv)) {
|
||||
dev_priv->audio_funcs = &ilk_audio_funcs;
|
||||
dev_priv->audio.funcs = &ilk_audio_funcs;
|
||||
}
|
||||
}
|
||||
|
||||
struct aud_ts_cdclk_m_n {
|
||||
u8 m;
|
||||
u16 n;
|
||||
};
|
||||
|
||||
void intel_audio_cdclk_change_pre(struct drm_i915_private *i915)
|
||||
{
|
||||
if (DISPLAY_VER(i915) >= 13)
|
||||
intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0);
|
||||
}
|
||||
|
||||
static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n *aud_ts)
|
||||
{
|
||||
if (refclk == 24000)
|
||||
aud_ts->m = 12;
|
||||
else
|
||||
aud_ts->m = 15;
|
||||
|
||||
aud_ts->n = cdclk * aud_ts->m / 24000;
|
||||
}
|
||||
|
||||
void intel_audio_cdclk_change_post(struct drm_i915_private *i915)
|
||||
{
|
||||
struct aud_ts_cdclk_m_n aud_ts;
|
||||
|
||||
if (DISPLAY_VER(i915) >= 13) {
|
||||
get_aud_ts_cdclk_m_n(i915->cdclk.hw.ref, i915->cdclk.hw.cdclk, &aud_ts);
|
||||
|
||||
intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n);
|
||||
intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN);
|
||||
drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n", aud_ts.m, aud_ts.n);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,13 +1057,13 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
|
||||
|
||||
ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK);
|
||||
|
||||
if (dev_priv->audio_power_refcount++ == 0) {
|
||||
if (dev_priv->audio.power_refcount++ == 0) {
|
||||
if (DISPLAY_VER(dev_priv) >= 9) {
|
||||
intel_de_write(dev_priv, AUD_FREQ_CNTRL,
|
||||
dev_priv->audio_freq_cntrl);
|
||||
dev_priv->audio.freq_cntrl);
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"restored AUD_FREQ_CNTRL to 0x%x\n",
|
||||
dev_priv->audio_freq_cntrl);
|
||||
dev_priv->audio.freq_cntrl);
|
||||
}
|
||||
|
||||
/* Force CDCLK to 2*BCLK as long as we need audio powered. */
|
||||
@@ -1041,7 +1084,7 @@ static void i915_audio_component_put_power(struct device *kdev,
|
||||
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
|
||||
|
||||
/* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */
|
||||
if (--dev_priv->audio_power_refcount == 0)
|
||||
if (--dev_priv->audio.power_refcount == 0)
|
||||
if (IS_GEMINILAKE(dev_priv))
|
||||
glk_force_audio_cdclk(dev_priv, false);
|
||||
|
||||
@@ -1093,7 +1136,7 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
|
||||
/*
|
||||
* get the intel_encoder according to the parameter port and pipe
|
||||
* intel_encoder is saved by the index of pipe
|
||||
* MST & (pipe >= 0): return the av_enc_map[pipe],
|
||||
* MST & (pipe >= 0): return the audio.encoder_map[pipe],
|
||||
* when port is matched
|
||||
* MST & (pipe < 0): this is invalid
|
||||
* Non-MST & (pipe >= 0): only pipe = 0 (the first device entry)
|
||||
@@ -1108,10 +1151,10 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
|
||||
/* MST */
|
||||
if (pipe >= 0) {
|
||||
if (drm_WARN_ON(&dev_priv->drm,
|
||||
pipe >= ARRAY_SIZE(dev_priv->av_enc_map)))
|
||||
pipe >= ARRAY_SIZE(dev_priv->audio.encoder_map)))
|
||||
return NULL;
|
||||
|
||||
encoder = dev_priv->av_enc_map[pipe];
|
||||
encoder = dev_priv->audio.encoder_map[pipe];
|
||||
/*
|
||||
* when bootup, audio driver may not know it is
|
||||
* MST or not. So it will poll all the port & pipe
|
||||
@@ -1127,7 +1170,7 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
|
||||
return NULL;
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
encoder = dev_priv->av_enc_map[pipe];
|
||||
encoder = dev_priv->audio.encoder_map[pipe];
|
||||
if (encoder == NULL)
|
||||
continue;
|
||||
|
||||
@@ -1145,7 +1188,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port,
|
||||
int pipe, int rate)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
struct i915_audio_component *acomp = dev_priv->audio.component;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_crtc *crtc;
|
||||
unsigned long cookie;
|
||||
@@ -1155,7 +1198,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port,
|
||||
return 0;
|
||||
|
||||
cookie = i915_audio_component_get_power(kdev);
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
|
||||
/* 1. get the pipe */
|
||||
encoder = get_saved_enc(dev_priv, port, pipe);
|
||||
@@ -1174,7 +1217,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port,
|
||||
hsw_audio_config_update(encoder, crtc->config);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
mutex_unlock(&dev_priv->audio.mutex);
|
||||
i915_audio_component_put_power(kdev, cookie);
|
||||
return err;
|
||||
}
|
||||
@@ -1188,13 +1231,13 @@ static int i915_audio_component_get_eld(struct device *kdev, int port,
|
||||
const u8 *eld;
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
mutex_lock(&dev_priv->audio.mutex);
|
||||
|
||||
intel_encoder = get_saved_enc(dev_priv, port, pipe);
|
||||
if (!intel_encoder) {
|
||||
drm_dbg_kms(&dev_priv->drm, "Not valid for port %c\n",
|
||||
port_name(port));
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
mutex_unlock(&dev_priv->audio.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1206,7 +1249,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port,
|
||||
memcpy(buf, eld, min(max_bytes, ret));
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
mutex_unlock(&dev_priv->audio.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1241,7 +1284,7 @@ static int i915_audio_component_bind(struct device *i915_kdev,
|
||||
BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS);
|
||||
for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++)
|
||||
acomp->aud_sample_rate[i] = 0;
|
||||
dev_priv->audio_component = acomp;
|
||||
dev_priv->audio.component = acomp;
|
||||
drm_modeset_unlock_all(&dev_priv->drm);
|
||||
|
||||
return 0;
|
||||
@@ -1256,14 +1299,14 @@ static void i915_audio_component_unbind(struct device *i915_kdev,
|
||||
drm_modeset_lock_all(&dev_priv->drm);
|
||||
acomp->base.ops = NULL;
|
||||
acomp->base.dev = NULL;
|
||||
dev_priv->audio_component = NULL;
|
||||
dev_priv->audio.component = NULL;
|
||||
drm_modeset_unlock_all(&dev_priv->drm);
|
||||
|
||||
device_link_remove(hda_kdev, i915_kdev);
|
||||
|
||||
if (dev_priv->audio_power_refcount)
|
||||
if (dev_priv->audio.power_refcount)
|
||||
drm_err(&dev_priv->drm, "audio power refcount %d after unbind\n",
|
||||
dev_priv->audio_power_refcount);
|
||||
dev_priv->audio.power_refcount);
|
||||
}
|
||||
|
||||
static const struct component_ops i915_audio_component_bind_ops = {
|
||||
@@ -1327,10 +1370,13 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv)
|
||||
drm_dbg_kms(&dev_priv->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n",
|
||||
aud_freq, aud_freq_init);
|
||||
|
||||
dev_priv->audio_freq_cntrl = aud_freq;
|
||||
dev_priv->audio.freq_cntrl = aud_freq;
|
||||
}
|
||||
|
||||
dev_priv->audio_component_registered = true;
|
||||
/* init with current cdclk */
|
||||
intel_audio_cdclk_change_post(dev_priv);
|
||||
|
||||
dev_priv->audio.component_registered = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1342,11 +1388,11 @@ static void i915_audio_component_init(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
static void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (!dev_priv->audio_component_registered)
|
||||
if (!dev_priv->audio.component_registered)
|
||||
return;
|
||||
|
||||
component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops);
|
||||
dev_priv->audio_component_registered = false;
|
||||
dev_priv->audio.component_registered = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1368,7 +1414,7 @@ void intel_audio_init(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
void intel_audio_deinit(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if ((dev_priv)->lpe_audio.platdev != NULL)
|
||||
if ((dev_priv)->audio.lpe.platdev != NULL)
|
||||
intel_lpe_audio_teardown(dev_priv);
|
||||
else
|
||||
i915_audio_component_cleanup(dev_priv);
|
||||
|
||||
@@ -11,13 +11,15 @@ struct drm_i915_private;
|
||||
struct intel_crtc_state;
|
||||
struct intel_encoder;
|
||||
|
||||
void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_hooks_init(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_codec_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state);
|
||||
void intel_audio_codec_disable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *old_crtc_state,
|
||||
const struct drm_connector_state *old_conn_state);
|
||||
void intel_audio_cdclk_change_pre(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_cdclk_change_post(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_init(struct drm_i915_private *dev_priv);
|
||||
void intel_audio_deinit(struct drm_i915_private *dev_priv);
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ struct intel_qgv_info {
|
||||
u8 num_points;
|
||||
u8 num_psf_points;
|
||||
u8 t_bl;
|
||||
u8 max_numchannels;
|
||||
u8 channel_width;
|
||||
u8 deinterleave;
|
||||
};
|
||||
|
||||
static int dg1_mchbar_read_qgv_point_info(struct drm_i915_private *dev_priv,
|
||||
@@ -42,7 +45,7 @@ static int dg1_mchbar_read_qgv_point_info(struct drm_i915_private *dev_priv,
|
||||
dclk_reference = 6; /* 6 * 16.666 MHz = 100 MHz */
|
||||
else
|
||||
dclk_reference = 8; /* 8 * 16.666 MHz = 133 MHz */
|
||||
sp->dclk = dclk_ratio * dclk_reference;
|
||||
sp->dclk = DIV_ROUND_UP((16667 * dclk_ratio * dclk_reference) + 500, 1000);
|
||||
|
||||
val = intel_uncore_read(&dev_priv->uncore, SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
|
||||
if (val & DG1_GEAR_TYPE)
|
||||
@@ -69,6 +72,7 @@ static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
|
||||
int point)
|
||||
{
|
||||
u32 val = 0, val2 = 0;
|
||||
u16 dclk;
|
||||
int ret;
|
||||
|
||||
ret = sandybridge_pcode_read(dev_priv,
|
||||
@@ -78,7 +82,8 @@ static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sp->dclk = val & 0xffff;
|
||||
dclk = val & 0xffff;
|
||||
sp->dclk = DIV_ROUND_UP((16667 * dclk) + (DISPLAY_VER(dev_priv) > 11 ? 500 : 0), 1000);
|
||||
sp->t_rp = (val & 0xff0000) >> 16;
|
||||
sp->t_rcd = (val & 0xff000000) >> 24;
|
||||
|
||||
@@ -133,7 +138,8 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
|
||||
static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
|
||||
struct intel_qgv_info *qi)
|
||||
struct intel_qgv_info *qi,
|
||||
bool is_y_tile)
|
||||
{
|
||||
const struct dram_info *dram_info = &dev_priv->dram_info;
|
||||
int i, ret;
|
||||
@@ -141,20 +147,44 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
|
||||
qi->num_points = dram_info->num_qgv_points;
|
||||
qi->num_psf_points = dram_info->num_psf_gv_points;
|
||||
|
||||
if (DISPLAY_VER(dev_priv) == 12)
|
||||
if (DISPLAY_VER(dev_priv) >= 12)
|
||||
switch (dram_info->type) {
|
||||
case INTEL_DRAM_DDR4:
|
||||
qi->t_bl = 4;
|
||||
qi->t_bl = is_y_tile ? 8 : 4;
|
||||
qi->max_numchannels = 2;
|
||||
qi->channel_width = 64;
|
||||
qi->deinterleave = is_y_tile ? 1 : 2;
|
||||
break;
|
||||
case INTEL_DRAM_DDR5:
|
||||
qi->t_bl = 8;
|
||||
qi->t_bl = is_y_tile ? 16 : 8;
|
||||
qi->max_numchannels = 4;
|
||||
qi->channel_width = 32;
|
||||
qi->deinterleave = is_y_tile ? 1 : 2;
|
||||
break;
|
||||
case INTEL_DRAM_LPDDR4:
|
||||
if (IS_ROCKETLAKE(dev_priv)) {
|
||||
qi->t_bl = 8;
|
||||
qi->max_numchannels = 4;
|
||||
qi->channel_width = 32;
|
||||
qi->deinterleave = 2;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
case INTEL_DRAM_LPDDR5:
|
||||
qi->t_bl = 16;
|
||||
qi->max_numchannels = 8;
|
||||
qi->channel_width = 16;
|
||||
qi->deinterleave = is_y_tile ? 2 : 4;
|
||||
break;
|
||||
default:
|
||||
qi->t_bl = 16;
|
||||
qi->max_numchannels = 1;
|
||||
break;
|
||||
}
|
||||
else if (DISPLAY_VER(dev_priv) == 11)
|
||||
else if (DISPLAY_VER(dev_priv) == 11) {
|
||||
qi->t_bl = dev_priv->dram_info.type == INTEL_DRAM_DDR4 ? 4 : 8;
|
||||
qi->max_numchannels = 1;
|
||||
}
|
||||
|
||||
if (drm_WARN_ON(&dev_priv->drm,
|
||||
qi->num_points > ARRAY_SIZE(qi->points)))
|
||||
@@ -193,12 +223,6 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icl_calc_bw(int dclk, int num, int den)
|
||||
{
|
||||
/* multiples of 16.666MHz (100/6) */
|
||||
return DIV_ROUND_CLOSEST(num * dclk * 100, den * 6);
|
||||
}
|
||||
|
||||
static int adl_calc_psf_bw(int clk)
|
||||
{
|
||||
/*
|
||||
@@ -240,7 +264,7 @@ static const struct intel_sa_info tgl_sa_info = {
|
||||
};
|
||||
|
||||
static const struct intel_sa_info rkl_sa_info = {
|
||||
.deburst = 16,
|
||||
.deburst = 8,
|
||||
.deprogbwlimit = 20, /* GB/s */
|
||||
.displayrtids = 128,
|
||||
.derating = 10,
|
||||
@@ -265,34 +289,30 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
|
||||
struct intel_qgv_info qi = {};
|
||||
bool is_y_tile = true; /* assume y tile may be used */
|
||||
int num_channels = max_t(u8, 1, dev_priv->dram_info.num_channels);
|
||||
int deinterleave;
|
||||
int ipqdepth, ipqdepthpch;
|
||||
int ipqdepth, ipqdepthpch = 16;
|
||||
int dclk_max;
|
||||
int maxdebw;
|
||||
int num_groups = ARRAY_SIZE(dev_priv->max_bw);
|
||||
int i, ret;
|
||||
|
||||
ret = icl_get_qgv_points(dev_priv, &qi);
|
||||
ret = icl_get_qgv_points(dev_priv, &qi, is_y_tile);
|
||||
if (ret) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Failed to get memory subsystem information, ignoring bandwidth limits");
|
||||
return ret;
|
||||
}
|
||||
|
||||
deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
|
||||
dclk_max = icl_sagv_max_dclk(&qi);
|
||||
|
||||
ipqdepthpch = 16;
|
||||
|
||||
maxdebw = min(sa->deprogbwlimit * 1000,
|
||||
icl_calc_bw(dclk_max, 16, 1) * 6 / 10); /* 60% */
|
||||
maxdebw = min(sa->deprogbwlimit * 1000, dclk_max * 16 * 6 / 10);
|
||||
ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
|
||||
qi.deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
struct intel_bw_info *bi = &dev_priv->max_bw[i];
|
||||
int clpchgroup;
|
||||
int j;
|
||||
|
||||
clpchgroup = (sa->deburst * deinterleave / num_channels) << i;
|
||||
clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i;
|
||||
bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
|
||||
|
||||
bi->num_qgv_points = qi.num_points;
|
||||
@@ -310,7 +330,106 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
|
||||
*/
|
||||
ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd +
|
||||
(clpchgroup - 1) * qi.t_bl + sp->t_rdpre);
|
||||
bw = icl_calc_bw(sp->dclk, clpchgroup * 32 * num_channels, ct);
|
||||
bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct);
|
||||
|
||||
bi->deratedbw[j] = min(maxdebw,
|
||||
bw * (100 - sa->derating) / 100);
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"BW%d / QGV %d: num_planes=%d deratedbw=%u\n",
|
||||
i, j, bi->num_planes, bi->deratedbw[j]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* In case if SAGV is disabled in BIOS, we always get 1
|
||||
* SAGV point, but we can't send PCode commands to restrict it
|
||||
* as it will fail and pointless anyway.
|
||||
*/
|
||||
if (qi.num_points == 1)
|
||||
dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED;
|
||||
else
|
||||
dev_priv->sagv_status = I915_SAGV_ENABLED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa)
|
||||
{
|
||||
struct intel_qgv_info qi = {};
|
||||
const struct dram_info *dram_info = &dev_priv->dram_info;
|
||||
bool is_y_tile = true; /* assume y tile may be used */
|
||||
int num_channels = max_t(u8, 1, dev_priv->dram_info.num_channels);
|
||||
int ipqdepth, ipqdepthpch = 16;
|
||||
int dclk_max;
|
||||
int maxdebw, peakbw;
|
||||
int clperchgroup;
|
||||
int num_groups = ARRAY_SIZE(dev_priv->max_bw);
|
||||
int i, ret;
|
||||
|
||||
ret = icl_get_qgv_points(dev_priv, &qi, is_y_tile);
|
||||
if (ret) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Failed to get memory subsystem information, ignoring bandwidth limits");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dram_info->type == INTEL_DRAM_LPDDR4 || dram_info->type == INTEL_DRAM_LPDDR5)
|
||||
num_channels *= 2;
|
||||
|
||||
qi.deinterleave = qi.deinterleave ? : DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
|
||||
|
||||
if (num_channels < qi.max_numchannels && DISPLAY_VER(dev_priv) >= 12)
|
||||
qi.deinterleave = max(DIV_ROUND_UP(qi.deinterleave, 2), 1);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) > 11 && num_channels > qi.max_numchannels)
|
||||
drm_warn(&dev_priv->drm, "Number of channels exceeds max number of channels.");
|
||||
if (qi.max_numchannels != 0)
|
||||
num_channels = min_t(u8, num_channels, qi.max_numchannels);
|
||||
|
||||
dclk_max = icl_sagv_max_dclk(&qi);
|
||||
|
||||
peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max;
|
||||
maxdebw = min(sa->deprogbwlimit * 1000, peakbw * 6 / 10); /* 60% */
|
||||
|
||||
ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
|
||||
/*
|
||||
* clperchgroup = 4kpagespermempage * clperchperblock,
|
||||
* clperchperblock = 8 / num_channels * interleave
|
||||
*/
|
||||
clperchgroup = 4 * DIV_ROUND_UP(8, num_channels) * qi.deinterleave;
|
||||
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
struct intel_bw_info *bi = &dev_priv->max_bw[i];
|
||||
struct intel_bw_info *bi_next;
|
||||
int clpchgroup;
|
||||
int j;
|
||||
|
||||
if (i < num_groups - 1)
|
||||
bi_next = &dev_priv->max_bw[i + 1];
|
||||
|
||||
clpchgroup = (sa->deburst * qi.deinterleave / num_channels) << i;
|
||||
|
||||
if (i < num_groups - 1 && clpchgroup < clperchgroup)
|
||||
bi_next->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
|
||||
else
|
||||
bi_next->num_planes = 0;
|
||||
|
||||
bi->num_qgv_points = qi.num_points;
|
||||
bi->num_psf_gv_points = qi.num_psf_points;
|
||||
|
||||
for (j = 0; j < qi.num_points; j++) {
|
||||
const struct intel_qgv_point *sp = &qi.points[j];
|
||||
int ct, bw;
|
||||
|
||||
/*
|
||||
* Max row cycle time
|
||||
*
|
||||
* FIXME what is the logic behind the
|
||||
* assumed burst length?
|
||||
*/
|
||||
ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd +
|
||||
(clpchgroup - 1) * qi.t_bl + sp->t_rdpre);
|
||||
bw = DIV_ROUND_UP(sp->dclk * clpchgroup * 32 * num_channels, ct);
|
||||
|
||||
bi->deratedbw[j] = min(maxdebw,
|
||||
bw * (100 - sa->derating) / 100);
|
||||
@@ -329,9 +448,6 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
|
||||
"BW%d / PSF GV %d: num_planes=%d bw=%u\n",
|
||||
i, j, bi->num_planes, bi->psf_bw[j]);
|
||||
}
|
||||
|
||||
if (bi->num_planes == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -395,6 +511,34 @@ static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int tgl_max_bw(struct drm_i915_private *dev_priv,
|
||||
int num_planes, int qgv_point)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Let's return max bw for 0 planes
|
||||
*/
|
||||
num_planes = max(1, num_planes);
|
||||
|
||||
for (i = ARRAY_SIZE(dev_priv->max_bw) - 1; i >= 0; i--) {
|
||||
const struct intel_bw_info *bi =
|
||||
&dev_priv->max_bw[i];
|
||||
|
||||
/*
|
||||
* Pcode will not expose all QGV points when
|
||||
* SAGV is forced to off/min/med/max.
|
||||
*/
|
||||
if (qgv_point >= bi->num_qgv_points)
|
||||
return UINT_MAX;
|
||||
|
||||
if (num_planes <= bi->num_planes)
|
||||
return bi->deratedbw[qgv_point];
|
||||
}
|
||||
|
||||
return dev_priv->max_bw[0].deratedbw[qgv_point];
|
||||
}
|
||||
|
||||
static unsigned int adl_psf_bw(struct drm_i915_private *dev_priv,
|
||||
int psf_gv_point)
|
||||
{
|
||||
@@ -412,13 +556,13 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)
|
||||
if (IS_DG2(dev_priv))
|
||||
dg2_get_bw_info(dev_priv);
|
||||
else if (IS_ALDERLAKE_P(dev_priv))
|
||||
icl_get_bw_info(dev_priv, &adlp_sa_info);
|
||||
tgl_get_bw_info(dev_priv, &adlp_sa_info);
|
||||
else if (IS_ALDERLAKE_S(dev_priv))
|
||||
icl_get_bw_info(dev_priv, &adls_sa_info);
|
||||
tgl_get_bw_info(dev_priv, &adls_sa_info);
|
||||
else if (IS_ROCKETLAKE(dev_priv))
|
||||
icl_get_bw_info(dev_priv, &rkl_sa_info);
|
||||
tgl_get_bw_info(dev_priv, &rkl_sa_info);
|
||||
else if (DISPLAY_VER(dev_priv) == 12)
|
||||
icl_get_bw_info(dev_priv, &tgl_sa_info);
|
||||
tgl_get_bw_info(dev_priv, &tgl_sa_info);
|
||||
else if (DISPLAY_VER(dev_priv) == 11)
|
||||
icl_get_bw_info(dev_priv, &icl_sa_info);
|
||||
}
|
||||
@@ -746,7 +890,10 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
|
||||
for (i = 0; i < num_qgv_points; i++) {
|
||||
unsigned int max_data_rate;
|
||||
|
||||
max_data_rate = icl_max_bw(dev_priv, num_active_planes, i);
|
||||
if (DISPLAY_VER(dev_priv) > 11)
|
||||
max_data_rate = tgl_max_bw(dev_priv, num_active_planes, i);
|
||||
else
|
||||
max_data_rate = icl_max_bw(dev_priv, num_active_planes, i);
|
||||
/*
|
||||
* We need to know which qgv point gives us
|
||||
* maximum bandwidth in order to disable SAGV
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/time.h>
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_bw.h"
|
||||
#include "intel_cdclk.h"
|
||||
#include "intel_de.h"
|
||||
@@ -1975,6 +1976,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
intel_psr_pause(intel_dp);
|
||||
}
|
||||
|
||||
intel_audio_cdclk_change_pre(dev_priv);
|
||||
|
||||
/*
|
||||
* Lock aux/gmbus while we change cdclk in case those
|
||||
* functions use cdclk. Not all platforms/ports do,
|
||||
@@ -2003,6 +2006,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
intel_psr_resume(intel_dp);
|
||||
}
|
||||
|
||||
intel_audio_cdclk_change_post(dev_priv);
|
||||
|
||||
if (drm_WARN(&dev_priv->drm,
|
||||
intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
|
||||
"cdclk state doesn't match!\n")) {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dpll.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "vlv_dsi_pll.h"
|
||||
|
||||
#define CTM_COEFF_SIGN (1ULL << 63)
|
||||
|
||||
@@ -552,8 +552,8 @@ static void i9xx_load_lut_8(struct intel_crtc *crtc,
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
intel_de_write(dev_priv, PALETTE(pipe, i),
|
||||
i9xx_lut_8(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, PALETTE(pipe, i),
|
||||
i9xx_lut_8(&lut[i]));
|
||||
}
|
||||
|
||||
static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@@ -576,15 +576,15 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc,
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
for (i = 0; i < lut_size - 1; i++) {
|
||||
intel_de_write(dev_priv, PALETTE(pipe, 2 * i + 0),
|
||||
i965_lut_10p6_ldw(&lut[i]));
|
||||
intel_de_write(dev_priv, PALETTE(pipe, 2 * i + 1),
|
||||
i965_lut_10p6_udw(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 0),
|
||||
i965_lut_10p6_ldw(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, PALETTE(pipe, 2 * i + 1),
|
||||
i965_lut_10p6_udw(&lut[i]));
|
||||
}
|
||||
|
||||
intel_de_write(dev_priv, PIPEGCMAX(pipe, 0), lut[i].red);
|
||||
intel_de_write(dev_priv, PIPEGCMAX(pipe, 1), lut[i].green);
|
||||
intel_de_write(dev_priv, PIPEGCMAX(pipe, 2), lut[i].blue);
|
||||
intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 0), lut[i].red);
|
||||
intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 1), lut[i].green);
|
||||
intel_de_write_fw(dev_priv, PIPEGCMAX(pipe, 2), lut[i].blue);
|
||||
}
|
||||
|
||||
static void i965_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@@ -618,8 +618,8 @@ static void ilk_load_lut_8(struct intel_crtc *crtc,
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
intel_de_write(dev_priv, LGC_PALETTE(pipe, i),
|
||||
i9xx_lut_8(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, LGC_PALETTE(pipe, i),
|
||||
i9xx_lut_8(&lut[i]));
|
||||
}
|
||||
|
||||
static void ilk_load_lut_10(struct intel_crtc *crtc,
|
||||
@@ -631,8 +631,8 @@ static void ilk_load_lut_10(struct intel_crtc *crtc,
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
for (i = 0; i < lut_size; i++)
|
||||
intel_de_write(dev_priv, PREC_PALETTE(pipe, i),
|
||||
ilk_lut_10(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, PREC_PALETTE(pipe, i),
|
||||
ilk_lut_10(&lut[i]));
|
||||
}
|
||||
|
||||
static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@@ -681,16 +681,16 @@ static void ivb_load_lut_10(struct intel_crtc *crtc,
|
||||
const struct drm_color_lut *entry =
|
||||
&lut[i * (lut_size - 1) / (hw_lut_size - 1)];
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), prec_index++);
|
||||
intel_de_write(dev_priv, PREC_PAL_DATA(pipe),
|
||||
ilk_lut_10(entry));
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), prec_index++);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe),
|
||||
ilk_lut_10(entry));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the index, otherwise it prevents the legacy palette to be
|
||||
* written properly.
|
||||
*/
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0);
|
||||
}
|
||||
|
||||
/* On BDW+ the index auto increment mode actually works */
|
||||
@@ -704,23 +704,23 @@ static void bdw_load_lut_10(struct intel_crtc *crtc,
|
||||
int i, lut_size = drm_color_lut_size(blob);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe),
|
||||
prec_index | PAL_PREC_AUTO_INCREMENT);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe),
|
||||
prec_index | PAL_PREC_AUTO_INCREMENT);
|
||||
|
||||
for (i = 0; i < hw_lut_size; i++) {
|
||||
/* We discard half the user entries in split gamma mode */
|
||||
const struct drm_color_lut *entry =
|
||||
&lut[i * (lut_size - 1) / (hw_lut_size - 1)];
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_DATA(pipe),
|
||||
ilk_lut_10(entry));
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe),
|
||||
ilk_lut_10(entry));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the index, otherwise it prevents the legacy palette to be
|
||||
* written properly.
|
||||
*/
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0);
|
||||
}
|
||||
|
||||
static void ivb_load_lut_ext_max(const struct intel_crtc_state *crtc_state)
|
||||
@@ -821,9 +821,9 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
|
||||
* ignore the index bits, so we need to reset it to index 0
|
||||
* separately.
|
||||
*/
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
|
||||
PRE_CSC_GAMC_AUTO_INCREMENT);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
|
||||
PRE_CSC_GAMC_AUTO_INCREMENT);
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
/*
|
||||
@@ -839,15 +839,15 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
|
||||
* ToDo: Extend to max 7.0. Enable 32 bit input value
|
||||
* as compared to just 16 to achieve this.
|
||||
*/
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe),
|
||||
lut[i].green);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe),
|
||||
lut[i].green);
|
||||
}
|
||||
|
||||
/* Clamp values > 1.0. */
|
||||
while (i++ < 35)
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
|
||||
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
}
|
||||
|
||||
static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_state)
|
||||
@@ -862,21 +862,21 @@ static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_stat
|
||||
* ignore the index bits, so we need to reset it to index 0
|
||||
* separately.
|
||||
*/
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
|
||||
PRE_CSC_GAMC_AUTO_INCREMENT);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
|
||||
PRE_CSC_GAMC_AUTO_INCREMENT);
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
u32 v = (i << 16) / (lut_size - 1);
|
||||
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe), v);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), v);
|
||||
}
|
||||
|
||||
/* Clamp values > 1.0. */
|
||||
while (i++ < 35)
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
|
||||
|
||||
intel_de_write(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
|
||||
}
|
||||
|
||||
static void glk_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@@ -1071,10 +1071,10 @@ static void chv_load_cgm_degamma(struct intel_crtc *crtc,
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
intel_de_write(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0),
|
||||
chv_cgm_degamma_ldw(&lut[i]));
|
||||
intel_de_write(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1),
|
||||
chv_cgm_degamma_udw(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0),
|
||||
chv_cgm_degamma_ldw(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1),
|
||||
chv_cgm_degamma_udw(&lut[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1105,10 +1105,10 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc,
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
intel_de_write(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0),
|
||||
chv_cgm_gamma_ldw(&lut[i]));
|
||||
intel_de_write(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1),
|
||||
chv_cgm_gamma_udw(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0),
|
||||
chv_cgm_gamma_ldw(&lut[i]));
|
||||
intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1),
|
||||
chv_cgm_gamma_udw(&lut[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1131,8 +1131,8 @@ static void chv_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
else
|
||||
i965_load_luts(crtc_state);
|
||||
|
||||
intel_de_write(dev_priv, CGM_PIPE_MODE(crtc->pipe),
|
||||
crtc_state->cgm_mode);
|
||||
intel_de_write_fw(dev_priv, CGM_PIPE_MODE(crtc->pipe),
|
||||
crtc_state->cgm_mode);
|
||||
}
|
||||
|
||||
void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@@ -1808,7 +1808,7 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
|
||||
u32 val = intel_de_read(dev_priv, PALETTE(pipe, i));
|
||||
u32 val = intel_de_read_fw(dev_priv, PALETTE(pipe, i));
|
||||
|
||||
i9xx_lut_8_pack(&lut[i], val);
|
||||
}
|
||||
@@ -1843,15 +1843,15 @@ static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < lut_size - 1; i++) {
|
||||
u32 ldw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0));
|
||||
u32 udw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1));
|
||||
u32 ldw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 0));
|
||||
u32 udw = intel_de_read_fw(dev_priv, PALETTE(pipe, 2 * i + 1));
|
||||
|
||||
i965_lut_10p6_pack(&lut[i], ldw, udw);
|
||||
}
|
||||
|
||||
lut[i].red = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 0)));
|
||||
lut[i].green = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 1)));
|
||||
lut[i].blue = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 2)));
|
||||
lut[i].red = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 0)));
|
||||
lut[i].green = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 1)));
|
||||
lut[i].blue = i965_lut_11p6_max_pack(intel_de_read_fw(dev_priv, PIPEGCMAX(pipe, 2)));
|
||||
|
||||
return blob;
|
||||
}
|
||||
@@ -1886,8 +1886,8 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
u32 ldw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0));
|
||||
u32 udw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1));
|
||||
u32 ldw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0));
|
||||
u32 udw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1));
|
||||
|
||||
chv_cgm_gamma_pack(&lut[i], ldw, udw);
|
||||
}
|
||||
@@ -1922,7 +1922,7 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
|
||||
u32 val = intel_de_read(dev_priv, LGC_PALETTE(pipe, i));
|
||||
u32 val = intel_de_read_fw(dev_priv, LGC_PALETTE(pipe, i));
|
||||
|
||||
i9xx_lut_8_pack(&lut[i], val);
|
||||
}
|
||||
@@ -1947,7 +1947,7 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
|
||||
lut = blob->data;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
u32 val = intel_de_read(dev_priv, PREC_PALETTE(pipe, i));
|
||||
u32 val = intel_de_read_fw(dev_priv, PREC_PALETTE(pipe, i));
|
||||
|
||||
ilk_lut_10_pack(&lut[i], val);
|
||||
}
|
||||
@@ -1999,16 +1999,16 @@ static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc,
|
||||
|
||||
lut = blob->data;
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe),
|
||||
prec_index | PAL_PREC_AUTO_INCREMENT);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe),
|
||||
prec_index | PAL_PREC_AUTO_INCREMENT);
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
u32 val = intel_de_read(dev_priv, PREC_PAL_DATA(pipe));
|
||||
u32 val = intel_de_read_fw(dev_priv, PREC_PAL_DATA(pipe));
|
||||
|
||||
ilk_lut_10_pack(&lut[i], val);
|
||||
}
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0);
|
||||
|
||||
return blob;
|
||||
}
|
||||
@@ -2050,17 +2050,17 @@ icl_read_lut_multi_segment(struct intel_crtc *crtc)
|
||||
|
||||
lut = blob->data;
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe),
|
||||
PAL_PREC_AUTO_INCREMENT);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe),
|
||||
PAL_PREC_AUTO_INCREMENT);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
u32 ldw = intel_de_read(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe));
|
||||
u32 udw = intel_de_read(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe));
|
||||
u32 ldw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe));
|
||||
u32 udw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe));
|
||||
|
||||
icl_lut_multi_seg_pack(&lut[i], ldw, udw);
|
||||
}
|
||||
|
||||
intel_de_write(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), 0);
|
||||
intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), 0);
|
||||
|
||||
/*
|
||||
* FIXME readouts from PAL_PREC_DATA register aren't giving
|
||||
|
||||
@@ -301,7 +301,7 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv,
|
||||
|
||||
val = intel_de_read(dev_priv, ICL_PORT_CL_DW10(phy));
|
||||
val &= ~PWR_DOWN_LN_MASK;
|
||||
val |= lane_mask << PWR_DOWN_LN_SHIFT;
|
||||
val |= lane_mask;
|
||||
intel_de_write(dev_priv, ICL_PORT_CL_DW10(phy), val);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_pch_display.h"
|
||||
|
||||
/* Here's the desired hotplug mode */
|
||||
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \
|
||||
@@ -143,7 +144,7 @@ static void intel_crt_get_config(struct intel_encoder *encoder,
|
||||
static void hsw_crt_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
lpt_pch_get_config(pipe_config);
|
||||
|
||||
hsw_ddi_get_config(encoder, pipe_config);
|
||||
|
||||
@@ -152,8 +153,6 @@ static void hsw_crt_get_config(struct intel_encoder *encoder,
|
||||
DRM_MODE_FLAG_PVSYNC |
|
||||
DRM_MODE_FLAG_NVSYNC);
|
||||
pipe_config->hw.adjusted_mode.flags |= intel_crt_get_flags(encoder);
|
||||
|
||||
pipe_config->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv);
|
||||
}
|
||||
|
||||
/* Note: The caller is required to filter out dpms modes not supported by the
|
||||
@@ -247,6 +246,7 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state,
|
||||
const struct intel_crtc_state *old_crtc_state,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
intel_crtc_vblank_off(old_crtc_state);
|
||||
@@ -261,10 +261,9 @@ static void hsw_post_disable_crt(struct intel_atomic_state *state,
|
||||
|
||||
pch_post_disable_crt(state, encoder, old_crtc_state, old_conn_state);
|
||||
|
||||
lpt_disable_pch_transcoder(dev_priv);
|
||||
lpt_disable_iclkip(dev_priv);
|
||||
lpt_pch_disable(state, crtc);
|
||||
|
||||
intel_ddi_fdi_post_disable(state, encoder, old_crtc_state, old_conn_state);
|
||||
hsw_fdi_disable(encoder);
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, !old_crtc_state->has_pch_encoder);
|
||||
|
||||
@@ -316,7 +315,7 @@ static void hsw_enable_crt(struct intel_atomic_state *state,
|
||||
|
||||
intel_enable_transcoder(crtc_state);
|
||||
|
||||
lpt_pch_enable(crtc_state);
|
||||
lpt_pch_enable(state, crtc);
|
||||
|
||||
intel_crtc_vblank_on(crtc_state);
|
||||
|
||||
|
||||
@@ -3,16 +3,18 @@
|
||||
* Copyright © 2020 Intel Corporation
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_vblank_work.h>
|
||||
|
||||
#include "i915_trace.h"
|
||||
#include "i915_vgpu.h"
|
||||
|
||||
#include "icl_dsi.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_atomic_plane.h"
|
||||
#include "intel_color.h"
|
||||
@@ -167,6 +169,8 @@ static void intel_crtc_destroy(struct drm_crtc *_crtc)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(_crtc);
|
||||
|
||||
cpu_latency_qos_remove_request(&crtc->vblank_pm_qos);
|
||||
|
||||
drm_crtc_cleanup(&crtc->base);
|
||||
kfree(crtc);
|
||||
}
|
||||
@@ -344,6 +348,8 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
|
||||
|
||||
intel_crtc_crc_init(crtc);
|
||||
|
||||
cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
|
||||
|
||||
return 0;
|
||||
@@ -354,6 +360,65 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
return crtc_state->hw.active &&
|
||||
!intel_crtc_needs_modeset(crtc_state) &&
|
||||
!crtc_state->preload_luts &&
|
||||
(crtc_state->uapi.color_mgmt_changed ||
|
||||
crtc_state->update_pipe);
|
||||
}
|
||||
|
||||
static void intel_crtc_vblank_work(struct kthread_work *base)
|
||||
{
|
||||
struct drm_vblank_work *work = to_drm_vblank_work(base);
|
||||
struct intel_crtc_state *crtc_state =
|
||||
container_of(work, typeof(*crtc_state), vblank_work);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
trace_intel_crtc_vblank_work_start(crtc);
|
||||
|
||||
intel_color_load_luts(crtc_state);
|
||||
|
||||
if (crtc_state->uapi.event) {
|
||||
spin_lock_irq(&crtc->base.dev->event_lock);
|
||||
drm_crtc_send_vblank_event(&crtc->base, crtc_state->uapi.event);
|
||||
crtc_state->uapi.event = NULL;
|
||||
spin_unlock_irq(&crtc->base.dev->event_lock);
|
||||
}
|
||||
|
||||
trace_intel_crtc_vblank_work_end(crtc);
|
||||
}
|
||||
|
||||
static void intel_crtc_vblank_work_init(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
|
||||
drm_vblank_work_init(&crtc_state->vblank_work, &crtc->base,
|
||||
intel_crtc_vblank_work);
|
||||
/*
|
||||
* Interrupt latency is critical for getting the vblank
|
||||
* work executed as early as possible during the vblank.
|
||||
*/
|
||||
cpu_latency_qos_update_request(&crtc->vblank_pm_qos, 0);
|
||||
}
|
||||
|
||||
void intel_wait_for_vblank_workers(struct intel_atomic_state *state)
|
||||
{
|
||||
struct intel_crtc_state *crtc_state;
|
||||
struct intel_crtc *crtc;
|
||||
int i;
|
||||
|
||||
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
if (!intel_crtc_needs_vblank_work(crtc_state))
|
||||
continue;
|
||||
|
||||
drm_vblank_work_flush(&crtc_state->vblank_work);
|
||||
cpu_latency_qos_update_request(&crtc->vblank_pm_qos,
|
||||
PM_QOS_DEFAULT_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
||||
int usecs)
|
||||
{
|
||||
@@ -387,7 +452,7 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode)
|
||||
* until a subsequent call to intel_pipe_update_end(). That is done to
|
||||
* avoid random delays.
|
||||
*/
|
||||
void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
|
||||
void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
@@ -402,10 +467,17 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
|
||||
if (new_crtc_state->uapi.async_flip)
|
||||
return;
|
||||
|
||||
if (new_crtc_state->vrr.enable)
|
||||
vblank_start = intel_vrr_vmax_vblank_start(new_crtc_state);
|
||||
else
|
||||
if (intel_crtc_needs_vblank_work(new_crtc_state))
|
||||
intel_crtc_vblank_work_init(new_crtc_state);
|
||||
|
||||
if (new_crtc_state->vrr.enable) {
|
||||
if (intel_vrr_is_push_sent(new_crtc_state))
|
||||
vblank_start = intel_vrr_vmin_vblank_start(new_crtc_state);
|
||||
else
|
||||
vblank_start = intel_vrr_vmax_vblank_start(new_crtc_state);
|
||||
} else {
|
||||
vblank_start = intel_mode_vblank_start(adjusted_mode);
|
||||
}
|
||||
|
||||
/* FIXME needs to be calibrated sensibly */
|
||||
min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
|
||||
@@ -554,7 +626,11 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
|
||||
* Would be slightly nice to just grab the vblank count and arm the
|
||||
* event outside of the critical section - the spinlock might spin for a
|
||||
* while ... */
|
||||
if (new_crtc_state->uapi.event) {
|
||||
if (intel_crtc_needs_vblank_work(new_crtc_state)) {
|
||||
drm_vblank_work_schedule(&new_crtc_state->vblank_work,
|
||||
drm_crtc_accurate_vblank_count(&crtc->base) + 1,
|
||||
false);
|
||||
} else if (new_crtc_state->uapi.event) {
|
||||
drm_WARN_ON(&dev_priv->drm,
|
||||
drm_crtc_vblank_get(&crtc->base) != 0);
|
||||
|
||||
@@ -566,11 +642,24 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
|
||||
new_crtc_state->uapi.event = NULL;
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
/* Send VRR Push to terminate Vblank */
|
||||
/*
|
||||
* Send VRR Push to terminate Vblank. If we are already in vblank
|
||||
* this has to be done _after_ sampling the frame counter, as
|
||||
* otherwise the push would immediately terminate the vblank and
|
||||
* the sampled frame counter would correspond to the next frame
|
||||
* instead of the current frame.
|
||||
*
|
||||
* There is a tiny race here (iff vblank evasion failed us) where
|
||||
* we might sample the frame counter just before vmax vblank start
|
||||
* but the push would be sent just after it. That would cause the
|
||||
* push to affect the next frame instead of the current frame,
|
||||
* which would cause the next frame to terminate already at vmin
|
||||
* vblank start instead of vmax vblank start.
|
||||
*/
|
||||
intel_vrr_send_push(new_crtc_state);
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
if (intel_vgpu_active(dev_priv))
|
||||
return;
|
||||
|
||||
|
||||
@@ -9,10 +9,14 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
enum pipe;
|
||||
struct drm_display_mode;
|
||||
struct drm_i915_private;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
|
||||
int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
|
||||
int usecs);
|
||||
u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
|
||||
int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
|
||||
struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
|
||||
@@ -21,5 +25,8 @@ void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
|
||||
u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc);
|
||||
void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state);
|
||||
void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state);
|
||||
void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state);
|
||||
void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state);
|
||||
void intel_wait_for_vblank_workers(struct intel_atomic_state *state);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,11 +28,6 @@ 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 =
|
||||
@@ -195,7 +190,7 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
|
||||
{
|
||||
return CURSOR_ENABLE |
|
||||
CURSOR_FORMAT_ARGB |
|
||||
CURSOR_STRIDE(plane_state->view.color_plane[0].stride);
|
||||
CURSOR_STRIDE(plane_state->view.color_plane[0].mapping_stride);
|
||||
}
|
||||
|
||||
static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
|
||||
@@ -234,7 +229,7 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
|
||||
drm_WARN_ON(&i915->drm, plane_state->uapi.visible &&
|
||||
plane_state->view.color_plane[0].stride != fb->pitches[0]);
|
||||
plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
|
||||
|
||||
switch (fb->pitches[0]) {
|
||||
case 256:
|
||||
@@ -253,9 +248,10 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_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)
|
||||
/* TODO: split into noarm+arm pair */
|
||||
static void i845_cursor_update_arm(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;
|
||||
@@ -298,10 +294,10 @@ static void i845_update_cursor(struct intel_plane *plane,
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i845_disable_cursor(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
static void i845_cursor_disable_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
i845_update_cursor(plane, crtc_state, NULL);
|
||||
i845_cursor_update_arm(plane, crtc_state, NULL);
|
||||
}
|
||||
|
||||
static bool i845_cursor_get_hw_state(struct intel_plane *plane,
|
||||
@@ -455,7 +451,7 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
|
||||
drm_WARN_ON(&dev_priv->drm, plane_state->uapi.visible &&
|
||||
plane_state->view.color_plane[0].stride != fb->pitches[0]);
|
||||
plane_state->view.color_plane[0].mapping_stride != fb->pitches[0]);
|
||||
|
||||
if (fb->pitches[0] !=
|
||||
drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
|
||||
@@ -488,9 +484,10 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_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)
|
||||
/* TODO: split into noarm+arm pair */
|
||||
static void i9xx_cursor_update_arm(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;
|
||||
@@ -562,10 +559,10 @@ static void i9xx_update_cursor(struct intel_plane *plane,
|
||||
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
|
||||
}
|
||||
|
||||
static void i9xx_disable_cursor(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
static void i9xx_cursor_disable_arm(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
i9xx_update_cursor(plane, crtc_state, NULL);
|
||||
i9xx_cursor_update_arm(plane, crtc_state, NULL);
|
||||
}
|
||||
|
||||
static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
|
||||
@@ -605,8 +602,10 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
|
||||
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;
|
||||
if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
|
||||
return false;
|
||||
|
||||
return format == DRM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -717,10 +716,12 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
|
||||
*/
|
||||
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);
|
||||
if (new_plane_state->uapi.visible) {
|
||||
intel_plane_update_noarm(plane, crtc_state, new_plane_state);
|
||||
intel_plane_update_arm(plane, crtc_state, new_plane_state);
|
||||
} else {
|
||||
intel_plane_disable_arm(plane, crtc_state);
|
||||
}
|
||||
|
||||
intel_plane_unpin_fb(old_plane_state);
|
||||
|
||||
@@ -754,6 +755,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
|
||||
{
|
||||
struct intel_plane *cursor;
|
||||
int ret, zpos;
|
||||
u64 *modifiers;
|
||||
|
||||
cursor = intel_plane_alloc();
|
||||
if (IS_ERR(cursor))
|
||||
@@ -766,14 +768,14 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
|
||||
|
||||
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->update_arm = i845_cursor_update_arm;
|
||||
cursor->disable_arm = i845_cursor_disable_arm;
|
||||
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->update_arm = i9xx_cursor_update_arm;
|
||||
cursor->disable_arm = i9xx_cursor_disable_arm;
|
||||
cursor->get_hw_state = i9xx_cursor_get_hw_state;
|
||||
cursor->check_plane = i9xx_check_cursor;
|
||||
}
|
||||
@@ -784,13 +786,18 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
|
||||
if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
|
||||
cursor->cursor.size = ~0;
|
||||
|
||||
modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_NONE);
|
||||
|
||||
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,
|
||||
modifiers,
|
||||
DRM_PLANE_TYPE_CURSOR,
|
||||
"cursor %c", pipe_name(pipe));
|
||||
|
||||
kfree(modifiers);
|
||||
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,11 +6,11 @@
|
||||
#ifndef __INTEL_DDI_H__
|
||||
#define __INTEL_DDI_H__
|
||||
|
||||
#include "intel_display.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
struct drm_connector_state;
|
||||
struct drm_i915_private;
|
||||
struct intel_atomic_state;
|
||||
struct intel_connector;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
@@ -18,6 +18,8 @@ struct intel_dp;
|
||||
struct intel_dpll_hw_state;
|
||||
struct intel_encoder;
|
||||
struct intel_shared_dpll;
|
||||
enum pipe;
|
||||
enum port;
|
||||
enum transcoder;
|
||||
|
||||
i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
|
||||
@@ -30,6 +32,7 @@ void intel_ddi_fdi_post_disable(struct intel_atomic_state *state,
|
||||
const struct drm_connector_state *old_conn_state);
|
||||
void intel_ddi_enable_clock(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_ddi_disable_clock(struct intel_encoder *encoder);
|
||||
void intel_ddi_get_clock(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct intel_shared_dpll *pll);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user