UAPI Changes:

On i915 we have a new UAPI to allow userspace to specify CS ring buffer size on
 construction (I915_CONTEXT_PARAM_RINGSIZE) and also new sysfs entries exposing
 various engine properties
 
 GVT Changes:
 
 VFIO edid getting expanded to all platforms and a big cleanup around attr
 group, unused vblank complete, kvmgt, Intel engine and dev_priv usages.
 
 i915 Changes:
 
 - new UAPI to allow userspace to specify CS ring buffer size on construction
   (I915_CONTEXT_PARAM_RINGSIZE) -  (Chris)
 - New sysfs entries exposing various engine properties (Chris)
 - Tiger Lake is out of require_force_probe protection (Jose)
 - Changes in many places around active requests, reset and heartbeat (Chris)
 - Stop assigning drm-dev_private pointer (Jani)
 - Many code refactor in many places, including intel_modeset_init,
   increasing use of intel_uncore_*, vgpu, and gvt stuff (Jani)
 - Fixes around display pipe iterators (Anshuman)
 - Tigerlake enabling work (Matt Ropper, Matt Atwood, Ville, Lucas, Daniele,
   Jose, Anusha, Vivek, Swathi, Caz. Kai)
 - Code clean-up like reducing use of drm/i915_drv.h, removing unused
   registers, removing garbage warns, and some other code polishing (Jani, Lucas,
   Ville)
 - Selftests fixes, improvements and additions (Chris, Dan, Aditya, Matt Auld)
 - Fix plane possible_crtcs bit mask (Anshuman)
 - Fixes and cleanup on GLK pre production identification and w/a (Ville)
 - Fix display orientation on few cases (Hans, Ville)
 - dbuf clean-up and improvements for slice arrays handling (Ville)
 - Improvement around min cdclk calculation (Stanislav)
 - Fixes and refactor around display PLLs (Imre)
 - Other execlists and perf fixes (Chris)
 - Documentation fixes (Jani, Chris)
 - Fix build issue (Anshuman)
 - Many more fixes around the locking mechanisms (Chris)
 - Other fixes and debugability info around preemption (Chris, Tvrtko)
 - Add mechanism to submit a context WA on ring submission (Mika)
 - Clear all Eu/L3 resitual context (Prathap)
 - More changes around local memory (Abdiel, Matt, Chris)
 - Fix RPS (Chris)
 - DP MST fix (Lyude)
 - Display FBC fixes (Jose, RK)
 - debugfs cleanup (Tvrtko)
 - More convertion towards drm_debive based loggin (Wambui, Ram)
 - Avoid potential buffer overflow (Takashi)
 - Ice Lake and Elkhart Lake workarounds (Matt Roper)
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAl5sIZ0ACgkQ+mJfZA7r
 E8o1LQf+L/Vpm46QQGEyzHINf/gTQvFvumuNAX352vEHaKUgLtTuI7xfpd0c83G1
 5VI+L0Q/ARvakkgfZuHYInlxc9azkcPF1wXb3bLqkoiJ15ydwx5GWjVpZ8uFT+fG
 xzaHBqhqUcvw/kXI1Cy5kIDAlFO9rKLsoLS2qQF9BsYHyxa52ok9/hW+lM7C+vfR
 aYvEr7aAK0o06mqgwc3DHXGuzaS1S9kxtvj9ZkHNsD9iwD4rrEIvW3BPuDqEVkGq
 TkKfThhzJp2FDjXkgCQbLm2BQmxBS0aihwNsQ/lDUUAxcFiuRYwMSoT63vPD1OYI
 lgG0BuJkwK7csJIMrnOs/ZAMeKyTQA==
 =vrB8
 -----END PGP SIGNATURE-----

Merge tag 'drm-intel-next-2020-03-13' of git://anongit.freedesktop.org/drm/drm-intel into drm-next

UAPI Changes:

On i915 we have a new UAPI to allow userspace to specify CS ring buffer size on
construction (I915_CONTEXT_PARAM_RINGSIZE) and also new sysfs entries exposing
various engine properties

GVT Changes:

VFIO edid getting expanded to all platforms and a big cleanup around attr
group, unused vblank complete, kvmgt, Intel engine and dev_priv usages.

i915 Changes:

- new UAPI to allow userspace to specify CS ring buffer size on construction
  (I915_CONTEXT_PARAM_RINGSIZE) -  (Chris)
- New sysfs entries exposing various engine properties (Chris)
- Tiger Lake is out of require_force_probe protection (Jose)
- Changes in many places around active requests, reset and heartbeat (Chris)
- Stop assigning drm-dev_private pointer (Jani)
- Many code refactor in many places, including intel_modeset_init,
  increasing use of intel_uncore_*, vgpu, and gvt stuff (Jani)
- Fixes around display pipe iterators (Anshuman)
- Tigerlake enabling work (Matt Ropper, Matt Atwood, Ville, Lucas, Daniele,
  Jose, Anusha, Vivek, Swathi, Caz. Kai)
- Code clean-up like reducing use of drm/i915_drv.h, removing unused
  registers, removing garbage warns, and some other code polishing (Jani, Lucas,
  Ville)
- Selftests fixes, improvements and additions (Chris, Dan, Aditya, Matt Auld)
- Fix plane possible_crtcs bit mask (Anshuman)
- Fixes and cleanup on GLK pre production identification and w/a (Ville)
- Fix display orientation on few cases (Hans, Ville)
- dbuf clean-up and improvements for slice arrays handling (Ville)
- Improvement around min cdclk calculation (Stanislav)
- Fixes and refactor around display PLLs (Imre)
- Other execlists and perf fixes (Chris)
- Documentation fixes (Jani, Chris)
- Fix build issue (Anshuman)
- Many more fixes around the locking mechanisms (Chris)
- Other fixes and debugability info around preemption (Chris, Tvrtko)
- Add mechanism to submit a context WA on ring submission (Mika)
- Clear all Eu/L3 resitual context (Prathap)
- More changes around local memory (Abdiel, Matt, Chris)
- Fix RPS (Chris)
- DP MST fix (Lyude)
- Display FBC fixes (Jose, RK)
- debugfs cleanup (Tvrtko)
- More convertion towards drm_debive based loggin (Wambui, Ram)
- Avoid potential buffer overflow (Takashi)
- Ice Lake and Elkhart Lake workarounds (Matt Roper)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200314001535.GA2969344@intel.com
This commit is contained in:
Dave Airlie 2020-03-19 10:39:27 +10:00
commit 9001b17698
172 changed files with 6994 additions and 4134 deletions

View File

@ -207,10 +207,10 @@ DPIO
CSR firmware support for DMC
----------------------------
.. kernel-doc:: drivers/gpu/drm/i915/intel_csr.c
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_csr.c
:doc: csr support for dmc
.. kernel-doc:: drivers/gpu/drm/i915/intel_csr.c
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_csr.c
:internal:
Video BIOS Table (VBT)
@ -332,7 +332,7 @@ This process is dubbed relocation.
GEM BO Management Implementation Details
----------------------------------------
.. kernel-doc:: drivers/gpu/drm/i915/i915_vma.h
.. kernel-doc:: drivers/gpu/drm/i915/i915_vma_types.h
:doc: Virtual Memory Address
Buffer Object Eviction
@ -382,7 +382,7 @@ Logical Rings, Logical Ring Contexts and Execlists
Global GTT views
----------------
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_gtt.c
.. kernel-doc:: drivers/gpu/drm/i915/i915_vma_types.h
:doc: Global GTT views
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_gtt.c

View File

@ -1280,6 +1280,85 @@ drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch)
#undef DEVICE_ID_ANY
#undef DEVICE_ID
struct edid_quirk {
u8 mfg_id[2];
u8 prod_id[2];
u32 quirks;
};
#define MFG(first, second) { (first), (second) }
#define PROD_ID(first, second) { (first), (second) }
/*
* Some devices have unreliable OUIDs where they don't set the device ID
* correctly, and as a result we need to use the EDID for finding additional
* DP quirks in such cases.
*/
static const struct edid_quirk edid_quirk_list[] = {
/* Optional 4K AMOLED panel in the ThinkPad X1 Extreme 2nd Generation
* only supports DPCD backlight controls
*/
{ MFG(0x4c, 0x83), PROD_ID(0x41, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
/*
* Some Dell CML 2020 systems have panels support both AUX and PWM
* backlight control, and some only support AUX backlight control. All
* said panels start up in AUX mode by default, and we don't have any
* support for disabling HDR mode on these panels which would be
* required to switch to PWM backlight control mode (plus, I'm not
* even sure we want PWM backlight controls over DPCD backlight
* controls anyway...). Until we have a better way of detecting these,
* force DPCD backlight mode on all of them.
*/
{ MFG(0x06, 0xaf), PROD_ID(0x9b, 0x32), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
{ MFG(0x06, 0xaf), PROD_ID(0xeb, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
{ MFG(0x4d, 0x10), PROD_ID(0xc7, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
{ MFG(0x4d, 0x10), PROD_ID(0xe6, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
};
#undef MFG
#undef PROD_ID
/**
* drm_dp_get_edid_quirks() - Check the EDID of a DP device to find additional
* DP-specific quirks
* @edid: The EDID to check
*
* While OUIDs are meant to be used to recognize a DisplayPort device, a lot
* of manufacturers don't seem to like following standards and neglect to fill
* the dev-ID in, making it impossible to only use OUIDs for determining
* quirks in some cases. This function can be used to check the EDID and look
* up any additional DP quirks. The bits returned by this function correspond
* to the quirk bits in &drm_dp_quirk.
*
* Returns: a bitmask of quirks, if any. The driver can check this using
* drm_dp_has_quirk().
*/
u32 drm_dp_get_edid_quirks(const struct edid *edid)
{
const struct edid_quirk *quirk;
u32 quirks = 0;
int i;
if (!edid)
return 0;
for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
quirk = &edid_quirk_list[i];
if (memcmp(quirk->mfg_id, edid->mfg_id,
sizeof(edid->mfg_id)) == 0 &&
memcmp(quirk->prod_id, edid->prod_code,
sizeof(edid->prod_code)) == 0)
quirks |= quirk->quirks;
}
DRM_DEBUG_KMS("DP sink: EDID mfg %*phD prod-ID %*phD quirks: 0x%04x\n",
(int)sizeof(edid->mfg_id), edid->mfg_id,
(int)sizeof(edid->prod_code), edid->prod_code, quirks);
return quirks;
}
EXPORT_SYMBOL(drm_dp_get_edid_quirks);
/**
* drm_dp_read_desc - read sink/branch descriptor from DPCD
* @aux: DisplayPort AUX channel

View File

@ -5472,7 +5472,8 @@ struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port)
if (drm_dp_read_desc(port->mgr->aux, &desc, true))
return NULL;
if (drm_dp_has_quirk(&desc, DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) &&
if (drm_dp_has_quirk(&desc, 0,
DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) &&
port->mgr->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14 &&
port->parent == port->mgr->mst_primary) {
u8 downstreamport;

View File

@ -20,6 +20,9 @@ config DRM_I915_HEARTBEAT_INTERVAL
check the health of the GPU and undertake regular house-keeping of
internal driver state.
This is adjustable via
/sys/class/drm/card?/engine/*/heartbeat_interval_ms
May be 0 to disable heartbeats and therefore disable automatic GPU
hang detection.
@ -33,11 +36,18 @@ config DRM_I915_PREEMPT_TIMEOUT
expires, the HW will be reset to allow the more important context
to execute.
This is adjustable via
/sys/class/drm/card?/engine/*/preempt_timeout_ms
May be 0 to disable the timeout.
config DRM_I915_SPIN_REQUEST
int "Busywait for request completion (us)"
default 5 # microseconds
The compiled in default may get overridden at driver probe time on
certain platforms and certain engines which will be reflected in the
sysfs control.
config DRM_I915_MAX_REQUEST_BUSYWAIT
int "Busywait for request completion limit (ns)"
default 8000 # nanoseconds
help
Before sleeping waiting for a request (GPU operation) to complete,
we may spend some time polling for its completion. As the IRQ may
@ -45,6 +55,9 @@ config DRM_I915_SPIN_REQUEST
check if the request will complete in the time it would have taken
us to enable the interrupt.
This is adjustable via
/sys/class/drm/card?/engine/*/max_busywait_duration_ns
May be 0 to disable the initial spin. In practice, we estimate
the cost of enabling the interrupt (if currently disabled) to be
a few microseconds.
@ -60,6 +73,9 @@ config DRM_I915_STOP_TIMEOUT
that the reset itself may take longer and so be more disruptive to
interactive or low latency workloads.
This is adjustable via
/sys/class/drm/card?/engine/*/stop_timeout_ms
config DRM_I915_TIMESLICE_DURATION
int "Scheduling quantum for userspace batches (ms, jiffy granularity)"
default 1 # milliseconds
@ -73,4 +89,7 @@ config DRM_I915_TIMESLICE_DURATION
is scheduled for execution for the timeslice duration, before
switching to the next context.
This is adjustable via
/sys/class/drm/card?/engine/*/timeslice_duration_ms
May be 0 to disable timeslicing.

View File

@ -47,6 +47,7 @@ i915-y += i915_drv.o \
i915_sysfs.o \
i915_utils.o \
intel_device_info.o \
intel_dram.o \
intel_memory_region.o \
intel_pch.o \
intel_pm.o \
@ -79,9 +80,11 @@ gt-y += \
gt/debugfs_gt.o \
gt/debugfs_gt_pm.o \
gt/gen6_ppgtt.o \
gt/gen7_renderclear.o \
gt/gen8_ppgtt.o \
gt/intel_breadcrumbs.o \
gt/intel_context.o \
gt/intel_context_param.o \
gt/intel_context_sseu.o \
gt/intel_engine_cs.o \
gt/intel_engine_heartbeat.o \
@ -107,7 +110,8 @@ gt-y += \
gt/intel_rps.o \
gt/intel_sseu.o \
gt/intel_timeline.o \
gt/intel_workarounds.o
gt/intel_workarounds.o \
gt/sysfs_engines.o
# autogenerated null render state
gt-y += \
gt/gen6_renderstate.o \

View File

@ -599,13 +599,13 @@ static void gen11_dsi_gate_clocks(struct intel_encoder *encoder)
u32 tmp;
enum phy phy;
mutex_lock(&dev_priv->dpll_lock);
mutex_lock(&dev_priv->dpll.lock);
tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys)
tmp |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
mutex_unlock(&dev_priv->dpll_lock);
mutex_unlock(&dev_priv->dpll.lock);
}
static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
@ -615,13 +615,13 @@ static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
u32 tmp;
enum phy phy;
mutex_lock(&dev_priv->dpll_lock);
mutex_lock(&dev_priv->dpll.lock);
tmp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys)
tmp &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, tmp);
mutex_unlock(&dev_priv->dpll_lock);
mutex_unlock(&dev_priv->dpll.lock);
}
static void gen11_dsi_map_pll(struct intel_encoder *encoder,
@ -633,7 +633,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
enum phy phy;
u32 val;
mutex_lock(&dev_priv->dpll_lock);
mutex_lock(&dev_priv->dpll.lock);
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
for_each_dsi_phy(phy, intel_dsi->phys) {
@ -652,7 +652,7 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
intel_de_posting_read(dev_priv, ICL_DPCLKA_CFGCR0);
mutex_unlock(&dev_priv->dpll_lock);
mutex_unlock(&dev_priv->dpll.lock);
}
static void
@ -1350,15 +1350,15 @@ static void gen11_dsi_get_timings(struct intel_encoder *encoder,
static void gen11_dsi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
intel_dsc_get_config(encoder, pipe_config);
/* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */
pipe_config->port_clock =
cnl_calc_wrpll_link(dev_priv, &pipe_config->dpll_hw_state);
pipe_config->port_clock = intel_dpll_get_freq(i915,
pipe_config->shared_dpll);
pipe_config->hw.adjusted_mode.crtc_clock = intel_dsi->pclk;
if (intel_dsi->dual_link)

View File

@ -133,15 +133,37 @@ intel_plane_destroy_state(struct drm_plane *plane,
kfree(plane_state);
}
unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
unsigned int src_w, src_h, dst_w, dst_h;
unsigned int pixel_rate = crtc_state->pixel_rate;
src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
dst_w = drm_rect_width(&plane_state->uapi.dst);
dst_h = drm_rect_height(&plane_state->uapi.dst);
/* Downscaling limits the maximum pixel rate */
dst_w = min(src_w, dst_w);
dst_h = min(src_h, dst_h);
return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, src_w * src_h),
dst_w * dst_h);
}
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int cpp;
unsigned int pixel_rate;
if (!plane_state->uapi.visible)
return 0;
pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
cpp = fb->format->cpp[0];
/*
@ -153,7 +175,7 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
if (fb->format->is_yuv && fb->format->num_planes > 1)
cpp *= 4;
return cpp * crtc_state->pixel_rate;
return pixel_rate * cpp;
}
int intel_plane_calc_min_cdclk(struct intel_atomic_state *state,

View File

@ -18,6 +18,9 @@ struct intel_plane_state;
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state,

View File

@ -149,6 +149,10 @@ static const struct {
{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 },
{ 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 },
{ 296703, AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 },
{ 297000, AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 },
{ 593407, AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 },
{ 594000, AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 },
};
/* HDMI N/CTS table */
@ -234,6 +238,7 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = {
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int i;
@ -243,6 +248,9 @@ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_sta
break;
}
if (INTEL_GEN(dev_priv) < 12 && adjusted_mode->crtc_clock > 148500)
i = ARRAY_SIZE(hdmi_audio_clock);
if (i == ARRAY_SIZE(hdmi_audio_clock)) {
DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n",
adjusted_mode->crtc_clock);
@ -844,7 +852,7 @@ static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv,
struct intel_crtc *crtc;
int ret;
crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
crtc = intel_get_first_crtc(dev_priv);
if (!crtc)
return;

View File

@ -26,7 +26,6 @@
*/
#include <drm/drm_dp_helper.h>
#include <drm/i915_drm.h>
#include "display/intel_display.h"
#include "display/intel_display_types.h"

View File

@ -32,8 +32,6 @@
#include <linux/types.h>
#include <drm/i915_drm.h>
struct drm_i915_private;
struct intel_crtc_state;
struct intel_encoder;

View File

@ -1868,6 +1868,8 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
{
struct intel_encoder *encoder;
if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config))
return;
@ -1876,8 +1878,28 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv,
intel_dump_cdclk_config(cdclk_config, "Changing CDCLK to");
/*
* Lock aux/gmbus while we change cdclk in case those
* functions use cdclk. Not all platforms/ports do,
* but we'll lock them all for simplicity.
*/
mutex_lock(&dev_priv->gmbus_mutex);
for_each_intel_dp(&dev_priv->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
mutex_lock_nest_lock(&intel_dp->aux.hw_mutex,
&dev_priv->gmbus_mutex);
}
dev_priv->display.set_cdclk(dev_priv, cdclk_config, pipe);
for_each_intel_dp(&dev_priv->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
mutex_unlock(&intel_dp->aux.hw_mutex);
}
mutex_unlock(&dev_priv->gmbus_mutex);
if (drm_WARN(&dev_priv->drm,
intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
"cdclk state doesn't match!\n")) {

View File

@ -348,48 +348,56 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
crtc_state->csc_mode);
}
/*
* Set up the pipe CSC unit on CherryView.
*/
static void cherryview_load_csc_matrix(const struct intel_crtc_state *crtc_state)
static void chv_load_cgm_csc(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_color_ctm *ctm = blob->data;
enum pipe pipe = crtc->pipe;
u16 coeffs[9];
int i;
if (crtc_state->hw.ctm) {
const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
u16 coeffs[9] = {};
int i;
for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
u64 abs_coeff = ((1ULL << 63) - 1) & ctm->matrix[i];
for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
u64 abs_coeff =
((1ULL << 63) - 1) & ctm->matrix[i];
/* Round coefficient. */
abs_coeff += 1 << (32 - 13);
/* Clamp to hardware limits. */
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
/* Round coefficient. */
abs_coeff += 1 << (32 - 13);
/* Clamp to hardware limits. */
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
coeffs[i] = 0;
/* Write coefficients in S3.12 format. */
if (ctm->matrix[i] & (1ULL << 63))
coeffs[i] = 1 << 15;
coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
coeffs[i] |= (abs_coeff >> 20) & 0xfff;
}
/* Write coefficients in S3.12 format. */
if (ctm->matrix[i] & (1ULL << 63))
coeffs[i] |= 1 << 15;
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF01(pipe),
coeffs[1] << 16 | coeffs[0]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF23(pipe),
coeffs[3] << 16 | coeffs[2]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF45(pipe),
coeffs[5] << 16 | coeffs[4]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF67(pipe),
coeffs[7] << 16 | coeffs[6]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
coeffs[i] |= (abs_coeff >> 20) & 0xfff;
}
intel_de_write(dev_priv, CGM_PIPE_MODE(pipe), crtc_state->cgm_mode);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF01(pipe),
coeffs[1] << 16 | coeffs[0]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF23(pipe),
coeffs[3] << 16 | coeffs[2]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF45(pipe),
coeffs[5] << 16 | coeffs[4]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF67(pipe),
coeffs[7] << 16 | coeffs[6]);
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF8(pipe),
coeffs[8]);
}
/* convert hw value with given bit_precision to lut property val */
static u32 intel_color_lut_pack(u32 val, int bit_precision)
{
u32 max = 0xffff >> (16 - bit_precision);
val = clamp_val(val, 0, max);
if (bit_precision < 16)
val <<= 16 - bit_precision;
return val;
}
static u32 i9xx_lut_8(const struct drm_color_lut *color)
@ -399,6 +407,13 @@ static u32 i9xx_lut_8(const struct drm_color_lut *color)
drm_color_lut_extract(color->blue, 8);
}
static void i9xx_lut_8_pack(struct drm_color_lut *entry, u32 val)
{
entry->red = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_RED_MASK, val), 8);
entry->green = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_GREEN_MASK, val), 8);
entry->blue = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_BLUE_MASK, val), 8);
}
/* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */
static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color)
{
@ -415,6 +430,22 @@ static u32 i965_lut_10p6_udw(const struct drm_color_lut *color)
(color->blue >> 8);
}
static void i965_lut_10p6_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
{
entry->red = REG_FIELD_GET(PALETTE_RED_MASK, udw) << 8 |
REG_FIELD_GET(PALETTE_RED_MASK, ldw);
entry->green = REG_FIELD_GET(PALETTE_GREEN_MASK, udw) << 8 |
REG_FIELD_GET(PALETTE_GREEN_MASK, ldw);
entry->blue = REG_FIELD_GET(PALETTE_BLUE_MASK, udw) << 8 |
REG_FIELD_GET(PALETTE_BLUE_MASK, ldw);
}
static u16 i965_lut_11p6_max_pack(u32 val)
{
/* PIPEGCMAX is 11.6, clamp to 10.6 */
return clamp_val(val, 0, 0xffff);
}
static u32 ilk_lut_10(const struct drm_color_lut *color)
{
return drm_color_lut_extract(color->red, 10) << 20 |
@ -422,41 +453,11 @@ static u32 ilk_lut_10(const struct drm_color_lut *color)
drm_color_lut_extract(color->blue, 10);
}
/* Loads the legacy palette/gamma unit for the CRTC. */
static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob)
static void ilk_lut_10_pack(struct drm_color_lut *entry, u32 val)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
int i;
if (HAS_GMCH(dev_priv)) {
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
assert_dsi_pll_enabled(dev_priv);
else
assert_pll_enabled(dev_priv, pipe);
}
if (blob) {
const struct drm_color_lut *lut = blob->data;
for (i = 0; i < 256; i++) {
u32 word = i9xx_lut_8(&lut[i]);
if (HAS_GMCH(dev_priv))
intel_de_write(dev_priv, PALETTE(pipe, i),
word);
else
intel_de_write(dev_priv, LGC_PALETTE(pipe, i),
word);
}
}
}
static void i9xx_load_luts(const struct intel_crtc_state *crtc_state)
{
i9xx_load_luts_internal(crtc_state, crtc_state->hw.gamma_lut);
entry->red = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_RED_MASK, val), 10);
entry->green = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_GREEN_MASK, val), 10);
entry->blue = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_BLUE_MASK, val), 10);
}
static void i9xx_color_commit(const struct intel_crtc_state *crtc_state)
@ -525,6 +526,35 @@ static void skl_color_commit(const struct intel_crtc_state *crtc_state)
ilk_load_csc_matrix(crtc_state);
}
static void i9xx_load_lut_8(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_color_lut *lut;
enum pipe pipe = crtc->pipe;
int i;
if (!blob)
return;
lut = blob->data;
for (i = 0; i < 256; i++)
intel_de_write(dev_priv, PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
}
static void i9xx_load_luts(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);
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
assert_pll_enabled(dev_priv, crtc->pipe);
i9xx_load_lut_8(crtc, gamma_lut);
}
static void i965_load_lut_10p6(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
@ -548,14 +578,38 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc,
static void i965_load_luts(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);
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
assert_dsi_pll_enabled(dev_priv);
else
assert_pll_enabled(dev_priv, crtc->pipe);
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
i9xx_load_luts(crtc_state);
i9xx_load_lut_8(crtc, gamma_lut);
else
i965_load_lut_10p6(crtc, gamma_lut);
}
static void ilk_load_lut_8(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_color_lut *lut;
enum pipe pipe = crtc->pipe;
int i;
if (!blob)
return;
lut = blob->data;
for (i = 0; i < 256; i++)
intel_de_write(dev_priv, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
}
static void ilk_load_lut_10(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
@ -566,7 +620,7 @@ static void ilk_load_lut_10(struct intel_crtc *crtc,
for (i = 0; i < lut_size; i++)
intel_de_write(dev_priv, PREC_PALETTE(pipe, i),
ilk_lut_10(&lut[i]));
ilk_lut_10(&lut[i]));
}
static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
@ -575,7 +629,7 @@ static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
i9xx_load_luts(crtc_state);
ilk_load_lut_8(crtc, gamma_lut);
else
ilk_load_lut_10(crtc, gamma_lut);
}
@ -685,7 +739,7 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
i9xx_load_luts(crtc_state);
ilk_load_lut_8(crtc, gamma_lut);
} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(0));
@ -708,7 +762,7 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
i9xx_load_luts(crtc_state);
ilk_load_lut_8(crtc, gamma_lut);
} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(0));
@ -729,9 +783,8 @@ static void glk_load_degamma_lut(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);
enum pipe pipe = crtc->pipe;
const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data;
u32 i;
/*
* When setting the auto-increment bit, the hardware seems to
@ -770,8 +823,7 @@ static void glk_load_degamma_lut_linear(const struct intel_crtc_state *crtc_stat
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
const u32 lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
u32 i;
int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
/*
* When setting the auto-increment bit, the hardware seems to
@ -812,7 +864,7 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state)
glk_load_degamma_lut_linear(crtc_state);
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
i9xx_load_luts(crtc_state);
ilk_load_lut_8(crtc, gamma_lut);
} else {
bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
ivb_load_lut_ext_max(crtc);
@ -856,7 +908,7 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
const struct drm_color_lut *lut = blob->data;
struct intel_dsb *dsb = intel_dsb_get(crtc);
enum pipe pipe = crtc->pipe;
u32 i;
int i;
/*
* Program Super Fine segment (let's call it seg1)...
@ -889,7 +941,7 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
const struct drm_color_lut *entry;
struct intel_dsb *dsb = intel_dsb_get(crtc);
enum pipe pipe = crtc->pipe;
u32 i;
int i;
/*
* Program Fine segment (let's call it seg2)...
@ -948,7 +1000,7 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
case GAMMA_MODE_MODE_8BIT:
i9xx_load_luts(crtc_state);
ilk_load_lut_8(crtc, gamma_lut);
break;
case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
icl_program_gamma_superfine_segment(crtc_state);
@ -974,6 +1026,13 @@ static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color)
return drm_color_lut_extract(color->red, 14);
}
static void chv_cgm_gamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
{
entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_GREEN_MASK, ldw), 10);
entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_BLUE_MASK, ldw), 10);
entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_RED_MASK, udw), 10);
}
static void chv_load_cgm_degamma(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
@ -1020,21 +1079,24 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc,
static void chv_load_luts(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
const struct drm_property_blob *ctm = crtc_state->hw.ctm;
cherryview_load_csc_matrix(crtc_state);
if (crtc_state->cgm_mode & CGM_PIPE_MODE_CSC)
chv_load_cgm_csc(crtc, ctm);
if (crtc_state_is_legacy_gamma(crtc_state)) {
i9xx_load_luts(crtc_state);
return;
}
if (degamma_lut)
if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
chv_load_cgm_degamma(crtc, degamma_lut);
if (gamma_lut)
if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
chv_load_cgm_gamma(crtc, gamma_lut);
else
i965_load_luts(crtc_state);
intel_de_write(dev_priv, CGM_PIPE_MODE(crtc->pipe),
crtc_state->cgm_mode);
}
void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
@ -1660,28 +1722,13 @@ bool intel_color_lut_equal(struct drm_property_blob *blob1,
return true;
}
/* convert hw value with given bit_precision to lut property val */
static u32 intel_color_lut_pack(u32 val, u32 bit_precision)
static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
{
u32 max = 0xffff >> (16 - bit_precision);
val = clamp_val(val, 0, max);
if (bit_precision < 16)
val <<= 16 - bit_precision;
return val;
}
static struct drm_property_blob *
i9xx_read_lut_8(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);
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *blob_data;
u32 i, val;
struct drm_color_lut *lut;
int i;
blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH,
@ -1689,20 +1736,12 @@ i9xx_read_lut_8(const struct intel_crtc_state *crtc_state)
if (IS_ERR(blob))
return NULL;
blob_data = blob->data;
lut = blob->data;
for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
if (HAS_GMCH(dev_priv))
val = intel_de_read(dev_priv, PALETTE(pipe, i));
else
val = intel_de_read(dev_priv, LGC_PALETTE(pipe, i));
u32 val = intel_de_read(dev_priv, PALETTE(pipe, i));
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
LGC_PALETTE_RED_MASK, val), 8);
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
LGC_PALETTE_GREEN_MASK, val), 8);
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
LGC_PALETTE_BLUE_MASK, val), 8);
i9xx_lut_8_pack(&lut[i], val);
}
return blob;
@ -1710,22 +1749,21 @@ i9xx_read_lut_8(const struct intel_crtc_state *crtc_state)
static void i9xx_read_luts(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (!crtc_state->gamma_enable)
return;
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc);
}
static struct drm_property_blob *
i965_read_lut_10p6(const struct intel_crtc_state *crtc_state)
static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *blob_data;
u32 i, val1, val2;
struct drm_color_lut *lut;
blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * lut_size,
@ -1733,51 +1771,42 @@ i965_read_lut_10p6(const struct intel_crtc_state *crtc_state)
if (IS_ERR(blob))
return NULL;
blob_data = blob->data;
lut = blob->data;
for (i = 0; i < lut_size - 1; i++) {
val1 = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0));
val2 = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1));
u32 ldw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0));
u32 udw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1));
blob_data[i].red = REG_FIELD_GET(PALETTE_RED_MASK, val2) << 8 |
REG_FIELD_GET(PALETTE_RED_MASK, val1);
blob_data[i].green = REG_FIELD_GET(PALETTE_GREEN_MASK, val2) << 8 |
REG_FIELD_GET(PALETTE_GREEN_MASK, val1);
blob_data[i].blue = REG_FIELD_GET(PALETTE_BLUE_MASK, val2) << 8 |
REG_FIELD_GET(PALETTE_BLUE_MASK, val1);
i965_lut_10p6_pack(&lut[i], ldw, udw);
}
blob_data[i].red = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
intel_de_read(dev_priv, PIPEGCMAX(pipe, 0)));
blob_data[i].green = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
intel_de_read(dev_priv, PIPEGCMAX(pipe, 1)));
blob_data[i].blue = REG_FIELD_GET(PIPEGCMAX_RGB_MASK,
intel_de_read(dev_priv, PIPEGCMAX(pipe, 2)));
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)));
return blob;
}
static void i965_read_luts(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (!crtc_state->gamma_enable)
return;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc);
else
crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc_state);
crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc);
}
static struct drm_property_blob *
chv_read_cgm_lut(const struct intel_crtc_state *crtc_state)
static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *blob_data;
u32 i, val;
struct drm_color_lut *lut;
blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * lut_size,
@ -1785,18 +1814,13 @@ chv_read_cgm_lut(const struct intel_crtc_state *crtc_state)
if (IS_ERR(blob))
return NULL;
blob_data = blob->data;
lut = blob->data;
for (i = 0; i < lut_size; i++) {
val = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0));
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
CGM_PIPE_GAMMA_GREEN_MASK, val), 10);
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
CGM_PIPE_GAMMA_BLUE_MASK, val), 10);
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));
val = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1));
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
CGM_PIPE_GAMMA_RED_MASK, val), 10);
chv_cgm_gamma_pack(&lut[i], ldw, udw);
}
return blob;
@ -1804,22 +1828,46 @@ chv_read_cgm_lut(const struct intel_crtc_state *crtc_state)
static void chv_read_luts(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
crtc_state->hw.gamma_lut = chv_read_cgm_lut(crtc_state);
crtc_state->hw.gamma_lut = chv_read_cgm_gamma(crtc);
else
i965_read_luts(crtc_state);
}
static struct drm_property_blob *
ilk_read_lut_10(const struct intel_crtc_state *crtc_state)
static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
u32 lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *blob_data;
u32 i, val;
struct drm_color_lut *lut;
int i;
blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH,
NULL);
if (IS_ERR(blob))
return NULL;
lut = blob->data;
for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
u32 val = intel_de_read(dev_priv, LGC_PALETTE(pipe, i));
i9xx_lut_8_pack(&lut[i], val);
}
return blob;
}
static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * lut_size,
@ -1827,17 +1875,12 @@ ilk_read_lut_10(const struct intel_crtc_state *crtc_state)
if (IS_ERR(blob))
return NULL;
blob_data = blob->data;
lut = blob->data;
for (i = 0; i < lut_size; i++) {
val = intel_de_read(dev_priv, PREC_PALETTE(pipe, i));
u32 val = intel_de_read(dev_priv, PREC_PALETTE(pipe, i));
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
PREC_PALETTE_RED_MASK, val), 10);
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
PREC_PALETTE_GREEN_MASK, val), 10);
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
PREC_PALETTE_BLUE_MASK, val), 10);
ilk_lut_10_pack(&lut[i], val);
}
return blob;
@ -1845,6 +1888,8 @@ ilk_read_lut_10(const struct intel_crtc_state *crtc_state)
static void ilk_read_luts(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (!crtc_state->gamma_enable)
return;
@ -1852,21 +1897,19 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state)
return;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc);
else
crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc_state);
crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc);
}
static struct drm_property_blob *
glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index)
static struct drm_property_blob *glk_read_lut_10(struct intel_crtc *crtc,
u32 prec_index)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
int hw_lut_size = ivb_lut_10_size(prec_index);
int i, hw_lut_size = ivb_lut_10_size(prec_index);
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *blob_data;
u32 i, val;
struct drm_color_lut *lut;
blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * hw_lut_size,
@ -1874,20 +1917,15 @@ glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index)
if (IS_ERR(blob))
return NULL;
blob_data = blob->data;
lut = blob->data;
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe),
prec_index | PAL_PREC_AUTO_INCREMENT);
for (i = 0; i < hw_lut_size; i++) {
val = intel_de_read(dev_priv, PREC_PAL_DATA(pipe));
u32 val = intel_de_read(dev_priv, PREC_PAL_DATA(pipe));
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
PREC_PAL_DATA_RED_MASK, val), 10);
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET(
PREC_PAL_DATA_GREEN_MASK, val), 10);
blob_data[i].blue = intel_color_lut_pack(REG_FIELD_GET(
PREC_PAL_DATA_BLUE_MASK, val), 10);
ilk_lut_10_pack(&lut[i], val);
}
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0);
@ -1897,13 +1935,15 @@ glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index)
static void glk_read_luts(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
if (!crtc_state->gamma_enable)
return;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc_state);
crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc);
else
crtc_state->hw.gamma_lut = glk_read_lut_10(crtc_state, PAL_PREC_INDEX_VALUE(0));
crtc_state->hw.gamma_lut = glk_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
}
void intel_color_init(struct intel_crtc *crtc)

View File

@ -32,7 +32,6 @@
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_probe_helper.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_connector.h"

View File

@ -40,8 +40,8 @@
#define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE
#define TGL_CSR_PATH "i915/tgl_dmc_ver2_04.bin"
#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 4)
#define TGL_CSR_PATH "i915/tgl_dmc_ver2_06.bin"
#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 6)
#define TGL_CSR_MAX_FW_SIZE 0x6000
MODULE_FIRMWARE(TGL_CSR_PATH);

View File

@ -1325,164 +1325,6 @@ intel_ddi_get_crtc_encoder(struct intel_crtc *crtc)
return ret;
}
static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
i915_reg_t reg)
{
int refclk;
int n, p, r;
u32 wrpll;
wrpll = intel_de_read(dev_priv, reg);
switch (wrpll & WRPLL_REF_MASK) {
case WRPLL_REF_SPECIAL_HSW:
/*
* muxed-SSC for BDW.
* non-SSC for non-ULT HSW. Check FUSE_STRAP3
* for the non-SSC reference frequency.
*/
if (IS_HASWELL(dev_priv) && !IS_HSW_ULT(dev_priv)) {
if (intel_de_read(dev_priv, FUSE_STRAP3) & HSW_REF_CLK_SELECT)
refclk = 24;
else
refclk = 135;
break;
}
/* fall through */
case WRPLL_REF_PCH_SSC:
/*
* We could calculate spread here, but our checking
* code only cares about 5% accuracy, and spread is a max of
* 0.5% downspread.
*/
refclk = 135;
break;
case WRPLL_REF_LCPLL:
refclk = 2700;
break;
default:
MISSING_CASE(wrpll);
return 0;
}
r = wrpll & WRPLL_DIVIDER_REF_MASK;
p = (wrpll & WRPLL_DIVIDER_POST_MASK) >> WRPLL_DIVIDER_POST_SHIFT;
n = (wrpll & WRPLL_DIVIDER_FB_MASK) >> WRPLL_DIVIDER_FB_SHIFT;
/* Convert to KHz, p & r have a fixed point portion */
return (refclk * n * 100) / (p * r);
}
static int skl_calc_wrpll_link(const struct intel_dpll_hw_state *pll_state)
{
u32 p0, p1, p2, dco_freq;
p0 = pll_state->cfgcr2 & DPLL_CFGCR2_PDIV_MASK;
p2 = pll_state->cfgcr2 & DPLL_CFGCR2_KDIV_MASK;
if (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_MODE(1))
p1 = (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8;
else
p1 = 1;
switch (p0) {
case DPLL_CFGCR2_PDIV_1:
p0 = 1;
break;
case DPLL_CFGCR2_PDIV_2:
p0 = 2;
break;
case DPLL_CFGCR2_PDIV_3:
p0 = 3;
break;
case DPLL_CFGCR2_PDIV_7:
p0 = 7;
break;
}
switch (p2) {
case DPLL_CFGCR2_KDIV_5:
p2 = 5;
break;
case DPLL_CFGCR2_KDIV_2:
p2 = 2;
break;
case DPLL_CFGCR2_KDIV_3:
p2 = 3;
break;
case DPLL_CFGCR2_KDIV_1:
p2 = 1;
break;
}
dco_freq = (pll_state->cfgcr1 & DPLL_CFGCR1_DCO_INTEGER_MASK)
* 24 * 1000;
dco_freq += (((pll_state->cfgcr1 & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9)
* 24 * 1000) / 0x8000;
if (WARN_ON(p0 == 0 || p1 == 0 || p2 == 0))
return 0;
return dco_freq / (p0 * p1 * p2 * 5);
}
int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
struct intel_dpll_hw_state *pll_state)
{
u32 p0, p1, p2, dco_freq, ref_clock;
p0 = pll_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK;
p2 = pll_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK;
if (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1))
p1 = (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >>
DPLL_CFGCR1_QDIV_RATIO_SHIFT;
else
p1 = 1;
switch (p0) {
case DPLL_CFGCR1_PDIV_2:
p0 = 2;
break;
case DPLL_CFGCR1_PDIV_3:
p0 = 3;
break;
case DPLL_CFGCR1_PDIV_5:
p0 = 5;
break;
case DPLL_CFGCR1_PDIV_7:
p0 = 7;
break;
}
switch (p2) {
case DPLL_CFGCR1_KDIV_1:
p2 = 1;
break;
case DPLL_CFGCR1_KDIV_2:
p2 = 2;
break;
case DPLL_CFGCR1_KDIV_3:
p2 = 3;
break;
}
ref_clock = cnl_hdmi_pll_ref_clock(dev_priv);
dco_freq = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK)
* ref_clock;
dco_freq += (((pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >>
DPLL_CFGCR0_DCO_FRACTION_SHIFT) * ref_clock) / 0x8000;
if (drm_WARN_ON(&dev_priv->drm, p0 == 0 || p1 == 0 || p2 == 0))
return 0;
return dco_freq / (p0 * p1 * p2 * 5);
}
static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
enum port port)
{
@ -1505,77 +1347,6 @@ static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
}
}
static int icl_calc_mg_pll_link(struct drm_i915_private *dev_priv,
const struct intel_dpll_hw_state *pll_state)
{
u32 m1, m2_int, m2_frac, div1, div2, ref_clock;
u64 tmp;
ref_clock = dev_priv->cdclk.hw.ref;
if (INTEL_GEN(dev_priv) >= 12) {
m1 = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBPREDIV_MASK;
m1 = m1 >> DKL_PLL_DIV0_FBPREDIV_SHIFT;
m2_int = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBDIV_INT_MASK;
if (pll_state->mg_pll_bias & DKL_PLL_BIAS_FRAC_EN_H) {
m2_frac = pll_state->mg_pll_bias &
DKL_PLL_BIAS_FBDIV_FRAC_MASK;
m2_frac = m2_frac >> DKL_PLL_BIAS_FBDIV_SHIFT;
} else {
m2_frac = 0;
}
} else {
m1 = pll_state->mg_pll_div1 & MG_PLL_DIV1_FBPREDIV_MASK;
m2_int = pll_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK;
if (pll_state->mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) {
m2_frac = pll_state->mg_pll_div0 &
MG_PLL_DIV0_FBDIV_FRAC_MASK;
m2_frac = m2_frac >> MG_PLL_DIV0_FBDIV_FRAC_SHIFT;
} else {
m2_frac = 0;
}
}
switch (pll_state->mg_clktop2_hsclkctl &
MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK) {
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2:
div1 = 2;
break;
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_3:
div1 = 3;
break;
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_5:
div1 = 5;
break;
case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_7:
div1 = 7;
break;
default:
MISSING_CASE(pll_state->mg_clktop2_hsclkctl);
return 0;
}
div2 = (pll_state->mg_clktop2_hsclkctl &
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK) >>
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_SHIFT;
/* div2 value of 0 is same as 1 means no div */
if (div2 == 0)
div2 = 1;
/*
* Adjust the original formula to delay the division by 2^22 in order to
* minimize possible rounding errors.
*/
tmp = (u64)m1 * m2_int * ref_clock +
(((u64)m1 * m2_frac * ref_clock) >> 22);
tmp = div_u64(tmp, 5 * div1 * div2);
return tmp;
}
static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
{
int dotclock;
@ -1601,215 +1372,22 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
pipe_config->hw.adjusted_mode.crtc_clock = dotclock;
}
static void icl_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
enum port port = encoder->port;
enum phy phy = intel_port_to_phy(dev_priv, port);
int link_clock;
if (intel_phy_is_combo(dev_priv, phy)) {
link_clock = cnl_calc_wrpll_link(dev_priv, pll_state);
} else {
enum intel_dpll_id pll_id = intel_get_shared_dpll_id(dev_priv,
pipe_config->shared_dpll);
if (pll_id == DPLL_ID_ICL_TBTPLL)
link_clock = icl_calc_tbt_pll_link(dev_priv, port);
else
link_clock = icl_calc_mg_pll_link(dev_priv, pll_state);
}
pipe_config->port_clock = link_clock;
ddi_dotclock_get(pipe_config);
}
static void cnl_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
int link_clock;
if (pll_state->cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
link_clock = cnl_calc_wrpll_link(dev_priv, pll_state);
} else {
link_clock = pll_state->cfgcr0 & DPLL_CFGCR0_LINK_RATE_MASK;
switch (link_clock) {
case DPLL_CFGCR0_LINK_RATE_810:
link_clock = 81000;
break;
case DPLL_CFGCR0_LINK_RATE_1080:
link_clock = 108000;
break;
case DPLL_CFGCR0_LINK_RATE_1350:
link_clock = 135000;
break;
case DPLL_CFGCR0_LINK_RATE_1620:
link_clock = 162000;
break;
case DPLL_CFGCR0_LINK_RATE_2160:
link_clock = 216000;
break;
case DPLL_CFGCR0_LINK_RATE_2700:
link_clock = 270000;
break;
case DPLL_CFGCR0_LINK_RATE_3240:
link_clock = 324000;
break;
case DPLL_CFGCR0_LINK_RATE_4050:
link_clock = 405000;
break;
default:
drm_WARN(&dev_priv->drm, 1, "Unsupported link rate\n");
break;
}
link_clock *= 2;
}
pipe_config->port_clock = link_clock;
ddi_dotclock_get(pipe_config);
}
static void skl_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct intel_dpll_hw_state *pll_state = &pipe_config->dpll_hw_state;
int link_clock;
/*
* ctrl1 register is already shifted for each pll, just use 0 to get
* the internal shift for each field
*/
if (pll_state->ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) {
link_clock = skl_calc_wrpll_link(pll_state);
} else {
link_clock = pll_state->ctrl1 & DPLL_CTRL1_LINK_RATE_MASK(0);
link_clock >>= DPLL_CTRL1_LINK_RATE_SHIFT(0);
switch (link_clock) {
case DPLL_CTRL1_LINK_RATE_810:
link_clock = 81000;
break;
case DPLL_CTRL1_LINK_RATE_1080:
link_clock = 108000;
break;
case DPLL_CTRL1_LINK_RATE_1350:
link_clock = 135000;
break;
case DPLL_CTRL1_LINK_RATE_1620:
link_clock = 162000;
break;
case DPLL_CTRL1_LINK_RATE_2160:
link_clock = 216000;
break;
case DPLL_CTRL1_LINK_RATE_2700:
link_clock = 270000;
break;
default:
drm_WARN(encoder->base.dev, 1,
"Unsupported link rate\n");
break;
}
link_clock *= 2;
}
pipe_config->port_clock = link_clock;
ddi_dotclock_get(pipe_config);
}
static void hsw_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
int link_clock = 0;
u32 val, pll;
val = hsw_pll_to_ddi_pll_sel(pipe_config->shared_dpll);
switch (val & PORT_CLK_SEL_MASK) {
case PORT_CLK_SEL_LCPLL_810:
link_clock = 81000;
break;
case PORT_CLK_SEL_LCPLL_1350:
link_clock = 135000;
break;
case PORT_CLK_SEL_LCPLL_2700:
link_clock = 270000;
break;
case PORT_CLK_SEL_WRPLL1:
link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(0));
break;
case PORT_CLK_SEL_WRPLL2:
link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(1));
break;
case PORT_CLK_SEL_SPLL:
pll = intel_de_read(dev_priv, SPLL_CTL) & SPLL_FREQ_MASK;
if (pll == SPLL_FREQ_810MHz)
link_clock = 81000;
else if (pll == SPLL_FREQ_1350MHz)
link_clock = 135000;
else if (pll == SPLL_FREQ_2700MHz)
link_clock = 270000;
else {
drm_WARN(&dev_priv->drm, 1, "bad spll freq\n");
return;
}
break;
default:
drm_WARN(&dev_priv->drm, 1, "bad port clock sel\n");
return;
}
pipe_config->port_clock = link_clock * 2;
ddi_dotclock_get(pipe_config);
}
static int bxt_calc_pll_link(const struct intel_dpll_hw_state *pll_state)
{
struct dpll clock;
clock.m1 = 2;
clock.m2 = (pll_state->pll0 & PORT_PLL_M2_MASK) << 22;
if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE)
clock.m2 |= pll_state->pll2 & PORT_PLL_M2_FRAC_MASK;
clock.n = (pll_state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT;
clock.p1 = (pll_state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT;
clock.p2 = (pll_state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT;
return chv_calc_dpll_params(100000, &clock);
}
static void bxt_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
pipe_config->port_clock =
bxt_calc_pll_link(&pipe_config->dpll_hw_state);
ddi_dotclock_get(pipe_config);
}
static void intel_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
if (INTEL_GEN(dev_priv) >= 11)
icl_ddi_clock_get(encoder, pipe_config);
else if (IS_CANNONLAKE(dev_priv))
cnl_ddi_clock_get(encoder, pipe_config);
else if (IS_GEN9_LP(dev_priv))
bxt_ddi_clock_get(encoder, pipe_config);
else if (IS_GEN9_BC(dev_priv))
skl_ddi_clock_get(encoder, pipe_config);
else if (INTEL_GEN(dev_priv) <= 8)
hsw_ddi_clock_get(encoder, pipe_config);
if (intel_phy_is_tc(dev_priv, phy) &&
intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll) ==
DPLL_ID_ICL_TBTPLL)
pipe_config->port_clock = icl_calc_tbt_pll_link(dev_priv,
encoder->port);
else
pipe_config->port_clock =
intel_dpll_get_freq(dev_priv, pipe_config->shared_dpll);
ddi_dotclock_get(pipe_config);
}
void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
@ -3049,7 +2627,7 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder,
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
u32 val;
mutex_lock(&dev_priv->dpll_lock);
mutex_lock(&dev_priv->dpll.lock);
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
drm_WARN_ON(&dev_priv->drm,
@ -3075,7 +2653,7 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder,
val &= ~icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
mutex_unlock(&dev_priv->dpll_lock);
mutex_unlock(&dev_priv->dpll.lock);
}
static void icl_unmap_plls_to_ports(struct intel_encoder *encoder)
@ -3084,13 +2662,13 @@ static void icl_unmap_plls_to_ports(struct intel_encoder *encoder)
enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
u32 val;
mutex_lock(&dev_priv->dpll_lock);
mutex_lock(&dev_priv->dpll.lock);
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val);
mutex_unlock(&dev_priv->dpll_lock);
mutex_unlock(&dev_priv->dpll.lock);
}
static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv,
@ -3189,7 +2767,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
if (drm_WARN_ON(&dev_priv->drm, !pll))
return;
mutex_lock(&dev_priv->dpll_lock);
mutex_lock(&dev_priv->dpll.lock);
if (INTEL_GEN(dev_priv) >= 11) {
if (!intel_phy_is_combo(dev_priv, phy))
@ -3233,7 +2811,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
hsw_pll_to_ddi_pll_sel(pll));
}
mutex_unlock(&dev_priv->dpll_lock);
mutex_unlock(&dev_priv->dpll.lock);
}
static void intel_ddi_clk_disable(struct intel_encoder *encoder)
@ -3987,8 +3565,9 @@ static void intel_enable_ddi_hdmi(struct intel_encoder *encoder,
if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
crtc_state->hdmi_high_tmds_clock_ratio,
crtc_state->hdmi_scrambling))
DRM_ERROR("[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n",
connector->base.id, connector->name);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Failed to configure sink "
"scrambling/TMDS bit clock ratio\n",
connector->base.id, connector->name);
/* Display WA #1143: skl,kbl,cfl */
if (IS_GEN9_BC(dev_priv)) {

View File

@ -6,8 +6,6 @@
#ifndef __INTEL_DDI_H__
#define __INTEL_DDI_H__
#include <drm/i915_drm.h>
#include "intel_display.h"
struct drm_connector_state;
@ -47,7 +45,5 @@ u8 intel_ddi_dp_pre_emphasis_max(struct intel_encoder *encoder,
int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
bool enable);
void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder);
int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,
struct intel_dpll_hw_state *state);
#endif /* __INTEL_DDI_H__ */

View File

@ -41,7 +41,6 @@
#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h>
#include <drm/i915_drm.h>
#include "display/intel_crt.h"
#include "display/intel_ddi.h"
@ -2720,9 +2719,10 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
/*
* We assume the primary plane for pipe A has
* the highest stride limits of them all.
* the highest stride limits of them all,
* if in case pipe A is disabled, use the first pipe from pipe_mask.
*/
crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
crtc = intel_get_first_crtc(dev_priv);
if (!crtc)
return 0;
@ -9542,7 +9542,7 @@ static void ilk_init_pch_refclk(struct drm_i915_private *dev_priv)
}
/* Check if any DPLLs are using the SSC source */
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) {
u32 temp = intel_de_read(dev_priv, PCH_DPLL(i));
if (!(temp & DPLL_VCO_ENABLE))
@ -10129,6 +10129,9 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
BIT(PLANE_CURSOR))) == 0)
val |= PIPEMISC_HDR_MODE_PRECISION;
if (INTEL_GEN(dev_priv) >= 12)
val |= PIPEMISC_PIXEL_ROUNDING_TRUNC;
intel_de_write(dev_priv, PIPEMISC(crtc->pipe), val);
}
@ -14299,11 +14302,11 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
if (new_crtc_state->hw.active)
I915_STATE_WARN(!(pll->active_mask & crtc_mask),
"pll active mismatch (expected pipe %c in active mask 0x%02x)\n",
pipe_name(drm_crtc_index(&crtc->base)), pll->active_mask);
pipe_name(crtc->pipe), pll->active_mask);
else
I915_STATE_WARN(pll->active_mask & crtc_mask,
"pll active mismatch (didn't expect pipe %c in active mask 0x%02x)\n",
pipe_name(drm_crtc_index(&crtc->base)), pll->active_mask);
pipe_name(crtc->pipe), pll->active_mask);
I915_STATE_WARN(!(pll->state.crtc_mask & crtc_mask),
"pll enabled crtcs mismatch (expected 0x%x in 0x%02x)\n",
@ -14332,10 +14335,10 @@ verify_shared_dpll_state(struct intel_crtc *crtc,
I915_STATE_WARN(pll->active_mask & crtc_mask,
"pll active mismatch (didn't expect pipe %c in active mask)\n",
pipe_name(drm_crtc_index(&crtc->base)));
pipe_name(crtc->pipe));
I915_STATE_WARN(pll->state.crtc_mask & crtc_mask,
"pll enabled crtcs mismatch (found %x in enabled mask)\n",
pipe_name(drm_crtc_index(&crtc->base)));
pipe_name(crtc->pipe));
}
}
@ -14359,8 +14362,10 @@ verify_disabled_dpll_state(struct drm_i915_private *dev_priv)
{
int i;
for (i = 0; i < dev_priv->num_shared_dpll; i++)
verify_single_dpll_state(dev_priv, &dev_priv->shared_dplls[i], NULL, NULL);
for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++)
verify_single_dpll_state(dev_priv,
&dev_priv->dpll.shared_dplls[i],
NULL, NULL);
}
static void
@ -15318,7 +15323,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
struct intel_crtc *crtc;
struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
const u8 num_pipes = INTEL_NUM_PIPES(dev_priv);
u8 update_pipes = 0, modeset_pipes = 0;
int i;
@ -15355,7 +15359,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
continue;
if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
entries, num_pipes, pipe))
entries, I915_MAX_PIPES, pipe))
continue;
entries[pipe] = new_crtc_state->wm.skl.ddb;
@ -15393,7 +15397,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
continue;
drm_WARN_ON(&dev_priv->drm, skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
entries, num_pipes, pipe));
entries, I915_MAX_PIPES, pipe));
entries[pipe] = new_crtc_state->wm.skl.ddb;
modeset_pipes &= ~BIT(pipe);
@ -15428,7 +15432,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
continue;
drm_WARN_ON(&dev_priv->drm, skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
entries, num_pipes, pipe));
entries, I915_MAX_PIPES, pipe));
entries[pipe] = new_crtc_state->wm.skl.ddb;
modeset_pipes &= ~BIT(pipe);
@ -16320,7 +16324,6 @@ 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;
unsigned int possible_crtcs;
const u32 *formats;
int num_formats;
int ret, zpos;
@ -16401,18 +16404,16 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
plane->get_hw_state = i9xx_plane_get_hw_state;
plane->check_plane = i9xx_plane_check;
possible_crtcs = BIT(pipe);
if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
possible_crtcs, plane_funcs,
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,
possible_crtcs, plane_funcs,
0, plane_funcs,
formats, num_formats,
i9xx_format_modifiers,
DRM_PLANE_TYPE_PRIMARY,
@ -16454,7 +16455,6 @@ static struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
unsigned int possible_crtcs;
struct intel_plane *cursor;
int ret, zpos;
@ -16487,10 +16487,8 @@ 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;
possible_crtcs = BIT(pipe);
ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
possible_crtcs, &intel_cursor_plane_funcs,
0, &intel_cursor_plane_funcs,
intel_cursor_formats,
ARRAY_SIZE(intel_cursor_formats),
cursor_format_modifiers,
@ -16619,6 +16617,18 @@ static void intel_crtc_free(struct intel_crtc *crtc)
kfree(crtc);
}
static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
{
struct intel_plane *plane;
for_each_intel_plane(&dev_priv->drm, plane) {
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
plane->pipe);
plane->base.possible_crtcs = drm_crtc_mask(&crtc->base);
}
}
static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
{
struct intel_plane *primary, *cursor;
@ -16697,6 +16707,8 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
intel_color_init(crtc);
intel_crtc_crc_init(crtc);
drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
return 0;
@ -17785,11 +17797,9 @@ static void plane_config_fini(struct intel_initial_plane_config *plane_config)
i915_vma_put(plane_config->vma);
}
int intel_modeset_init(struct drm_i915_private *i915)
/* part #1: call before irq install */
int intel_modeset_init_noirq(struct drm_i915_private *i915)
{
struct drm_device *dev = &i915->drm;
enum pipe pipe;
struct intel_crtc *crtc;
int ret;
i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0);
@ -17814,6 +17824,17 @@ int intel_modeset_init(struct drm_i915_private *i915)
intel_fbc_init(i915);
return 0;
}
/* part #2: call after irq install */
int intel_modeset_init(struct drm_i915_private *i915)
{
struct drm_device *dev = &i915->drm;
enum pipe pipe;
struct intel_crtc *crtc;
int ret;
intel_init_pm(i915);
intel_panel_sanitize_ssc(i915);
@ -17834,6 +17855,7 @@ int intel_modeset_init(struct drm_i915_private *i915)
}
}
intel_plane_possible_crtcs_init(i915);
intel_shared_dpll_init(dev);
intel_update_fdi_pll_freq(i915);
@ -18311,7 +18333,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
struct intel_connector *connector;
struct drm_connector_list_iter conn_iter;
u8 active_pipes = 0;
int i;
for_each_intel_crtc(dev, crtc) {
struct intel_crtc_state *crtc_state =
@ -18340,33 +18361,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
readout_plane_state(dev_priv);
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
pll->on = pll->info->funcs->get_hw_state(dev_priv, pll,
&pll->state.hw_state);
if (IS_ELKHARTLAKE(dev_priv) && pll->on &&
pll->info->id == DPLL_ID_EHL_DPLL4) {
pll->wakeref = intel_display_power_get(dev_priv,
POWER_DOMAIN_DPLL_DC_OFF);
}
pll->state.crtc_mask = 0;
for_each_intel_crtc(dev, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
if (crtc_state->hw.active &&
crtc_state->shared_dpll == pll)
pll->state.crtc_mask |= 1 << crtc->pipe;
}
pll->active_mask = pll->state.crtc_mask;
drm_dbg_kms(&dev_priv->drm,
"%s hw state readout: crtc_mask 0x%08x, on %i\n",
pll->info->name, pll->state.crtc_mask, pll->on);
}
intel_dpll_readout_hw_state(dev_priv);
for_each_intel_encoder(dev, encoder) {
pipe = 0;
@ -18623,7 +18618,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
struct intel_encoder *encoder;
struct intel_crtc *crtc;
intel_wakeref_t wakeref;
int i;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
@ -18676,19 +18670,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
intel_modeset_update_connector_atomic_state(dev);
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
if (!pll->on || pll->active_mask)
continue;
drm_dbg_kms(&dev_priv->drm,
"%s enabled but not in use, disabling\n",
pll->info->name);
pll->info->funcs->disable(dev_priv, pll);
pll->on = false;
}
intel_dpll_sanitize_state(dev_priv);
if (IS_G4X(dev_priv)) {
g4x_wm_get_hw_state(dev_priv);
@ -18820,6 +18802,15 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
static bool
has_transcoder(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder)
{
if (cpu_transcoder == TRANSCODER_EDP)
return HAS_TRANSCODER_EDP(dev_priv);
else
return INTEL_INFO(dev_priv)->pipe_mask & BIT(cpu_transcoder);
}
struct intel_display_error_state {
u32 power_well_driver;
@ -18928,7 +18919,7 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
enum transcoder cpu_transcoder = transcoders[i];
if (!INTEL_INFO(dev_priv)->trans_offsets[cpu_transcoder])
if (!has_transcoder(dev_priv, cpu_transcoder))
continue;
error->transcoder[i].available = true;

View File

@ -26,7 +26,6 @@
#define _INTEL_DISPLAY_H_
#include <drm/drm_util.h>
#include <drm/i915_drm.h>
enum link_m_n_set;
struct dpll;
@ -40,6 +39,7 @@ struct drm_framebuffer;
struct drm_i915_error_state_buf;
struct drm_i915_gem_object;
struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct drm_modeset_acquire_ctx;
struct drm_plane;
struct drm_plane_state;
@ -47,6 +47,7 @@ struct i915_ggtt_view;
struct intel_atomic_state;
struct intel_crtc;
struct intel_crtc_state;
struct intel_crtc_state;
struct intel_digital_port;
struct intel_dp;
struct intel_encoder;
@ -55,7 +56,6 @@ struct intel_plane;
struct intel_plane_state;
struct intel_remapped_info;
struct intel_rotation_info;
struct intel_crtc_state;
enum i915_gpio {
GPIOA,
@ -313,10 +313,11 @@ enum phy_fia {
};
#define for_each_pipe(__dev_priv, __p) \
for ((__p) = 0; (__p) < INTEL_NUM_PIPES(__dev_priv); (__p)++)
for ((__p) = 0; (__p) < I915_MAX_PIPES; (__p)++) \
for_each_if(INTEL_INFO(__dev_priv)->pipe_mask & BIT(__p))
#define for_each_pipe_masked(__dev_priv, __p, __mask) \
for ((__p) = 0; (__p) < INTEL_NUM_PIPES(__dev_priv); (__p)++) \
for_each_pipe(__dev_priv, __p) \
for_each_if((__mask) & BIT(__p))
#define for_each_cpu_transcoder_masked(__dev_priv, __t, __mask) \
@ -614,6 +615,7 @@ intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info,
/* modesetting */
void intel_modeset_init_hw(struct drm_i915_private *i915);
int intel_modeset_init_noirq(struct drm_i915_private *i915);
int intel_modeset_init(struct drm_i915_private *i915);
void intel_modeset_driver_remove(struct drm_i915_private *i915);
void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915);

View File

@ -920,8 +920,13 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
int i;
drm_modeset_lock_all(dev);
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
seq_printf(m, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n",
dev_priv->dpll.ref_clks.nssc,
dev_priv->dpll.ref_clks.ssc);
for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++) {
struct intel_shared_dpll *pll = &dev_priv->dpll.shared_dplls[i];
seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name,
pll->info->id);

View File

@ -939,11 +939,17 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,
static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
{
bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
SKL_DISP_PW_2);
enum i915_power_well_id high_pg;
drm_WARN_ONCE(&dev_priv->drm, pg2_enabled,
"PG2 not disabled to enable DC5.\n");
/* Power wells at this level and above must be disabled for DC5 entry */
if (INTEL_GEN(dev_priv) >= 12)
high_pg = TGL_DISP_PW_3;
else
high_pg = SKL_DISP_PW_2;
drm_WARN_ONCE(&dev_priv->drm,
intel_display_power_well_is_enabled(dev_priv, high_pg),
"Power wells above platform's DC5 limit still enabled.\n");
drm_WARN_ONCE(&dev_priv->drm,
(intel_de_read(dev_priv, DC_STATE_EN) &
@ -2740,7 +2746,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
BIT_ULL(POWER_DOMAIN_INIT))
#define TGL_DISPLAY_DC_OFF_POWER_DOMAINS ( \
TGL_PW_2_POWER_DOMAINS | \
TGL_PW_3_POWER_DOMAINS | \
BIT_ULL(POWER_DOMAIN_MODESET) | \
BIT_ULL(POWER_DOMAIN_AUX_A) | \
BIT_ULL(POWER_DOMAIN_AUX_B) | \
@ -3936,7 +3942,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
.name = "power well 3",
.domains = TGL_PW_3_POWER_DOMAINS,
.ops = &hsw_power_well_ops,
.id = DISP_PW_ID_NONE,
.id = TGL_DISP_PW_3,
{
.hsw.regs = &hsw_power_well_regs,
.hsw.idx = ICL_PW_CTL_IDX_PW_3,

View File

@ -100,6 +100,7 @@ enum i915_power_well_id {
SKL_DISP_PW_MISC_IO,
SKL_DISP_PW_1,
SKL_DISP_PW_2,
TGL_DISP_PW_3,
SKL_DISP_DC_OFF,
};

View File

@ -39,7 +39,6 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h>
#include <drm/drm_vblank.h>
#include <drm/i915_drm.h>
#include <drm/i915_mei_hdcp_interface.h>
#include <media/cec-notifier.h>
@ -642,6 +641,14 @@ struct intel_crtc_scaler_state {
/* Flag to use the scanline counter instead of the pixel counter */
#define I915_MODE_FLAG_USE_SCANLINE_COUNTER (1<<2)
struct intel_wm_level {
bool enable;
u32 pri_val;
u32 spr_val;
u32 cur_val;
u32 fbc_val;
};
struct intel_pipe_wm {
struct intel_wm_level wm[5];
bool fbc_wm_enabled;
@ -650,6 +657,14 @@ struct intel_pipe_wm {
bool sprites_scaled;
};
struct skl_wm_level {
u16 min_ddb_alloc;
u16 plane_res_b;
u8 plane_res_l;
bool plane_en;
bool ignore_lines;
};
struct skl_plane_wm {
struct skl_wm_level wm[8];
struct skl_wm_level uv_wm[8];
@ -1046,6 +1061,32 @@ struct intel_crtc_state {
enum transcoder mst_master_transcoder;
};
enum intel_pipe_crc_source {
INTEL_PIPE_CRC_SOURCE_NONE,
INTEL_PIPE_CRC_SOURCE_PLANE1,
INTEL_PIPE_CRC_SOURCE_PLANE2,
INTEL_PIPE_CRC_SOURCE_PLANE3,
INTEL_PIPE_CRC_SOURCE_PLANE4,
INTEL_PIPE_CRC_SOURCE_PLANE5,
INTEL_PIPE_CRC_SOURCE_PLANE6,
INTEL_PIPE_CRC_SOURCE_PLANE7,
INTEL_PIPE_CRC_SOURCE_PIPE,
/* TV/DP on pre-gen5/vlv can't use the pipe source. */
INTEL_PIPE_CRC_SOURCE_TV,
INTEL_PIPE_CRC_SOURCE_DP_B,
INTEL_PIPE_CRC_SOURCE_DP_C,
INTEL_PIPE_CRC_SOURCE_DP_D,
INTEL_PIPE_CRC_SOURCE_AUTO,
INTEL_PIPE_CRC_SOURCE_MAX,
};
#define INTEL_PIPE_CRC_ENTRIES_NR 128
struct intel_pipe_crc {
spinlock_t lock;
int skipped;
enum intel_pipe_crc_source source;
};
struct intel_crtc {
struct drm_crtc base;
enum pipe pipe;
@ -1089,6 +1130,10 @@ struct intel_crtc {
/* per pipe DSB related info */
struct intel_dsb dsb;
#ifdef CONFIG_DEBUG_FS
struct intel_pipe_crc pipe_crc;
#endif
};
struct intel_plane {
@ -1235,6 +1280,7 @@ struct intel_dp {
int max_link_rate;
/* sink or branch descriptor */
struct drm_dp_desc desc;
u32 edid_quirks;
struct drm_dp_aux aux;
u32 aux_busy_last_status;
u8 train_set[4];
@ -1406,9 +1452,18 @@ vlv_pipe_to_channel(enum pipe pipe)
}
}
static inline struct intel_crtc *
intel_get_first_crtc(struct drm_i915_private *dev_priv)
{
return to_intel_crtc(drm_crtc_from_index(&dev_priv->drm, 0));
}
static inline struct intel_crtc *
intel_get_crtc_for_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
{
/* pipe_to_crtc_mapping may have hole on any of 3 display pipe system */
drm_WARN_ON(&dev_priv->drm,
!(INTEL_INFO(dev_priv)->pipe_mask & BIT(pipe)));
return dev_priv->pipe_to_crtc_mapping[pipe];
}
@ -1598,11 +1653,15 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
(1 << INTEL_OUTPUT_DP_MST) |
(1 << INTEL_OUTPUT_EDP));
}
static inline void
intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
{
drm_wait_one_vblank(&dev_priv->drm, pipe);
struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
drm_crtc_wait_one_vblank(&crtc->base);
}
static inline void
intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, enum pipe pipe)
{

View File

@ -40,7 +40,6 @@
#include <drm/drm_edid.h>
#include <drm/drm_hdcp.h>
#include <drm/drm_probe_helper.h>
#include <drm/i915_drm.h>
#include "i915_debugfs.h"
#include "i915_drv.h"
@ -2399,7 +2398,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
struct intel_connector *intel_connector = intel_dp->attached_connector;
struct intel_digital_connector_state *intel_conn_state =
to_intel_digital_connector_state(conn_state);
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
DP_DPCD_QUIRK_CONSTANT_N);
int ret = 0, output_bpp;
@ -4515,7 +4514,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
* it don't care about read it here and in intel_edp_init_dpcd().
*/
if (!intel_dp_is_edp(intel_dp) &&
!drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_SINK_COUNT)) {
!drm_dp_has_quirk(&intel_dp->desc, 0,
DP_DPCD_QUIRK_NO_SINK_COUNT)) {
u8 count;
ssize_t r;
@ -5682,6 +5682,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
intel_dp->has_audio = drm_detect_monitor_audio(edid);
drm_dp_cec_set_edid(&intel_dp->aux, edid);
intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
}
static void
@ -5694,6 +5695,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
intel_connector->detect_edid = NULL;
intel_dp->has_audio = false;
intel_dp->edid_quirks = 0;
}
static int
@ -6449,6 +6451,7 @@ static
int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
bool is_repeater, u8 content_type)
{
int ret;
struct hdcp2_dp_errata_stream_type stream_type_msg;
if (is_repeater)
@ -6464,8 +6467,11 @@ int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
stream_type_msg.stream_type = content_type;
return intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg,
ret = intel_dp_hdcp2_write_msg(intel_dig_port, &stream_type_msg,
sizeof(stream_type_msg));
return ret < 0 ? ret : 0;
}
static
@ -7562,8 +7568,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
edid = drm_get_edid(connector, &intel_dp->aux.ddc);
if (edid) {
if (drm_add_edid_modes(connector, edid)) {
drm_connector_update_edid_property(connector,
edid);
drm_connector_update_edid_property(connector, edid);
intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
} else {
kfree(edid);
edid = ERR_PTR(-EINVAL);
@ -7609,9 +7615,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
intel_panel_setup_backlight(connector, pipe);
if (fixed_mode) {
/* We do not know the orientation, but their might be a quirk */
drm_connector_set_panel_orientation_with_quirk(connector,
DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
dev_priv->vbt.orientation,
fixed_mode->hdisplay, fixed_mode->vdisplay);
}

View File

@ -8,8 +8,6 @@
#include <linux/types.h>
#include <drm/i915_drm.h>
#include "i915_reg.h"
enum pipe;

View File

@ -328,15 +328,31 @@ intel_dp_aux_display_control_capable(struct intel_connector *connector)
int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
{
struct intel_panel *panel = &intel_connector->panel;
struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(intel_connector->encoder);
struct drm_device *dev = intel_connector->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
if (i915_modparams.enable_dpcd_backlight == 0 ||
(i915_modparams.enable_dpcd_backlight == -1 &&
dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
!intel_dp_aux_display_control_capable(intel_connector))
return -ENODEV;
if (!intel_dp_aux_display_control_capable(intel_connector))
/*
* There are a lot of machines that don't advertise the backlight
* control interface to use properly in their VBIOS, :\
*/
if (dev_priv->vbt.backlight.type !=
INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE &&
!drm_dp_has_quirk(&intel_dp->desc, intel_dp->edid_quirks,
DP_QUIRK_FORCE_DPCD_BACKLIGHT)) {
DRM_DEV_INFO(dev->dev,
"Panel advertises DPCD backlight support, but "
"VBT disagrees. If your backlight controls "
"don't work try booting with "
"i915.enable_dpcd_backlight=1. If your machine "
"needs this, please file a _new_ bug report on "
"drm/i915, see " FDO_BUG_URL " for details.\n");
return -ENODEV;
}
panel->backlight.setup = intel_dp_aux_setup_backlight;
panel->backlight.enable = intel_dp_aux_enable_backlight;

View File

@ -50,7 +50,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
void *port = connector->port;
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
DP_DPCD_QUIRK_CONSTANT_N);
int bpp, slots = -EINVAL;
@ -548,12 +548,41 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
return ret;
}
static int
intel_dp_mst_connector_late_register(struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
int ret;
ret = drm_dp_mst_connector_late_register(connector,
intel_connector->port);
if (ret < 0)
return ret;
ret = intel_connector_register(connector);
if (ret < 0)
drm_dp_mst_connector_early_unregister(connector,
intel_connector->port);
return ret;
}
static void
intel_dp_mst_connector_early_unregister(struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
intel_connector_unregister(connector);
drm_dp_mst_connector_early_unregister(connector,
intel_connector->port);
}
static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_digital_connector_atomic_get_property,
.atomic_set_property = intel_digital_connector_atomic_set_property,
.late_register = intel_connector_register,
.early_unregister = intel_connector_unregister,
.late_register = intel_dp_mst_connector_late_register,
.early_unregister = intel_dp_mst_connector_early_unregister,
.destroy = intel_connector_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_digital_connector_duplicate_state,

File diff suppressed because it is too large Load Diff

View File

@ -278,6 +278,15 @@ struct intel_shared_dpll_funcs {
bool (*get_hw_state)(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state);
/**
* @get_freq:
*
* Hook for calculating the pll's output frequency based on its
* current state.
*/
int (*get_freq)(struct drm_i915_private *i915,
const struct intel_shared_dpll *pll);
};
/**
@ -372,15 +381,18 @@ void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state,
void intel_update_active_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc,
struct intel_encoder *encoder);
int intel_dpll_get_freq(struct drm_i915_private *i915,
const struct intel_shared_dpll *pll);
void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_shared_dpll_swap_state(struct intel_atomic_state *state);
void intel_shared_dpll_init(struct drm_device *dev);
void intel_dpll_readout_hw_state(struct drm_i915_private *dev_priv);
void intel_dpll_sanitize_state(struct drm_i915_private *dev_priv);
void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
const struct intel_dpll_hw_state *hw_state);
int cnl_hdmi_pll_ref_clock(struct drm_i915_private *dev_priv);
enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port);
bool intel_dpll_is_combophy(enum intel_dpll_id id);

View File

@ -52,7 +52,7 @@ static inline bool intel_dsb_enable_engine(struct intel_dsb *dsb)
dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id));
if (DSB_STATUS & dsb_ctrl) {
DRM_DEBUG_KMS("DSB engine is busy.\n");
drm_dbg_kms(&dev_priv->drm, "DSB engine is busy.\n");
return false;
}
@ -72,7 +72,7 @@ static inline bool intel_dsb_disable_engine(struct intel_dsb *dsb)
dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id));
if (DSB_STATUS & dsb_ctrl) {
DRM_DEBUG_KMS("DSB engine is busy.\n");
drm_dbg_kms(&dev_priv->drm, "DSB engine is busy.\n");
return false;
}
@ -115,20 +115,20 @@ intel_dsb_get(struct intel_crtc *crtc)
obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
if (IS_ERR(obj)) {
DRM_ERROR("Gem object creation failed\n");
drm_err(&i915->drm, "Gem object creation failed\n");
goto out;
}
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
if (IS_ERR(vma)) {
DRM_ERROR("Vma creation failed\n");
drm_err(&i915->drm, "Vma creation failed\n");
i915_gem_object_put(obj);
goto out;
}
buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
if (IS_ERR(buf)) {
DRM_ERROR("Command buffer creation failed\n");
drm_err(&i915->drm, "Command buffer creation failed\n");
goto out;
}
@ -203,7 +203,7 @@ void intel_dsb_indexed_reg_write(struct intel_dsb *dsb, i915_reg_t reg,
}
if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
DRM_DEBUG_KMS("DSB buffer overflow\n");
drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
return;
}
@ -277,7 +277,7 @@ void intel_dsb_reg_write(struct intel_dsb *dsb, i915_reg_t reg, u32 val)
}
if (drm_WARN_ON(&dev_priv->drm, dsb->free_pos >= DSB_BUF_SIZE)) {
DRM_DEBUG_KMS("DSB buffer overflow\n");
drm_dbg_kms(&dev_priv->drm, "DSB buffer overflow\n");
return;
}
@ -310,7 +310,8 @@ void intel_dsb_commit(struct intel_dsb *dsb)
goto reset;
if (is_dsb_busy(dsb)) {
DRM_ERROR("HEAD_PTR write failed - dsb engine is busy.\n");
drm_err(&dev_priv->drm,
"HEAD_PTR write failed - dsb engine is busy.\n");
goto reset;
}
intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id),
@ -322,15 +323,18 @@ void intel_dsb_commit(struct intel_dsb *dsb)
(tail - dsb->free_pos * 4));
if (is_dsb_busy(dsb)) {
DRM_ERROR("TAIL_PTR write failed - dsb engine is busy.\n");
drm_err(&dev_priv->drm,
"TAIL_PTR write failed - dsb engine is busy.\n");
goto reset;
}
DRM_DEBUG_KMS("DSB execution started - head 0x%x, tail 0x%x\n",
i915_ggtt_offset(dsb->vma), tail);
drm_dbg_kms(&dev_priv->drm,
"DSB execution started - head 0x%x, tail 0x%x\n",
i915_ggtt_offset(dsb->vma), tail);
intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id),
i915_ggtt_offset(dsb->vma) + tail);
if (wait_for(!is_dsb_busy(dsb), 1)) {
DRM_ERROR("Timed out waiting for DSB workload completion.\n");
drm_err(&dev_priv->drm,
"Timed out waiting for DSB workload completion.\n");
goto reset;
}

View File

@ -36,7 +36,6 @@
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/i915_drm.h>
#include <video/mipi_display.h>

View File

@ -30,7 +30,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_connector.h"

View File

@ -42,6 +42,7 @@
#include "i915_drv.h"
#include "i915_trace.h"
#include "i915_vgpu.h"
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_frontbuffer.h"
@ -320,7 +321,7 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
SNB_CPU_FENCE_ENABLE | params->fence_id);
intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET,
params->crtc.fence_y_offset);
} else {
} else if (dev_priv->ggtt.num_fences) {
intel_de_write(dev_priv, SNB_DPFC_CTL_SA, 0);
intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, 0);
}
@ -508,12 +509,12 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
fbc->compressed_llb = compressed_llb;
GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start,
fbc->compressed_fb.start,
U32_MAX));
GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start,
fbc->compressed_llb->start,
U32_MAX));
GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
fbc->compressed_fb.start,
U32_MAX));
GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
fbc->compressed_llb->start,
U32_MAX));
intel_de_write(dev_priv, FBC_CFB_BASE,
dev_priv->dsm.start + fbc->compressed_fb.start);
intel_de_write(dev_priv, FBC_LL_BASE,
@ -691,12 +692,37 @@ static bool intel_fbc_cfb_size_changed(struct drm_i915_private *dev_priv)
fbc->compressed_fb.size * fbc->threshold;
}
static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
{
struct intel_fbc *fbc = &dev_priv->fbc;
if (intel_vgpu_active(dev_priv)) {
fbc->no_fbc_reason = "VGPU is active";
return false;
}
if (!i915_modparams.enable_fbc) {
fbc->no_fbc_reason = "disabled per module param or by default";
return false;
}
if (fbc->underrun_detected) {
fbc->no_fbc_reason = "underrun detected";
return false;
}
return true;
}
static bool intel_fbc_can_activate(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_fbc *fbc = &dev_priv->fbc;
struct intel_fbc_state_cache *cache = &fbc->state_cache;
if (!intel_fbc_can_enable(dev_priv))
return false;
if (!cache->plane.visible) {
fbc->no_fbc_reason = "primary plane not visible";
return false;
@ -795,28 +821,6 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
return true;
}
static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
{
struct intel_fbc *fbc = &dev_priv->fbc;
if (intel_vgpu_active(dev_priv)) {
fbc->no_fbc_reason = "VGPU is active";
return false;
}
if (!i915_modparams.enable_fbc) {
fbc->no_fbc_reason = "disabled per module param or by default";
return false;
}
if (fbc->underrun_detected) {
fbc->no_fbc_reason = "underrun detected";
return false;
}
return true;
}
static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
struct intel_fbc_reg_params *params)
{

View File

@ -40,7 +40,6 @@
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_display_types.h"

View File

@ -103,7 +103,7 @@ static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
intel_de_posting_read(dev_priv, reg);
trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe);
DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
drm_err(&dev_priv->drm, "pipe %c underrun\n", pipe_name(crtc->pipe));
}
static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
@ -123,7 +123,8 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
intel_de_posting_read(dev_priv, reg);
} else {
if (old && intel_de_read(dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS)
DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
drm_err(&dev_priv->drm, "pipe %c underrun\n",
pipe_name(pipe));
}
}
@ -155,7 +156,7 @@ static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
intel_de_posting_read(dev_priv, GEN7_ERR_INT);
trace_intel_cpu_fifo_underrun(dev_priv, pipe);
DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe));
drm_err(&dev_priv->drm, "fifo underrun on pipe %c\n", pipe_name(pipe));
}
static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
@ -176,8 +177,9 @@ static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
if (old &&
intel_de_read(dev_priv, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
DRM_ERROR("uncleared fifo underrun on pipe %c\n",
pipe_name(pipe));
drm_err(&dev_priv->drm,
"uncleared fifo underrun on pipe %c\n",
pipe_name(pipe));
}
}
}
@ -223,8 +225,8 @@ static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
intel_de_posting_read(dev_priv, SERR_INT);
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder));
drm_err(&dev_priv->drm, "pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder));
}
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
@ -246,8 +248,9 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
if (old && intel_de_read(dev_priv, SERR_INT) &
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder));
drm_err(&dev_priv->drm,
"uncleared pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder));
}
}
}
@ -381,8 +384,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
trace_intel_cpu_fifo_underrun(dev_priv, pipe);
DRM_ERROR("CPU pipe %c FIFO underrun\n",
pipe_name(pipe));
drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n",
pipe_name(pipe));
}
intel_fbc_handle_fifo_underrun_irq(dev_priv);
@ -403,8 +406,8 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
false)) {
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
DRM_ERROR("PCH transcoder %c FIFO underrun\n",
pipe_name(pch_transcoder));
drm_err(&dev_priv->drm, "PCH transcoder %c FIFO underrun\n",
pipe_name(pch_transcoder));
}
}

View File

@ -32,7 +32,6 @@
#include <linux/i2c.h>
#include <drm/drm_hdcp.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_display_types.h"
@ -632,8 +631,9 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
* till then let it sleep.
*/
if (gmbus_wait_idle(dev_priv)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",
adapter->name);
drm_dbg_kms(&dev_priv->drm,
"GMBUS [%s] timed out waiting for idle\n",
adapter->name);
ret = -ETIMEDOUT;
}
intel_de_write_fw(dev_priv, GMBUS0, 0);
@ -656,8 +656,9 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
*/
ret = -ENXIO;
if (gmbus_wait_idle(dev_priv)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n",
adapter->name);
drm_dbg_kms(&dev_priv->drm,
"GMBUS [%s] timed out after NAK\n",
adapter->name);
ret = -ETIMEDOUT;
}
@ -669,9 +670,9 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
intel_de_write_fw(dev_priv, GMBUS1, 0);
intel_de_write_fw(dev_priv, GMBUS0, 0);
DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n",
adapter->name, msgs[i].addr,
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
drm_dbg_kms(&dev_priv->drm, "GMBUS [%s] NAK for addr: %04x %c(%d)\n",
adapter->name, msgs[i].addr,
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
/*
* Passive adapters sometimes NAK the first probe. Retry the first
@ -680,16 +681,18 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
* drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
*/
if (ret == -ENXIO && i == 0 && try++ == 0) {
DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n",
adapter->name);
drm_dbg_kms(&dev_priv->drm,
"GMBUS [%s] NAK on first message, retry\n",
adapter->name);
goto retry;
}
goto out;
timeout:
DRM_DEBUG_KMS("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
bus->adapter.name, bus->reg0 & 0xff);
drm_dbg_kms(&dev_priv->drm,
"GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
bus->adapter.name, bus->reg0 & 0xff);
intel_de_write_fw(dev_priv, GMBUS0, 0);
/*
@ -926,9 +929,10 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
mutex_lock(&dev_priv->gmbus_mutex);
bus->force_bit += force_bit ? 1 : -1;
DRM_DEBUG_KMS("%sabling bit-banging on %s. force bit now %d\n",
force_bit ? "en" : "dis", adapter->name,
bus->force_bit);
drm_dbg_kms(&dev_priv->drm,
"%sabling bit-banging on %s. force bit now %d\n",
force_bit ? "en" : "dis", adapter->name,
bus->force_bit);
mutex_unlock(&dev_priv->gmbus_mutex);
}

View File

@ -43,6 +43,7 @@ static
int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim, u8 *bksv)
{
struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev);
int ret, i, tries = 2;
/* HDCP spec states that we must retry the bksv if it is invalid */
@ -54,7 +55,7 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
break;
}
if (i == tries) {
DRM_DEBUG_KMS("Bksv is invalid\n");
drm_dbg_kms(&i915->drm, "Bksv is invalid\n");
return -ENODEV;
}
@ -485,8 +486,8 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
return ret;
sha_idx += sizeof(sha_text);
} else {
DRM_DEBUG_KMS("Invalid number of leftovers %d\n",
sha_leftovers);
drm_dbg_kms(&dev_priv->drm, "Invalid number of leftovers %d\n",
sha_leftovers);
return -EINVAL;
}
@ -514,11 +515,11 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
rep_ctl | HDCP_SHA1_COMPLETE_HASH);
if (intel_de_wait_for_set(dev_priv, HDCP_REP_CTL,
HDCP_SHA1_COMPLETE, 1)) {
DRM_ERROR("Timed out waiting for SHA1 complete\n");
drm_err(&dev_priv->drm, "Timed out waiting for SHA1 complete\n");
return -ETIMEDOUT;
}
if (!(intel_de_read(dev_priv, HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) {
DRM_DEBUG_KMS("SHA-1 mismatch, HDCP failed\n");
drm_dbg_kms(&dev_priv->drm, "SHA-1 mismatch, HDCP failed\n");
return -ENXIO;
}
@ -537,7 +538,8 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
ret = intel_hdcp_poll_ksv_fifo(intel_dig_port, shim);
if (ret) {
DRM_DEBUG_KMS("KSV list failed to become ready (%d)\n", ret);
drm_dbg_kms(&dev_priv->drm,
"KSV list failed to become ready (%d)\n", ret);
return ret;
}
@ -547,7 +549,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) ||
DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) {
DRM_DEBUG_KMS("Max Topology Limit Exceeded\n");
drm_dbg_kms(&dev_priv->drm, "Max Topology Limit Exceeded\n");
return -EPERM;
}
@ -560,13 +562,14 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
*/
num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]);
if (num_downstream == 0) {
DRM_DEBUG_KMS("Repeater with zero downstream devices\n");
drm_dbg_kms(&dev_priv->drm,
"Repeater with zero downstream devices\n");
return -EINVAL;
}
ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL);
if (!ksv_fifo) {
DRM_DEBUG_KMS("Out of mem: ksv_fifo\n");
drm_dbg_kms(&dev_priv->drm, "Out of mem: ksv_fifo\n");
return -ENOMEM;
}
@ -576,7 +579,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, ksv_fifo,
num_downstream)) {
DRM_ERROR("Revoked Ksv(s) in ksv_fifo\n");
drm_err(&dev_priv->drm, "Revoked Ksv(s) in ksv_fifo\n");
ret = -EPERM;
goto err;
}
@ -594,12 +597,13 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
}
if (i == tries) {
DRM_DEBUG_KMS("V Prime validation failed.(%d)\n", ret);
drm_dbg_kms(&dev_priv->drm,
"V Prime validation failed.(%d)\n", ret);
goto err;
}
DRM_DEBUG_KMS("HDCP is enabled (%d downstream devices)\n",
num_downstream);
drm_dbg_kms(&dev_priv->drm, "HDCP is enabled (%d downstream devices)\n",
num_downstream);
ret = 0;
err:
kfree(ksv_fifo);
@ -642,7 +646,8 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (ret)
return ret;
if (!hdcp_capable) {
DRM_DEBUG_KMS("Panel is not HDCP capable\n");
drm_dbg_kms(&dev_priv->drm,
"Panel is not HDCP capable\n");
return -EINVAL;
}
}
@ -659,7 +664,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (intel_de_wait_for_set(dev_priv,
HDCP_STATUS(dev_priv, cpu_transcoder, port),
HDCP_STATUS_AN_READY, 1)) {
DRM_ERROR("Timed out waiting for An\n");
drm_err(&dev_priv->drm, "Timed out waiting for An\n");
return -ETIMEDOUT;
}
@ -680,7 +685,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
return ret;
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, bksv.shim, 1)) {
DRM_ERROR("BKSV is revoked\n");
drm_err(&dev_priv->drm, "BKSV is revoked\n");
return -EPERM;
}
@ -706,7 +711,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
/* Wait for R0 ready */
if (wait_for(intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)) &
(HDCP_STATUS_R0_READY | HDCP_STATUS_ENC), 1)) {
DRM_ERROR("Timed out waiting for R0 ready\n");
drm_err(&dev_priv->drm, "Timed out waiting for R0 ready\n");
return -ETIMEDOUT;
}
@ -743,8 +748,10 @@ static int intel_hdcp_auth(struct intel_connector *connector)
}
if (i == tries) {
DRM_DEBUG_KMS("Timed out waiting for Ri prime match (%x)\n",
intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)));
drm_dbg_kms(&dev_priv->drm,
"Timed out waiting for Ri prime match (%x)\n",
intel_de_read(dev_priv, HDCP_STATUS(dev_priv,
cpu_transcoder, port)));
return -ETIMEDOUT;
}
@ -753,7 +760,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
HDCP_STATUS(dev_priv, cpu_transcoder, port),
HDCP_STATUS_ENC,
ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) {
DRM_ERROR("Timed out waiting for encryption\n");
drm_err(&dev_priv->drm, "Timed out waiting for encryption\n");
return -ETIMEDOUT;
}
@ -765,7 +772,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (repeater_present)
return intel_hdcp_auth_downstream(connector);
DRM_DEBUG_KMS("HDCP is enabled (no repeater present)\n");
drm_dbg_kms(&dev_priv->drm, "HDCP is enabled (no repeater present)\n");
return 0;
}
@ -1271,7 +1278,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
return ret;
if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL) {
DRM_DEBUG_KMS("cert.rx_caps dont claim HDCP2.2\n");
drm_dbg_kms(&dev_priv->drm, "cert.rx_caps dont claim HDCP2.2\n");
return -EINVAL;
}
@ -1280,7 +1287,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
msgs.send_cert.cert_rx.receiver_id,
1)) {
DRM_ERROR("Receiver ID is revoked\n");
drm_err(&dev_priv->drm, "Receiver ID is revoked\n");
return -EPERM;
}
@ -1455,7 +1462,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
HDCP_2_2_MAX_DEVS_EXCEEDED(rx_info[1])) {
DRM_DEBUG_KMS("Topology Max Size Exceeded\n");
drm_dbg_kms(&dev_priv->drm, "Topology Max Size Exceeded\n");
return -EINVAL;
}
@ -1463,9 +1470,15 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
seq_num_v =
drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.seq_num_v);
if (!hdcp->hdcp2_encrypted && seq_num_v) {
drm_dbg_kms(&dev_priv->drm,
"Non zero Seq_num_v at first RecvId_List msg\n");
return -EINVAL;
}
if (seq_num_v < hdcp->seq_num_v) {
/* Roll over of the seq_num_v from repeater. Reauthenticate. */
DRM_DEBUG_KMS("Seq_num_v roll over.\n");
drm_dbg_kms(&dev_priv->drm, "Seq_num_v roll over.\n");
return -EINVAL;
}
@ -1474,7 +1487,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
msgs.recvid_list.receiver_ids,
device_cnt)) {
DRM_ERROR("Revoked receiver ID(s) is in list\n");
drm_err(&dev_priv->drm, "Revoked receiver ID(s) is in list\n");
return -EPERM;
}
@ -1507,25 +1520,27 @@ static int hdcp2_authenticate_repeater(struct intel_connector *connector)
static int hdcp2_authenticate_sink(struct intel_connector *connector)
{
struct intel_digital_port *intel_dig_port = intel_attached_dig_port(connector);
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
const struct intel_hdcp_shim *shim = hdcp->shim;
int ret;
ret = hdcp2_authentication_key_exchange(connector);
if (ret < 0) {
DRM_DEBUG_KMS("AKE Failed. Err : %d\n", ret);
drm_dbg_kms(&i915->drm, "AKE Failed. Err : %d\n", ret);
return ret;
}
ret = hdcp2_locality_check(connector);
if (ret < 0) {
DRM_DEBUG_KMS("Locality Check failed. Err : %d\n", ret);
drm_dbg_kms(&i915->drm,
"Locality Check failed. Err : %d\n", ret);
return ret;
}
ret = hdcp2_session_key_exchange(connector);
if (ret < 0) {
DRM_DEBUG_KMS("SKE Failed. Err : %d\n", ret);
drm_dbg_kms(&i915->drm, "SKE Failed. Err : %d\n", ret);
return ret;
}
@ -1540,7 +1555,8 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
if (hdcp->is_repeater) {
ret = hdcp2_authenticate_repeater(connector);
if (ret < 0) {
DRM_DEBUG_KMS("Repeater Auth Failed. Err: %d\n", ret);
drm_dbg_kms(&i915->drm,
"Repeater Auth Failed. Err: %d\n", ret);
return ret;
}
}
@ -1630,6 +1646,7 @@ static int hdcp2_disable_encryption(struct intel_connector *connector)
static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int ret, i, tries = 3;
for (i = 0; i < tries; i++) {
@ -1638,10 +1655,10 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
break;
/* Clearing the mei hdcp session */
DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n",
i + 1, tries, ret);
drm_dbg_kms(&i915->drm, "HDCP2.2 Auth %d of %d Failed.(%d)\n",
i + 1, tries, ret);
if (hdcp2_deauthenticate_port(connector) < 0)
DRM_DEBUG_KMS("Port deauth failed.\n");
drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
}
if (i != tries) {
@ -1652,9 +1669,10 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
msleep(HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN);
ret = hdcp2_enable_encryption(connector);
if (ret < 0) {
DRM_DEBUG_KMS("Encryption Enable Failed.(%d)\n", ret);
drm_dbg_kms(&i915->drm,
"Encryption Enable Failed.(%d)\n", ret);
if (hdcp2_deauthenticate_port(connector) < 0)
DRM_DEBUG_KMS("Port deauth failed.\n");
drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
}
}
@ -1663,23 +1681,24 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
static int _intel_hdcp2_enable(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
ret = hdcp2_authenticate_and_encrypt(connector);
if (ret) {
DRM_DEBUG_KMS("HDCP2 Type%d Enabling Failed. (%d)\n",
hdcp->content_type, ret);
drm_dbg_kms(&i915->drm, "HDCP2 Type%d Enabling Failed. (%d)\n",
hdcp->content_type, ret);
return ret;
}
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is enabled. Type %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is enabled. Type %d\n",
connector->base.name, connector->base.base.id,
hdcp->content_type);
hdcp->hdcp2_encrypted = true;
return 0;
@ -1687,15 +1706,16 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)
static int _intel_hdcp2_disable(struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
int ret;
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n",
connector->base.name, connector->base.base.id);
drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being Disabled\n",
connector->base.name, connector->base.base.id);
ret = hdcp2_disable_encryption(connector);
if (hdcp2_deauthenticate_port(connector) < 0)
DRM_DEBUG_KMS("Port deauth failed.\n");
drm_dbg_kms(&i915->drm, "Port deauth failed.\n");
connector->hdcp.hdcp2_encrypted = false;
@ -1938,12 +1958,13 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv)
static void intel_hdcp2_init(struct intel_connector *connector,
const struct intel_hdcp_shim *shim)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
int ret;
ret = initialize_hdcp_port_data(connector, shim);
if (ret) {
DRM_DEBUG_KMS("Mei hdcp data init failed\n");
drm_dbg_kms(&i915->drm, "Mei hdcp data init failed\n");
return;
}

View File

@ -8,8 +8,6 @@
#include <linux/types.h>
#include <drm/i915_drm.h>
struct drm_connector;
struct drm_connector_state;
struct drm_i915_private;

View File

@ -36,7 +36,6 @@
#include <drm/drm_edid.h>
#include <drm/drm_hdcp.h>
#include <drm/drm_scdc_helper.h>
#include <drm/i915_drm.h>
#include <drm/intel_lpe_audio.h>
#include "i915_debugfs.h"
@ -2276,14 +2275,9 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
}
}
/* Display WA #1139: glk */
if (bpc == 12 && IS_GLK_REVID(dev_priv, 0, GLK_REVID_A1) &&
adjusted_mode->htotal > 5460)
return false;
/* Display Wa_1405510057:icl */
/* Display Wa_1405510057:icl,ehl */
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
bpc == 10 && INTEL_GEN(dev_priv) >= 11 &&
bpc == 10 && IS_GEN(dev_priv, 11) &&
(adjusted_mode->crtc_hblank_end -
adjusted_mode->crtc_hblank_start) % 8 == 2)
return false;

View File

@ -9,8 +9,6 @@
#include <linux/hdmi.h>
#include <linux/types.h>
#include <drm/i915_drm.h>
#include "i915_reg.h"
struct drm_connector;

View File

@ -23,8 +23,6 @@
#include <linux/kernel.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_display_types.h"
#include "intel_hotplug.h"
@ -89,29 +87,16 @@
enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
enum port port)
{
switch (port) {
case PORT_A:
return HPD_PORT_A;
case PORT_B:
return HPD_PORT_B;
case PORT_C:
return HPD_PORT_C;
case PORT_D:
return HPD_PORT_D;
case PORT_E:
return HPD_PORT_E;
case PORT_F:
if (IS_CNL_WITH_PORT_F(dev_priv))
return HPD_PORT_E;
return HPD_PORT_F;
case PORT_G:
return HPD_PORT_G;
case PORT_H:
return HPD_PORT_H;
case PORT_I:
return HPD_PORT_I;
enum phy phy = intel_port_to_phy(dev_priv, port);
switch (phy) {
case PHY_F:
return IS_CNL_WITH_PORT_F(dev_priv) ? HPD_PORT_E : HPD_PORT_F;
case PHY_A ... PHY_E:
case PHY_G ... PHY_I:
return HPD_PORT_A + phy - PHY_A;
default:
MISSING_CASE(port);
MISSING_CASE(phy);
return HPD_NONE;
}
}
@ -185,10 +170,13 @@ static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
hpd->stats[pin].count += increment;
if (hpd->stats[pin].count > threshold) {
hpd->stats[pin].state = HPD_MARK_DISABLED;
DRM_DEBUG_KMS("HPD interrupt storm detected on PIN %d\n", pin);
drm_dbg_kms(&dev_priv->drm,
"HPD interrupt storm detected on PIN %d\n", pin);
storm = true;
} else {
DRM_DEBUG_KMS("Received HPD interrupt on PIN %d - cnt: %d\n", pin,
drm_dbg_kms(&dev_priv->drm,
"Received HPD interrupt on PIN %d - cnt: %d\n",
pin,
hpd->stats[pin].count);
}
@ -217,7 +205,8 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv)
dev_priv->hotplug.stats[pin].state != HPD_MARK_DISABLED)
continue;
DRM_INFO("HPD interrupt storm detected on connector %s: "
drm_info(&dev_priv->drm,
"HPD interrupt storm detected on connector %s: "
"switching from hotplug detection to polling\n",
connector->base.name);
@ -259,8 +248,9 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
continue;
if (connector->base.polled != connector->polled)
DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
connector->base.name);
drm_dbg(&dev_priv->drm,
"Reenabling HPD on connector %s\n",
connector->base.name);
connector->base.polled = connector->polled;
}
drm_connector_list_iter_end(&conn_iter);
@ -295,11 +285,12 @@ intel_encoder_hotplug(struct intel_encoder *encoder,
if (old_status == connector->base.status)
return INTEL_HOTPLUG_UNCHANGED;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
connector->base.base.id,
connector->base.name,
drm_get_connector_status_name(old_status),
drm_get_connector_status_name(connector->base.status));
drm_dbg_kms(&to_i915(dev)->drm,
"[CONNECTOR:%d:%s] status updated from %s to %s\n",
connector->base.base.id,
connector->base.name,
drm_get_connector_status_name(old_status),
drm_get_connector_status_name(connector->base.status));
return INTEL_HOTPLUG_CHANGED;
}
@ -373,7 +364,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
u32 hpd_retry_bits;
mutex_lock(&dev->mode_config.mutex);
DRM_DEBUG_KMS("running encoder hotplug functions\n");
drm_dbg_kms(&dev_priv->drm, "running encoder hotplug functions\n");
spin_lock_irq(&dev_priv->irq_lock);
@ -401,8 +392,9 @@ static void i915_hotplug_work_func(struct work_struct *work)
struct intel_encoder *encoder =
intel_attached_encoder(connector);
DRM_DEBUG_KMS("Connector %s (pin %i) received hotplug event.\n",
connector->base.name, pin);
drm_dbg_kms(&dev_priv->drm,
"Connector %s (pin %i) received hotplug event.\n",
connector->base.name, pin);
switch (encoder->hotplug(encoder, connector,
hpd_event_bits & hpd_bit)) {
@ -487,9 +479,10 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
long_hpd = long_mask & BIT(pin);
DRM_DEBUG_DRIVER("digital hpd on [ENCODER:%d:%s] - %s\n",
encoder->base.base.id, encoder->base.name,
long_hpd ? "long" : "short");
drm_dbg(&dev_priv->drm,
"digital hpd on [ENCODER:%d:%s] - %s\n",
encoder->base.base.id, encoder->base.name,
long_hpd ? "long" : "short");
queue_dig = true;
if (long_hpd) {

View File

@ -8,8 +8,6 @@
#include <linux/types.h>
#include <drm/i915_drm.h>
struct drm_i915_private;
struct intel_connector;
struct intel_encoder;

View File

@ -127,7 +127,8 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
kfree(pdata);
if (IS_ERR(platdev)) {
DRM_ERROR("Failed to allocate LPE audio platform device\n");
drm_err(&dev_priv->drm,
"Failed to allocate LPE audio platform device\n");
return platdev;
}
@ -190,7 +191,8 @@ static bool lpe_audio_detect(struct drm_i915_private *dev_priv)
};
if (!pci_dev_present(atom_hdaudio_ids)) {
DRM_INFO("HDaudio controller not detected, using LPE audio instead\n");
drm_info(&dev_priv->drm,
"HDaudio controller not detected, using LPE audio instead\n");
lpe_present = true;
}
}
@ -203,18 +205,19 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv)
dev_priv->lpe_audio.irq = irq_alloc_desc(0);
if (dev_priv->lpe_audio.irq < 0) {
DRM_ERROR("Failed to allocate IRQ desc: %d\n",
drm_err(&dev_priv->drm, "Failed to allocate IRQ desc: %d\n",
dev_priv->lpe_audio.irq);
ret = dev_priv->lpe_audio.irq;
goto err;
}
DRM_DEBUG("irq = %d\n", dev_priv->lpe_audio.irq);
drm_dbg(&dev_priv->drm, "irq = %d\n", dev_priv->lpe_audio.irq);
ret = lpe_audio_irq_init(dev_priv);
if (ret) {
DRM_ERROR("Failed to initialize irqchip for lpe audio: %d\n",
drm_err(&dev_priv->drm,
"Failed to initialize irqchip for lpe audio: %d\n",
ret);
goto err_free_irq;
}
@ -223,7 +226,8 @@ static int lpe_audio_setup(struct drm_i915_private *dev_priv)
if (IS_ERR(dev_priv->lpe_audio.platdev)) {
ret = PTR_ERR(dev_priv->lpe_audio.platdev);
DRM_ERROR("Failed to create lpe audio platform device: %d\n",
drm_err(&dev_priv->drm,
"Failed to create lpe audio platform device: %d\n",
ret);
goto err_free_irq;
}
@ -259,8 +263,8 @@ void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv)
ret = generic_handle_irq(dev_priv->lpe_audio.irq);
if (ret)
DRM_ERROR_RATELIMITED("error handling LPE audio irq: %d\n",
ret);
drm_err_ratelimited(&dev_priv->drm,
"error handling LPE audio irq: %d\n", ret);
}
/**
@ -278,7 +282,8 @@ int intel_lpe_audio_init(struct drm_i915_private *dev_priv)
if (lpe_audio_detect(dev_priv)) {
ret = lpe_audio_setup(dev_priv);
if (ret < 0)
DRM_ERROR("failed to setup LPE Audio bridge\n");
drm_err(&dev_priv->drm,
"failed to setup LPE Audio bridge\n");
}
return ret;
}

View File

@ -37,7 +37,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_atomic.h"
@ -182,8 +181,9 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
if (INTEL_GEN(dev_priv) <= 4 &&
pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
DRM_DEBUG_KMS("Panel power timings uninitialized, "
"setting defaults\n");
drm_dbg_kms(&dev_priv->drm,
"Panel power timings uninitialized, "
"setting defaults\n");
/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
pps->t1_t2 = 40 * 10;
pps->t5 = 200 * 10;
@ -192,10 +192,10 @@ static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
pps->tx = 200 * 10;
}
DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
"divider %d port %d powerdown_on_reset %d\n",
pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
pps->divider, pps->port, pps->powerdown_on_reset);
drm_dbg(&dev_priv->drm, "LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
"divider %d port %d powerdown_on_reset %d\n",
pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
pps->divider, pps->port, pps->powerdown_on_reset);
}
static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
@ -317,7 +317,8 @@ static void intel_enable_lvds(struct intel_encoder *encoder,
intel_de_posting_read(dev_priv, lvds_encoder->reg);
if (intel_de_wait_for_set(dev_priv, PP_STATUS(0), PP_ON, 5000))
DRM_ERROR("timed out waiting for panel to power on\n");
drm_err(&dev_priv->drm,
"timed out waiting for panel to power on\n");
intel_panel_enable_backlight(pipe_config, conn_state);
}
@ -332,7 +333,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder,
intel_de_write(dev_priv, PP_CONTROL(0),
intel_de_read(dev_priv, PP_CONTROL(0)) & ~PANEL_POWER_ON);
if (intel_de_wait_for_clear(dev_priv, PP_STATUS(0), PP_ON, 1000))
DRM_ERROR("timed out waiting for panel to power off\n");
drm_err(&dev_priv->drm,
"timed out waiting for panel to power off\n");
intel_de_write(dev_priv, lvds_encoder->reg,
intel_de_read(dev_priv, lvds_encoder->reg) & ~LVDS_PORT_EN);
@ -398,7 +400,7 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
/* Should never happen!! */
if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) {
DRM_ERROR("Can't support LVDS on pipe A\n");
drm_err(&dev_priv->drm, "Can't support LVDS on pipe A\n");
return -EINVAL;
}
@ -408,8 +410,9 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
lvds_bpp = 6*3;
if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
pipe_config->pipe_bpp, lvds_bpp);
drm_dbg_kms(&dev_priv->drm,
"forcing display bpp (was %d) to LVDS (%d)\n",
pipe_config->pipe_bpp, lvds_bpp);
pipe_config->pipe_bpp = lvds_bpp;
}
@ -833,7 +836,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
}
if (!dev_priv->vbt.int_lvds_support) {
DRM_DEBUG_KMS("Internal LVDS support disabled by VBT\n");
drm_dbg_kms(&dev_priv->drm,
"Internal LVDS support disabled by VBT\n");
return;
}
@ -852,10 +856,12 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
pin = GMBUS_PIN_PANEL;
if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
if ((lvds & LVDS_PORT_EN) == 0) {
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
drm_dbg_kms(&dev_priv->drm,
"LVDS is not present in VBT\n");
return;
}
DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
drm_dbg_kms(&dev_priv->drm,
"LVDS is not present in VBT, but enabled anyway\n");
}
lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
@ -969,7 +975,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
*/
fixed_mode = intel_encoder_current_mode(intel_encoder);
if (fixed_mode) {
DRM_DEBUG_KMS("using current (BIOS) mode: ");
drm_dbg_kms(&dev_priv->drm, "using current (BIOS) mode: ");
drm_mode_debug_printmodeline(fixed_mode);
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
}
@ -985,8 +991,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
intel_panel_setup_backlight(connector, INVALID_PIPE);
lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
lvds_encoder->is_dual_link ? "dual" : "single");
drm_dbg_kms(&dev_priv->drm, "detected %s-link lvds configuration\n",
lvds_encoder->is_dual_link ? "dual" : "single");
lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
@ -995,7 +1001,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
failed:
mutex_unlock(&dev->mode_config.mutex);
DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
drm_dbg_kms(&dev_priv->drm, "No LVDS modes found, disabling.\n");
drm_connector_cleanup(connector);
drm_encoder_cleanup(encoder);
kfree(lvds_encoder);

View File

@ -30,8 +30,6 @@
#include <linux/firmware.h>
#include <acpi/video.h>
#include <drm/i915_drm.h>
#include "display/intel_panel.h"
#include "i915_drv.h"

View File

@ -27,7 +27,6 @@
*/
#include <drm/drm_fourcc.h>
#include <drm/i915_drm.h>
#include "gem/i915_gem_pm.h"
#include "gt/intel_ring.h"
@ -324,7 +323,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
/* check for underruns */
tmp = intel_de_read(dev_priv, DOVSTA);
if (tmp & (1 << 17))
DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
drm_dbg(&dev_priv->drm, "overlay underrun, DOVSTA: %x\n", tmp);
rq = alloc_request(overlay, NULL);
if (IS_ERR(rq))
@ -1069,7 +1068,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
overlay = dev_priv->overlay;
if (!overlay) {
DRM_DEBUG("userspace bug: no overlay\n");
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
return -ENODEV;
}
@ -1093,7 +1092,8 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
if (i915_gem_object_is_tiled(new_bo)) {
DRM_DEBUG_KMS("buffer used for overlay image can not be tiled\n");
drm_dbg_kms(&dev_priv->drm,
"buffer used for overlay image can not be tiled\n");
ret = -EINVAL;
goto out_unlock;
}
@ -1228,7 +1228,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
overlay = dev_priv->overlay;
if (!overlay) {
DRM_DEBUG("userspace bug: no overlay\n");
drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
return -ENODEV;
}
@ -1372,7 +1372,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
update_reg_attrs(overlay, overlay->regs);
dev_priv->overlay = overlay;
DRM_INFO("Initialized overlay support.\n");
drm_info(&dev_priv->drm, "Initialized overlay support.\n");
return;
out_free:

View File

@ -1882,6 +1882,7 @@ static int pwm_setup_backlight(struct intel_connector *connector,
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_panel *panel = &connector->panel;
const char *desc;
u32 level, ns;
int retval;
/* Get the right PWM chip for DSI backlight according to VBT */
@ -1906,8 +1907,12 @@ static int pwm_setup_backlight(struct intel_connector *connector,
*/
pwm_apply_args(panel->backlight.pwm);
retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS,
CRC_PMIC_PWM_PERIOD_NS);
panel->backlight.min = 0; /* 0% */
panel->backlight.max = 100; /* 100% */
level = intel_panel_compute_brightness(connector, 100);
ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100);
retval = pwm_config(panel->backlight.pwm, ns, CRC_PMIC_PWM_PERIOD_NS);
if (retval < 0) {
drm_err(&dev_priv->drm, "Failed to configure the pwm chip\n");
pwm_put(panel->backlight.pwm);
@ -1915,11 +1920,10 @@ static int pwm_setup_backlight(struct intel_connector *connector,
return retval;
}
panel->backlight.min = 0; /* 0% */
panel->backlight.max = 100; /* 100% */
panel->backlight.level = DIV_ROUND_UP(
pwm_get_duty_cycle(panel->backlight.pwm) * 100,
CRC_PMIC_PWM_PERIOD_NS);
level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100,
CRC_PMIC_PWM_PERIOD_NS);
panel->backlight.level =
intel_panel_compute_brightness(connector, level);
panel->backlight.enabled = panel->backlight.level != 0;
drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n",

View File

@ -441,15 +441,11 @@ display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s)
return 0;
}
void intel_display_crc_init(struct drm_i915_private *dev_priv)
void intel_crtc_crc_init(struct intel_crtc *crtc)
{
enum pipe pipe;
struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
for_each_pipe(dev_priv, pipe) {
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
spin_lock_init(&pipe_crc->lock);
}
spin_lock_init(&pipe_crc->lock);
}
static int i8xx_crc_source_valid(struct drm_i915_private *dev_priv,
@ -587,7 +583,8 @@ int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
{
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
enum intel_display_power_domain power_domain;
enum intel_pipe_crc_source source;
intel_wakeref_t wakeref;
@ -640,7 +637,7 @@ void intel_crtc_enable_pipe_crc(struct intel_crtc *intel_crtc)
{
struct drm_crtc *crtc = &intel_crtc->base;
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
u32 val = 0;
if (!crtc->crc.opened)
@ -660,7 +657,7 @@ void intel_crtc_disable_pipe_crc(struct intel_crtc *intel_crtc)
{
struct drm_crtc *crtc = &intel_crtc->base;
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
struct intel_pipe_crc *pipe_crc = &intel_crtc->pipe_crc;
/* Swallow crc's until we stop generating them. */
spin_lock_irq(&pipe_crc->lock);

View File

@ -13,7 +13,7 @@ struct drm_i915_private;
struct intel_crtc;
#ifdef CONFIG_DEBUG_FS
void intel_display_crc_init(struct drm_i915_private *dev_priv);
void intel_crtc_crc_init(struct intel_crtc *crtc);
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name);
int intel_crtc_verify_crc_source(struct drm_crtc *crtc,
const char *source_name, size_t *values_cnt);
@ -22,7 +22,7 @@ const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc);
void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc);
#else
static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {}
static inline void intel_crtc_crc_init(struct intel_crtc *crtc) {}
#define intel_crtc_set_crc_source NULL
#define intel_crtc_verify_crc_source NULL
#define intel_crtc_get_crc_sources NULL

View File

@ -304,7 +304,7 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
drm_dbg_kms(&dev_priv->drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]);
if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
if (drm_dp_has_quirk(&intel_dp->desc, 0, DP_DPCD_QUIRK_NO_PSR)) {
drm_dbg_kms(&dev_priv->drm,
"PSR support not currently available for this panel\n");
return;

View File

@ -82,6 +82,16 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = {
DMI_MATCH(DMI_PRODUCT_NAME, ""),
},
},
{
.callback = intel_dmi_reverse_brightness,
.ident = "Thundersoft TST178 tablet",
/* DMI strings are too generic, also match on BIOS date */
.matches = {DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),
DMI_EXACT_MATCH(DMI_BIOS_DATE, "04/15/2014"),
},
},
{ } /* terminating entry */
},
.hook = quirk_invert_brightness,

View File

@ -34,7 +34,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_atomic.h"

View File

@ -8,8 +8,6 @@
#include <linux/types.h>
#include <drm/i915_drm.h>
#include "i915_reg.h"
struct drm_i915_private;

View File

@ -37,10 +37,10 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_rect.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "i915_trace.h"
#include "i915_vgpu.h"
#include "intel_atomic_plane.h"
#include "intel_display_types.h"
#include "intel_frontbuffer.h"
@ -283,6 +283,16 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
u32 src_x, src_y, src_w, src_h, hsub, vsub;
bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
/*
* FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
* abuses hsub/vsub so we can't use them here. But as they
* are limited to 32bpp RGB formats we don't actually need
* to check anything.
*/
if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
return 0;
/*
* Hardware doesn't handle subpixel coordinates.
* Adjust to (macro)pixel boundary, but be careful not to
@ -297,26 +307,26 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
drm_rect_init(src, src_x << 16, src_y << 16,
src_w << 16, src_h << 16);
if (!fb->format->is_yuv)
return 0;
/* YUV specific checks */
if (!rotated) {
if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
hsub = 2;
vsub = 2;
} else {
hsub = fb->format->hsub;
vsub = fb->format->vsub;
} else {
hsub = vsub = max(fb->format->hsub, fb->format->vsub);
}
if (rotated)
hsub = vsub = max(hsub, vsub);
if (src_x % hsub || src_w % hsub) {
DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
src_x, src_w, hsub, rotated ? "rotated " : "");
DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
src_x, src_w, hsub, yesno(rotated));
return -EINVAL;
}
if (src_y % vsub || src_h % vsub) {
DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
src_y, src_h, vsub, rotated ? "rotated " : "");
DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
src_y, src_h, vsub, yesno(rotated));
return -EINVAL;
}
@ -355,9 +365,8 @@ static int skl_plane_min_cdclk(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);
unsigned int pixel_rate = crtc_state->pixel_rate;
unsigned int src_w, src_h, dst_w, dst_h;
unsigned int num, den;
unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
skl_plane_ratio(crtc_state, plane_state, &num, &den);
@ -365,17 +374,7 @@ static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
den *= 2;
src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
dst_w = drm_rect_width(&plane_state->uapi.dst);
dst_h = drm_rect_height(&plane_state->uapi.dst);
/* Downscaling limits the maximum pixel rate */
dst_w = min(src_w, dst_w);
dst_h = min(src_h, dst_h);
return DIV64_U64_ROUND_UP(mul_u32_u32(pixel_rate * num, src_w * src_h),
mul_u32_u32(den, dst_w * dst_h));
return DIV_ROUND_UP(pixel_rate * num, den);
}
static unsigned int
@ -2077,6 +2076,18 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
return 0;
}
static bool intel_format_is_p01x(u32 format)
{
switch (format) {
case DRM_FORMAT_P010:
case DRM_FORMAT_P012:
case DRM_FORMAT_P016:
return true;
default:
return false;
}
}
static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@ -2155,6 +2166,15 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
return -EINVAL;
}
/* Wa_1606054188:tgl */
if (IS_TIGERLAKE(dev_priv) &&
plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
intel_format_is_p01x(fb->format->format)) {
drm_dbg_kms(&dev_priv->drm,
"Source color keying not supported with P01x formats\n");
return -EINVAL;
}
return 0;
}
@ -3011,7 +3031,6 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
struct intel_plane *plane;
enum drm_plane_type plane_type;
unsigned int supported_rotations;
unsigned int possible_crtcs;
const u64 *modifiers;
const u32 *formats;
int num_formats;
@ -3066,10 +3085,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
else
plane_type = DRM_PLANE_TYPE_OVERLAY;
possible_crtcs = BIT(pipe);
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
possible_crtcs, plane_funcs,
0, plane_funcs,
formats, num_formats, modifiers,
plane_type,
"plane %d%c", plane_id + 1,
@ -3120,7 +3137,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
{
struct intel_plane *plane;
const struct drm_plane_funcs *plane_funcs;
unsigned long possible_crtcs;
unsigned int supported_rotations;
const u64 *modifiers;
const u32 *formats;
@ -3205,10 +3221,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
plane->id = PLANE_SPRITE0 + sprite;
plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
possible_crtcs = BIT(pipe);
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
possible_crtcs, plane_funcs,
0, plane_funcs,
formats, num_formats, modifiers,
DRM_PLANE_TYPE_OVERLAY,
"sprite %c", sprite_name(pipe, sprite));

View File

@ -33,7 +33,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_connector.h"

View File

@ -6,8 +6,6 @@
* Manasi Navare <manasi.d.navare@intel.com>
*/
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_display_types.h"
#include "intel_dsi.h"

View File

@ -1591,59 +1591,6 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = {
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
};
static enum drm_panel_orientation
vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_encoder *encoder = intel_attached_encoder(connector);
enum intel_display_power_domain power_domain;
enum drm_panel_orientation orientation;
struct intel_plane *plane;
struct intel_crtc *crtc;
intel_wakeref_t wakeref;
enum pipe pipe;
u32 val;
if (!encoder->get_hw_state(encoder, &pipe))
return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
plane = to_intel_plane(crtc->base.primary);
power_domain = POWER_DOMAIN_PIPE(pipe);
wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
if (!wakeref)
return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
val = intel_de_read(dev_priv, DSPCNTR(plane->i9xx_plane));
if (!(val & DISPLAY_PLANE_ENABLE))
orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
else if (val & DISPPLANE_ROTATE_180)
orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
else
orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
intel_display_power_put(dev_priv, power_domain, wakeref);
return orientation;
}
static enum drm_panel_orientation
vlv_dsi_get_panel_orientation(struct intel_connector *connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
enum drm_panel_orientation orientation;
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
orientation = vlv_dsi_get_hw_panel_orientation(connector);
if (orientation != DRM_MODE_PANEL_ORIENTATION_UNKNOWN)
return orientation;
}
return intel_dsi_get_panel_orientation(connector);
}
static void vlv_dsi_add_properties(struct intel_connector *connector)
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
@ -1662,7 +1609,7 @@ static void vlv_dsi_add_properties(struct intel_connector *connector)
drm_connector_set_panel_orientation_with_quirk(
&connector->base,
vlv_dsi_get_panel_orientation(connector),
intel_dsi_get_panel_orientation(connector),
connector->panel.fixed_mode->hdisplay,
connector->panel.fixed_mode->vdisplay);
}

View File

@ -217,7 +217,7 @@ static void clear_pages_worker(struct work_struct *work)
0);
out_request:
if (unlikely(err)) {
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
err = 0;
}

View File

@ -67,10 +67,9 @@
#include <linux/log2.h>
#include <linux/nospec.h>
#include <drm/i915_drm.h>
#include "gt/gen6_ppgtt.h"
#include "gt/intel_context.h"
#include "gt/intel_context_param.h"
#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_ring.h"
@ -243,7 +242,6 @@ static void __free_engines(struct i915_gem_engines *e, unsigned int count)
if (!e->engines[count])
continue;
RCU_INIT_POINTER(e->engines[count]->gem_context, NULL);
intel_context_put(e->engines[count]);
}
kfree(e);
@ -256,7 +254,51 @@ static void free_engines(struct i915_gem_engines *e)
static void free_engines_rcu(struct rcu_head *rcu)
{
free_engines(container_of(rcu, struct i915_gem_engines, rcu));
struct i915_gem_engines *engines =
container_of(rcu, struct i915_gem_engines, rcu);
i915_sw_fence_fini(&engines->fence);
free_engines(engines);
}
static int __i915_sw_fence_call
engines_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
{
struct i915_gem_engines *engines =
container_of(fence, typeof(*engines), fence);
switch (state) {
case FENCE_COMPLETE:
if (!list_empty(&engines->link)) {
struct i915_gem_context *ctx = engines->ctx;
unsigned long flags;
spin_lock_irqsave(&ctx->stale.lock, flags);
list_del(&engines->link);
spin_unlock_irqrestore(&ctx->stale.lock, flags);
}
i915_gem_context_put(engines->ctx);
break;
case FENCE_FREE:
init_rcu_head(&engines->rcu);
call_rcu(&engines->rcu, free_engines_rcu);
break;
}
return NOTIFY_DONE;
}
static struct i915_gem_engines *alloc_engines(unsigned int count)
{
struct i915_gem_engines *e;
e = kzalloc(struct_size(e, engines, count), GFP_KERNEL);
if (!e)
return NULL;
i915_sw_fence_init(&e->fence, engines_notify);
return e;
}
static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
@ -266,12 +308,10 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
struct i915_gem_engines *e;
enum intel_engine_id id;
e = kzalloc(struct_size(e, engines, I915_NUM_ENGINES), GFP_KERNEL);
e = alloc_engines(I915_NUM_ENGINES);
if (!e)
return ERR_PTR(-ENOMEM);
e->ctx = ctx;
for_each_engine(engine, gt, id) {
struct intel_context *ce;
@ -305,7 +345,6 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
list_del(&ctx->link);
spin_unlock(&ctx->i915->gem.contexts.lock);
free_engines(rcu_access_pointer(ctx->engines));
mutex_destroy(&ctx->engines_mutex);
if (ctx->timeline)
@ -492,30 +531,75 @@ static void kill_engines(struct i915_gem_engines *engines)
static void kill_stale_engines(struct i915_gem_context *ctx)
{
struct i915_gem_engines *pos, *next;
unsigned long flags;
spin_lock_irqsave(&ctx->stale.lock, flags);
spin_lock_irq(&ctx->stale.lock);
GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
list_for_each_entry_safe(pos, next, &ctx->stale.engines, link) {
if (!i915_sw_fence_await(&pos->fence))
if (!i915_sw_fence_await(&pos->fence)) {
list_del_init(&pos->link);
continue;
}
spin_unlock_irqrestore(&ctx->stale.lock, flags);
spin_unlock_irq(&ctx->stale.lock);
kill_engines(pos);
spin_lock_irqsave(&ctx->stale.lock, flags);
spin_lock_irq(&ctx->stale.lock);
GEM_BUG_ON(i915_sw_fence_signaled(&pos->fence));
list_safe_reset_next(pos, next, link);
list_del_init(&pos->link); /* decouple from FENCE_COMPLETE */
i915_sw_fence_complete(&pos->fence);
}
spin_unlock_irqrestore(&ctx->stale.lock, flags);
spin_unlock_irq(&ctx->stale.lock);
}
static void kill_context(struct i915_gem_context *ctx)
{
kill_stale_engines(ctx);
kill_engines(__context_engines_static(ctx));
}
static void engines_idle_release(struct i915_gem_context *ctx,
struct i915_gem_engines *engines)
{
struct i915_gem_engines_iter it;
struct intel_context *ce;
INIT_LIST_HEAD(&engines->link);
engines->ctx = i915_gem_context_get(ctx);
for_each_gem_engine(ce, engines, it) {
struct dma_fence *fence;
int err = 0;
/* serialises with execbuf */
RCU_INIT_POINTER(ce->gem_context, NULL);
if (!intel_context_pin_if_active(ce))
continue;
fence = i915_active_fence_get(&ce->timeline->last_request);
if (fence) {
err = i915_sw_fence_await_dma_fence(&engines->fence,
fence, 0,
GFP_KERNEL);
dma_fence_put(fence);
}
intel_context_unpin(ce);
if (err < 0)
goto kill;
}
spin_lock_irq(&ctx->stale.lock);
if (!i915_gem_context_is_closed(ctx))
list_add_tail(&engines->link, &ctx->stale.engines);
spin_unlock_irq(&ctx->stale.lock);
kill:
if (list_empty(&engines->link)) /* raced, already closed */
kill_engines(engines);
i915_sw_fence_commit(&engines->fence);
}
static void set_closed_name(struct i915_gem_context *ctx)
@ -539,11 +623,16 @@ static void context_close(struct i915_gem_context *ctx)
{
struct i915_address_space *vm;
/* Flush any concurrent set_engines() */
mutex_lock(&ctx->engines_mutex);
engines_idle_release(ctx, rcu_replace_pointer(ctx->engines, NULL, 1));
i915_gem_context_set_closed(ctx);
set_closed_name(ctx);
mutex_unlock(&ctx->engines_mutex);
mutex_lock(&ctx->mutex);
set_closed_name(ctx);
vm = i915_gem_context_vm(ctx);
if (vm)
i915_vm_close(vm);
@ -668,23 +757,30 @@ __create_context(struct drm_i915_private *i915)
return ERR_PTR(err);
}
static void
static int
context_apply_all(struct i915_gem_context *ctx,
void (*fn)(struct intel_context *ce, void *data),
int (*fn)(struct intel_context *ce, void *data),
void *data)
{
struct i915_gem_engines_iter it;
struct intel_context *ce;
int err = 0;
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)
fn(ce, data);
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
err = fn(ce, data);
if (err)
break;
}
i915_gem_context_unlock_engines(ctx);
return err;
}
static void __apply_ppgtt(struct intel_context *ce, void *vm)
static int __apply_ppgtt(struct intel_context *ce, void *vm)
{
i915_vm_put(ce->vm);
ce->vm = i915_vm_get(vm);
return 0;
}
static struct i915_address_space *
@ -722,9 +818,10 @@ static void __set_timeline(struct intel_timeline **dst,
intel_timeline_put(old);
}
static void __apply_timeline(struct intel_context *ce, void *timeline)
static int __apply_timeline(struct intel_context *ce, void *timeline)
{
__set_timeline(&ce->timeline, timeline);
return 0;
}
static void __assign_timeline(struct i915_gem_context *ctx,
@ -806,6 +903,7 @@ void i915_gem_init__contexts(struct drm_i915_private *i915)
void i915_gem_driver_release__contexts(struct drm_i915_private *i915)
{
flush_work(&i915->gem.contexts.free_work);
rcu_barrier(); /* and flush the left over RCU frees */
}
static int gem_context_register(struct i915_gem_context *ctx,
@ -971,6 +1069,30 @@ static void cb_retire(struct i915_active *base)
kfree(cb);
}
static inline struct i915_gem_engines *
__context_engines_await(const struct i915_gem_context *ctx)
{
struct i915_gem_engines *engines;
rcu_read_lock();
do {
engines = rcu_dereference(ctx->engines);
if (unlikely(!engines))
break;
if (unlikely(!i915_sw_fence_await(&engines->fence)))
continue;
if (likely(engines == rcu_access_pointer(ctx->engines)))
break;
i915_sw_fence_complete(&engines->fence);
} while (1);
rcu_read_unlock();
return engines;
}
I915_SELFTEST_DECLARE(static intel_engine_mask_t context_barrier_inject_fault);
static int context_barrier_task(struct i915_gem_context *ctx,
intel_engine_mask_t engines,
@ -981,6 +1103,7 @@ static int context_barrier_task(struct i915_gem_context *ctx,
{
struct context_barrier_task *cb;
struct i915_gem_engines_iter it;
struct i915_gem_engines *e;
struct intel_context *ce;
int err = 0;
@ -997,7 +1120,13 @@ static int context_barrier_task(struct i915_gem_context *ctx,
return err;
}
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
e = __context_engines_await(ctx);
if (!e) {
i915_active_release(&cb->base);
return -ENOENT;
}
for_each_gem_engine(ce, e, it) {
struct i915_request *rq;
if (I915_SELFTEST_ONLY(context_barrier_inject_fault &
@ -1028,7 +1157,7 @@ static int context_barrier_task(struct i915_gem_context *ctx,
if (err)
break;
}
i915_gem_context_unlock_engines(ctx);
i915_sw_fence_complete(&e->fence);
cb->task = err ? NULL : task; /* caller needs to unwind instead */
cb->data = data;
@ -1215,6 +1344,63 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv,
return err;
}
static int __apply_ringsize(struct intel_context *ce, void *sz)
{
return intel_context_set_ring_size(ce, (unsigned long)sz);
}
static int set_ringsize(struct i915_gem_context *ctx,
struct drm_i915_gem_context_param *args)
{
if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
return -ENODEV;
if (args->size)
return -EINVAL;
if (!IS_ALIGNED(args->value, I915_GTT_PAGE_SIZE))
return -EINVAL;
if (args->value < I915_GTT_PAGE_SIZE)
return -EINVAL;
if (args->value > 128 * I915_GTT_PAGE_SIZE)
return -EINVAL;
return context_apply_all(ctx,
__apply_ringsize,
__intel_context_ring_size(args->value));
}
static int __get_ringsize(struct intel_context *ce, void *arg)
{
long sz;
sz = intel_context_get_ring_size(ce);
GEM_BUG_ON(sz > INT_MAX);
return sz; /* stop on first engine */
}
static int get_ringsize(struct i915_gem_context *ctx,
struct drm_i915_gem_context_param *args)
{
int sz;
if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
return -ENODEV;
if (args->size)
return -EINVAL;
sz = context_apply_all(ctx, __get_ringsize, NULL);
if (sz < 0)
return sz;
args->value = sz;
return 0;
}
static int
user_to_context_sseu(struct drm_i915_private *i915,
const struct drm_i915_gem_context_param_sseu *user,
@ -1562,77 +1748,6 @@ static const i915_user_extension_fn set_engines__extensions[] = {
[I915_CONTEXT_ENGINES_EXT_BOND] = set_engines__bond,
};
static int engines_notify(struct i915_sw_fence *fence,
enum i915_sw_fence_notify state)
{
struct i915_gem_engines *engines =
container_of(fence, typeof(*engines), fence);
switch (state) {
case FENCE_COMPLETE:
if (!list_empty(&engines->link)) {
struct i915_gem_context *ctx = engines->ctx;
unsigned long flags;
spin_lock_irqsave(&ctx->stale.lock, flags);
list_del(&engines->link);
spin_unlock_irqrestore(&ctx->stale.lock, flags);
}
break;
case FENCE_FREE:
init_rcu_head(&engines->rcu);
call_rcu(&engines->rcu, free_engines_rcu);
break;
}
return NOTIFY_DONE;
}
static void engines_idle_release(struct i915_gem_engines *engines)
{
struct i915_gem_engines_iter it;
struct intel_context *ce;
unsigned long flags;
GEM_BUG_ON(!engines);
i915_sw_fence_init(&engines->fence, engines_notify);
INIT_LIST_HEAD(&engines->link);
spin_lock_irqsave(&engines->ctx->stale.lock, flags);
if (!i915_gem_context_is_closed(engines->ctx))
list_add(&engines->link, &engines->ctx->stale.engines);
spin_unlock_irqrestore(&engines->ctx->stale.lock, flags);
if (list_empty(&engines->link)) /* raced, already closed */
goto kill;
for_each_gem_engine(ce, engines, it) {
struct dma_fence *fence;
int err;
if (!ce->timeline)
continue;
fence = i915_active_fence_get(&ce->timeline->last_request);
if (!fence)
continue;
err = i915_sw_fence_await_dma_fence(&engines->fence,
fence, 0,
GFP_KERNEL);
dma_fence_put(fence);
if (err < 0)
goto kill;
}
goto out;
kill:
kill_engines(engines);
out:
i915_sw_fence_commit(&engines->fence);
}
static int
set_engines(struct i915_gem_context *ctx,
const struct drm_i915_gem_context_param *args)
@ -1669,14 +1784,10 @@ set_engines(struct i915_gem_context *ctx,
* first 64 engines defined here.
*/
num_engines = (args->size - sizeof(*user)) / sizeof(*user->engines);
set.engines = kmalloc(struct_size(set.engines, engines, num_engines),
GFP_KERNEL);
set.engines = alloc_engines(num_engines);
if (!set.engines)
return -ENOMEM;
set.engines->ctx = ctx;
for (n = 0; n < num_engines; n++) {
struct i915_engine_class_instance ci;
struct intel_engine_cs *engine;
@ -1729,6 +1840,11 @@ set_engines(struct i915_gem_context *ctx,
replace:
mutex_lock(&ctx->engines_mutex);
if (i915_gem_context_is_closed(ctx)) {
mutex_unlock(&ctx->engines_mutex);
free_engines(set.engines);
return -ENOENT;
}
if (args->size)
i915_gem_context_set_user_engines(ctx);
else
@ -1737,7 +1853,7 @@ set_engines(struct i915_gem_context *ctx,
mutex_unlock(&ctx->engines_mutex);
/* Keep track of old engine sets for kill_context() */
engines_idle_release(set.engines);
engines_idle_release(ctx, set.engines);
return 0;
}
@ -1748,7 +1864,7 @@ __copy_engines(struct i915_gem_engines *e)
struct i915_gem_engines *copy;
unsigned int n;
copy = kmalloc(struct_size(e, engines, e->num_engines), GFP_KERNEL);
copy = alloc_engines(e->num_engines);
if (!copy)
return ERR_PTR(-ENOMEM);
@ -1852,17 +1968,19 @@ set_persistence(struct i915_gem_context *ctx,
return __context_set_persistence(ctx, args->value);
}
static void __apply_priority(struct intel_context *ce, void *arg)
static int __apply_priority(struct intel_context *ce, void *arg)
{
struct i915_gem_context *ctx = arg;
if (!intel_engine_has_semaphores(ce->engine))
return;
return 0;
if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
intel_context_set_use_semaphores(ce);
else
intel_context_clear_use_semaphores(ce);
return 0;
}
static int set_priority(struct i915_gem_context *ctx,
@ -1955,6 +2073,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
ret = set_persistence(ctx, args);
break;
case I915_CONTEXT_PARAM_RINGSIZE:
ret = set_ringsize(ctx, args);
break;
case I915_CONTEXT_PARAM_BAN_PERIOD:
default:
ret = -EINVAL;
@ -1983,6 +2105,18 @@ static int create_setparam(struct i915_user_extension __user *ext, void *data)
return ctx_setparam(arg->fpriv, arg->ctx, &local.param);
}
static int copy_ring_size(struct intel_context *dst,
struct intel_context *src)
{
long sz;
sz = intel_context_get_ring_size(src);
if (sz < 0)
return sz;
return intel_context_set_ring_size(dst, sz);
}
static int clone_engines(struct i915_gem_context *dst,
struct i915_gem_context *src)
{
@ -1991,12 +2125,10 @@ static int clone_engines(struct i915_gem_context *dst,
bool user_engines;
unsigned long n;
clone = kmalloc(struct_size(e, engines, e->num_engines), GFP_KERNEL);
clone = alloc_engines(e->num_engines);
if (!clone)
goto err_unlock;
clone->ctx = dst;
for (n = 0; n < e->num_engines; n++) {
struct intel_engine_cs *engine;
@ -2026,6 +2158,12 @@ static int clone_engines(struct i915_gem_context *dst,
}
intel_context_set_gem(clone->engines[n], dst);
/* Copy across the preferred ringsize */
if (copy_ring_size(clone->engines[n], e->engines[n])) {
__free_engines(clone, n + 1);
goto err_unlock;
}
}
clone->num_engines = n;
@ -2033,8 +2171,7 @@ static int clone_engines(struct i915_gem_context *dst,
i915_gem_context_unlock_engines(src);
/* Serialised by constructor */
free_engines(__context_engines_static(dst));
RCU_INIT_POINTER(dst->engines, clone);
engines_idle_release(dst, rcu_replace_pointer(dst->engines, clone, 1));
if (user_engines)
i915_gem_context_set_user_engines(dst);
else
@ -2388,6 +2525,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
args->value = i915_gem_context_is_persistent(ctx);
break;
case I915_CONTEXT_PARAM_RINGSIZE:
ret = get_ringsize(ctx, args);
break;
case I915_CONTEXT_PARAM_BAN_PERIOD:
default:
ret = -EINVAL;
@ -2461,6 +2602,9 @@ i915_gem_engines_iter_next(struct i915_gem_engines_iter *it)
const struct i915_gem_engines *e = it->engines;
struct intel_context *ctx;
if (unlikely(!e))
return NULL;
do {
if (it->idx >= e->num_engines)
return NULL;

View File

@ -207,7 +207,6 @@ static inline void
i915_gem_engines_iter_init(struct i915_gem_engines_iter *it,
struct i915_gem_engines *engines)
{
GEM_BUG_ON(!engines);
it->engines = engines;
it->idx = 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,6 @@
#include <linux/slab.h>
#include <linux/swiotlb.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "i915_gem.h"
#include "i915_gem_object.h"

View File

@ -775,7 +775,7 @@ static struct file *mmap_singleton(struct drm_i915_private *i915)
struct file *file;
rcu_read_lock();
file = i915->gem.mmap_singleton;
file = READ_ONCE(i915->gem.mmap_singleton);
if (file && !get_file_rcu(file))
file = NULL;
rcu_read_unlock();

View File

@ -11,8 +11,6 @@
#include <drm/drm_file.h>
#include <drm/drm_device.h>
#include <drm/i915_drm.h>
#include "display/intel_frontbuffer.h"
#include "i915_gem_object_types.h"
#include "i915_gem_gtt.h"

View File

@ -186,7 +186,7 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj,
0);
out_request:
if (unlikely(err))
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
i915_request_add(rq);
out_batch:
@ -196,6 +196,17 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj,
return err;
}
/* Wa_1209644611:icl,ehl */
static bool wa_1209644611_applies(struct drm_i915_private *i915, u32 size)
{
u32 height = size >> PAGE_SHIFT;
if (!IS_GEN(i915, 11))
return false;
return height % 4 == 3 && height <= 8;
}
struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
struct i915_vma *src,
struct i915_vma *dst)
@ -237,7 +248,8 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce,
size = min_t(u64, rem, block_size);
GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX);
if (INTEL_GEN(i915) >= 9) {
if (INTEL_GEN(i915) >= 9 &&
!wa_1209644611_applies(i915, size)) {
*cmd++ = GEN9_XY_FAST_COPY_BLT_CMD | (10 - 2);
*cmd++ = BLT_DEPTH_32 | PAGE_SIZE;
*cmd++ = 0;
@ -385,7 +397,7 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src,
drm_gem_unlock_reservations(objs, ARRAY_SIZE(objs), &acquire);
out_request:
if (unlikely(err))
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
i915_request_add(rq);
out_batch:

View File

@ -194,10 +194,11 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)
/* Perma-pin (until release) the physical set of pages */
__i915_gem_object_pin_pages(obj);
if (!IS_ERR_OR_NULL(pages)) {
if (!IS_ERR_OR_NULL(pages))
i915_gem_shmem_ops.put_pages(obj, pages);
i915_gem_object_release_memory_region(obj);
}
i915_gem_object_release_memory_region(obj);
mutex_unlock(&obj->mm.lock);
return 0;

View File

@ -12,7 +12,6 @@
#include <linux/pci.h>
#include <linux/dma-buf.h>
#include <linux/vmalloc.h>
#include <drm/i915_drm.h>
#include "i915_trace.h"

View File

@ -13,6 +13,7 @@
#include "gem/i915_gem_region.h"
#include "i915_drv.h"
#include "i915_gem_stolen.h"
#include "i915_vgpu.h"
/*
* The BIOS typically reserves some of the system's memory for the exclusive

View File

@ -6,7 +6,6 @@
#include <linux/string.h>
#include <linux/bitops.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "i915_gem.h"

View File

@ -10,8 +10,6 @@
#include <linux/swap.h>
#include <linux/sched/mm.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "i915_gem_ioctls.h"
#include "i915_gem_object.h"

View File

@ -1004,7 +1004,7 @@ emit_rpcs_query(struct drm_i915_gem_object *obj,
return 0;
skip_request:
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
err_request:
i915_request_add(rq);
err_batch:
@ -1559,7 +1559,7 @@ static int write_to_scratch(struct i915_gem_context *ctx,
goto out_vm;
skip_request:
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
err_request:
i915_request_add(rq);
err_unpin:
@ -1708,7 +1708,7 @@ static int read_from_scratch(struct i915_gem_context *ctx,
goto out_vm;
skip_request:
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
err_request:
i915_request_add(rq);
err_unpin:
@ -1809,7 +1809,6 @@ static int igt_vm_isolation(void *arg)
vm_total = ctx_vm(ctx_a)->total;
GEM_BUG_ON(ctx_vm(ctx_b)->total != vm_total);
vm_total -= I915_GTT_PAGE_SIZE;
count = 0;
num_engines = 0;
@ -1828,10 +1827,10 @@ static int igt_vm_isolation(void *arg)
u32 value = 0xc5c5c5c5;
u64 offset;
div64_u64_rem(i915_prandom_u64_state(&prng),
vm_total, &offset);
offset = round_down(offset, alignof_dword);
offset += I915_GTT_PAGE_SIZE;
/* Leave enough space at offset 0 for the batch */
offset = igt_random_offset(&prng,
I915_GTT_PAGE_SIZE, vm_total,
sizeof(u32), alignof_dword);
err = write_to_scratch(ctx_a, engine,
offset, 0xdeadbeef);

View File

@ -159,7 +159,7 @@ int igt_gpu_fill_dw(struct intel_context *ce,
return 0;
skip_request:
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
err_request:
i915_request_add(rq);
err_batch:

View File

@ -23,6 +23,9 @@ mock_context(struct drm_i915_private *i915,
INIT_LIST_HEAD(&ctx->link);
ctx->i915 = i915;
spin_lock_init(&ctx->stale.lock);
INIT_LIST_HEAD(&ctx->stale.engines);
i915_gem_context_set_persistence(ctx);
mutex_init(&ctx->engines_mutex);

View File

@ -0,0 +1,402 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2019 Intel Corporation
*/
#include "gen7_renderclear.h"
#include "i915_drv.h"
#include "intel_gpu_commands.h"
#define MAX_URB_ENTRIES 64
#define STATE_SIZE (4 * 1024)
#define GT3_INLINE_DATA_DELAYS 0x1E00
#define batch_advance(Y, CS) GEM_BUG_ON((Y)->end != (CS))
struct cb_kernel {
const void *data;
u32 size;
};
#define CB_KERNEL(name) { .data = (name), .size = sizeof(name) }
#include "ivb_clear_kernel.c"
static const struct cb_kernel cb_kernel_ivb = CB_KERNEL(ivb_clear_kernel);
#include "hsw_clear_kernel.c"
static const struct cb_kernel cb_kernel_hsw = CB_KERNEL(hsw_clear_kernel);
struct batch_chunk {
struct i915_vma *vma;
u32 offset;
u32 *start;
u32 *end;
u32 max_items;
};
struct batch_vals {
u32 max_primitives;
u32 max_urb_entries;
u32 cmd_size;
u32 state_size;
u32 state_start;
u32 batch_size;
u32 surface_height;
u32 surface_width;
u32 scratch_size;
u32 max_size;
};
static void
batch_get_defaults(struct drm_i915_private *i915, struct batch_vals *bv)
{
if (IS_HASWELL(i915)) {
bv->max_primitives = 280;
bv->max_urb_entries = MAX_URB_ENTRIES;
bv->surface_height = 16 * 16;
bv->surface_width = 32 * 2 * 16;
} else {
bv->max_primitives = 128;
bv->max_urb_entries = MAX_URB_ENTRIES / 2;
bv->surface_height = 16 * 8;
bv->surface_width = 32 * 16;
}
bv->cmd_size = bv->max_primitives * 4096;
bv->state_size = STATE_SIZE;
bv->state_start = bv->cmd_size;
bv->batch_size = bv->cmd_size + bv->state_size;
bv->scratch_size = bv->surface_height * bv->surface_width;
bv->max_size = bv->batch_size + bv->scratch_size;
}
static void batch_init(struct batch_chunk *bc,
struct i915_vma *vma,
u32 *start, u32 offset, u32 max_bytes)
{
bc->vma = vma;
bc->offset = offset;
bc->start = start + bc->offset / sizeof(*bc->start);
bc->end = bc->start;
bc->max_items = max_bytes / sizeof(*bc->start);
}
static u32 batch_offset(const struct batch_chunk *bc, u32 *cs)
{
return (cs - bc->start) * sizeof(*bc->start) + bc->offset;
}
static u32 batch_addr(const struct batch_chunk *bc)
{
return bc->vma->node.start;
}
static void batch_add(struct batch_chunk *bc, const u32 d)
{
GEM_BUG_ON((bc->end - bc->start) >= bc->max_items);
*bc->end++ = d;
}
static u32 *batch_alloc_items(struct batch_chunk *bc, u32 align, u32 items)
{
u32 *map;
if (align) {
u32 *end = PTR_ALIGN(bc->end, align);
memset32(bc->end, 0, end - bc->end);
bc->end = end;
}
map = bc->end;
bc->end += items;
return map;
}
static u32 *batch_alloc_bytes(struct batch_chunk *bc, u32 align, u32 bytes)
{
GEM_BUG_ON(!IS_ALIGNED(bytes, sizeof(*bc->start)));
return batch_alloc_items(bc, align, bytes / sizeof(*bc->start));
}
static u32
gen7_fill_surface_state(struct batch_chunk *state,
const u32 dst_offset,
const struct batch_vals *bv)
{
u32 surface_h = bv->surface_height;
u32 surface_w = bv->surface_width;
u32 *cs = batch_alloc_items(state, 32, 8);
u32 offset = batch_offset(state, cs);
#define SURFACE_2D 1
#define SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0
#define RENDER_CACHE_READ_WRITE 1
*cs++ = SURFACE_2D << 29 |
(SURFACEFORMAT_B8G8R8A8_UNORM << 18) |
(RENDER_CACHE_READ_WRITE << 8);
*cs++ = batch_addr(state) + dst_offset;
*cs++ = ((surface_h / 4 - 1) << 16) | (surface_w / 4 - 1);
*cs++ = surface_w;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
#define SHADER_CHANNELS(r, g, b, a) \
(((r) << 25) | ((g) << 22) | ((b) << 19) | ((a) << 16))
*cs++ = SHADER_CHANNELS(4, 5, 6, 7);
batch_advance(state, cs);
return offset;
}
static u32
gen7_fill_binding_table(struct batch_chunk *state,
const struct batch_vals *bv)
{
u32 surface_start = gen7_fill_surface_state(state, bv->batch_size, bv);
u32 *cs = batch_alloc_items(state, 32, 8);
u32 offset = batch_offset(state, cs);
*cs++ = surface_start - state->offset;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
batch_advance(state, cs);
return offset;
}
static u32
gen7_fill_kernel_data(struct batch_chunk *state,
const u32 *data,
const u32 size)
{
return batch_offset(state,
memcpy(batch_alloc_bytes(state, 64, size),
data, size));
}
static u32
gen7_fill_interface_descriptor(struct batch_chunk *state,
const struct batch_vals *bv,
const struct cb_kernel *kernel,
unsigned int count)
{
u32 kernel_offset =
gen7_fill_kernel_data(state, kernel->data, kernel->size);
u32 binding_table = gen7_fill_binding_table(state, bv);
u32 *cs = batch_alloc_items(state, 32, 8 * count);
u32 offset = batch_offset(state, cs);
*cs++ = kernel_offset;
*cs++ = (1 << 7) | (1 << 13);
*cs++ = 0;
*cs++ = (binding_table - state->offset) | 1;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
/* 1 - 63dummy idds */
memset32(cs, 0x00, (count - 1) * 8);
batch_advance(state, cs + (count - 1) * 8);
return offset;
}
static void
gen7_emit_state_base_address(struct batch_chunk *batch,
u32 surface_state_base)
{
u32 *cs = batch_alloc_items(batch, 0, 12);
*cs++ = STATE_BASE_ADDRESS | (12 - 2);
/* general */
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
/* surface */
*cs++ = batch_addr(batch) | surface_state_base | BASE_ADDRESS_MODIFY;
/* dynamic */
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
/* indirect */
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
/* instruction */
*cs++ = batch_addr(batch) | BASE_ADDRESS_MODIFY;
/* general/dynamic/indirect/instruction access Bound */
*cs++ = 0;
*cs++ = BASE_ADDRESS_MODIFY;
*cs++ = 0;
*cs++ = BASE_ADDRESS_MODIFY;
*cs++ = 0;
*cs++ = 0;
batch_advance(batch, cs);
}
static void
gen7_emit_vfe_state(struct batch_chunk *batch,
const struct batch_vals *bv,
u32 urb_size, u32 curbe_size,
u32 mode)
{
u32 urb_entries = bv->max_urb_entries;
u32 threads = bv->max_primitives - 1;
u32 *cs = batch_alloc_items(batch, 32, 8);
*cs++ = MEDIA_VFE_STATE | (8 - 2);
/* scratch buffer */
*cs++ = 0;
/* number of threads & urb entries for GPGPU vs Media Mode */
*cs++ = threads << 16 | urb_entries << 8 | mode << 2;
*cs++ = 0;
/* urb entry size & curbe size in 256 bits unit */
*cs++ = urb_size << 16 | curbe_size;
/* scoreboard */
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
batch_advance(batch, cs);
}
static void
gen7_emit_interface_descriptor_load(struct batch_chunk *batch,
const u32 interface_descriptor,
unsigned int count)
{
u32 *cs = batch_alloc_items(batch, 8, 4);
*cs++ = MEDIA_INTERFACE_DESCRIPTOR_LOAD | (4 - 2);
*cs++ = 0;
*cs++ = count * 8 * sizeof(*cs);
/*
* interface descriptor address - it is relative to the dynamics base
* address
*/
*cs++ = interface_descriptor;
batch_advance(batch, cs);
}
static void
gen7_emit_media_object(struct batch_chunk *batch,
unsigned int media_object_index)
{
unsigned int x_offset = (media_object_index % 16) * 64;
unsigned int y_offset = (media_object_index / 16) * 16;
unsigned int inline_data_size;
unsigned int media_batch_size;
unsigned int i;
u32 *cs;
inline_data_size = 112 * 8;
media_batch_size = inline_data_size + 6;
cs = batch_alloc_items(batch, 8, media_batch_size);
*cs++ = MEDIA_OBJECT | (media_batch_size - 2);
/* interface descriptor offset */
*cs++ = 0;
/* without indirect data */
*cs++ = 0;
*cs++ = 0;
/* scoreboard */
*cs++ = 0;
*cs++ = 0;
/* inline */
*cs++ = (y_offset << 16) | (x_offset);
*cs++ = 0;
*cs++ = GT3_INLINE_DATA_DELAYS;
for (i = 3; i < inline_data_size; i++)
*cs++ = 0;
batch_advance(batch, cs);
}
static void gen7_emit_pipeline_flush(struct batch_chunk *batch)
{
u32 *cs = batch_alloc_items(batch, 0, 5);
*cs++ = GFX_OP_PIPE_CONTROL(5);
*cs++ = PIPE_CONTROL_STATE_CACHE_INVALIDATE |
PIPE_CONTROL_GLOBAL_GTT_IVB;
*cs++ = 0;
*cs++ = 0;
*cs++ = 0;
batch_advance(batch, cs);
}
static void emit_batch(struct i915_vma * const vma,
u32 *start,
const struct batch_vals *bv)
{
struct drm_i915_private *i915 = vma->vm->i915;
unsigned int desc_count = 64;
const u32 urb_size = 112;
struct batch_chunk cmds, state;
u32 interface_descriptor;
unsigned int i;
batch_init(&cmds, vma, start, 0, bv->cmd_size);
batch_init(&state, vma, start, bv->state_start, bv->state_size);
interface_descriptor =
gen7_fill_interface_descriptor(&state, bv,
IS_HASWELL(i915) ?
&cb_kernel_hsw :
&cb_kernel_ivb,
desc_count);
gen7_emit_pipeline_flush(&cmds);
batch_add(&cmds, PIPELINE_SELECT | PIPELINE_SELECT_MEDIA);
batch_add(&cmds, MI_NOOP);
gen7_emit_state_base_address(&cmds, interface_descriptor);
gen7_emit_pipeline_flush(&cmds);
gen7_emit_vfe_state(&cmds, bv, urb_size - 1, 0, 0);
gen7_emit_interface_descriptor_load(&cmds,
interface_descriptor,
desc_count);
for (i = 0; i < bv->max_primitives; i++)
gen7_emit_media_object(&cmds, i);
batch_add(&cmds, MI_BATCH_BUFFER_END);
}
int gen7_setup_clear_gpr_bb(struct intel_engine_cs * const engine,
struct i915_vma * const vma)
{
struct batch_vals bv;
u32 *batch;
batch_get_defaults(engine->i915, &bv);
if (!vma)
return bv.max_size;
GEM_BUG_ON(vma->obj->base.size < bv.max_size);
batch = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
if (IS_ERR(batch))
return PTR_ERR(batch);
emit_batch(vma, memset(batch, 0, bv.max_size), &bv);
i915_gem_object_flush_map(vma->obj);
i915_gem_object_unpin_map(vma->obj);
return 0;
}

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2019 Intel Corporation
*/
#ifndef __GEN7_RENDERCLEAR_H__
#define __GEN7_RENDERCLEAR_H__
struct intel_engine_cs;
struct i915_vma;
int gen7_setup_clear_gpr_bb(struct intel_engine_cs * const engine,
struct i915_vma * const vma);
#endif /* __GEN7_RENDERCLEAR_H__ */

View File

@ -8,6 +8,7 @@
#include "gen8_ppgtt.h"
#include "i915_scatterlist.h"
#include "i915_trace.h"
#include "i915_pvinfo.h"
#include "i915_vgpu.h"
#include "intel_gt.h"
#include "intel_gtt.h"
@ -25,6 +26,30 @@ static u64 gen8_pde_encode(const dma_addr_t addr,
return pde;
}
static u64 gen8_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
u32 flags)
{
gen8_pte_t pte = addr | _PAGE_PRESENT | _PAGE_RW;
if (unlikely(flags & PTE_READ_ONLY))
pte &= ~_PAGE_RW;
switch (level) {
case I915_CACHE_NONE:
pte |= PPAT_UNCACHED;
break;
case I915_CACHE_WT:
pte |= PPAT_DISPLAY_ELLC;
break;
default:
pte |= PPAT_CACHED;
break;
}
return pte;
}
static void gen8_ppgtt_notify_vgt(struct i915_ppgtt *ppgtt, bool create)
{
struct drm_i915_private *i915 = ppgtt->vm.i915;
@ -706,6 +731,8 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
ppgtt->vm.clear_range = gen8_ppgtt_clear;
ppgtt->vm.pte_encode = gen8_pte_encode;
if (intel_vgpu_active(gt->i915))
gen8_ppgtt_notify_vgt(ppgtt, true);

View File

@ -0,0 +1,61 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2020 Intel Corporation
*
* Generated by: IGT Gpu Tools on Fri 21 Feb 2020 05:30:13 AM UTC
*/
static const u32 hsw_clear_kernel[] = {
0x00000001, 0x26020128, 0x00000024, 0x00000000,
0x00000040, 0x20280c21, 0x00000028, 0x00000001,
0x01000010, 0x20000c20, 0x0000002c, 0x00000000,
0x00010220, 0x34001c00, 0x00001400, 0x00000160,
0x00600001, 0x20600061, 0x00000000, 0x00000000,
0x00000008, 0x20601c85, 0x00000e00, 0x0000000c,
0x00000005, 0x20601ca5, 0x00000060, 0x00000001,
0x00000008, 0x20641c85, 0x00000e00, 0x0000000d,
0x00000005, 0x20641ca5, 0x00000064, 0x00000003,
0x00000041, 0x207424a5, 0x00000064, 0x00000034,
0x00000040, 0x206014a5, 0x00000060, 0x00000074,
0x00000008, 0x20681c85, 0x00000e00, 0x00000008,
0x00000005, 0x20681ca5, 0x00000068, 0x0000000f,
0x00000041, 0x20701ca5, 0x00000060, 0x00000010,
0x00000040, 0x206814a5, 0x00000068, 0x00000070,
0x00600001, 0x20a00061, 0x00000000, 0x00000000,
0x00000005, 0x206c1c85, 0x00000e00, 0x00000007,
0x00000041, 0x206c1ca5, 0x0000006c, 0x00000004,
0x00600001, 0x20800021, 0x008d0000, 0x00000000,
0x00000001, 0x20800021, 0x0000006c, 0x00000000,
0x00000001, 0x20840021, 0x00000068, 0x00000000,
0x00000001, 0x20880061, 0x00000000, 0x00000003,
0x00000005, 0x208c0d21, 0x00000086, 0xffffffff,
0x05600032, 0x20a00fa1, 0x008d0080, 0x02190001,
0x00000040, 0x20a01ca5, 0x000000a0, 0x00000001,
0x05600032, 0x20a00fa1, 0x008d0080, 0x040a8001,
0x02000040, 0x20281c21, 0x00000028, 0xffffffff,
0x00010220, 0x34001c00, 0x00001400, 0xffffffe0,
0x00000001, 0x26020128, 0x00000024, 0x00000000,
0x00000001, 0x220010e4, 0x00000000, 0x00000000,
0x00000001, 0x220831ec, 0x00000000, 0x007f007f,
0x00600001, 0x20400021, 0x008d0000, 0x00000000,
0x00600001, 0x2fe00021, 0x008d0000, 0x00000000,
0x00200001, 0x20400121, 0x00450020, 0x00000000,
0x00000001, 0x20480061, 0x00000000, 0x000f000f,
0x00000005, 0x204c0d21, 0x00000046, 0xffffffef,
0x00800001, 0x20600061, 0x00000000, 0x00000000,
0x00800001, 0x20800061, 0x00000000, 0x00000000,
0x00800001, 0x20a00061, 0x00000000, 0x00000000,
0x00800001, 0x20c00061, 0x00000000, 0x00000000,
0x00800001, 0x20e00061, 0x00000000, 0x00000000,
0x00800001, 0x21000061, 0x00000000, 0x00000000,
0x00800001, 0x21200061, 0x00000000, 0x00000000,
0x00800001, 0x21400061, 0x00000000, 0x00000000,
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
0x00000040, 0x20402d21, 0x00000020, 0x00100010,
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
0x02000040, 0x22083d8c, 0x00000208, 0xffffffff,
0x00800001, 0xa0000109, 0x00000602, 0x00000000,
0x00000040, 0x22001c84, 0x00000200, 0x00000020,
0x00010220, 0x34001c00, 0x00001400, 0xffffffc0,
0x07600032, 0x20000fa0, 0x008d0fe0, 0x82000010,
};

View File

@ -51,6 +51,11 @@ int intel_context_alloc_state(struct intel_context *ce)
return -EINTR;
if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
if (intel_context_is_banned(ce)) {
err = -EIO;
goto unlock;
}
err = ce->ops->alloc(ce);
if (unlikely(err))
goto unlock;

View File

@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2019 Intel Corporation
*/
#include "i915_active.h"
#include "intel_context.h"
#include "intel_context_param.h"
#include "intel_ring.h"
int intel_context_set_ring_size(struct intel_context *ce, long sz)
{
int err;
if (intel_context_lock_pinned(ce))
return -EINTR;
err = i915_active_wait(&ce->active);
if (err < 0)
goto unlock;
if (intel_context_is_pinned(ce)) {
err = -EBUSY; /* In active use, come back later! */
goto unlock;
}
if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
struct intel_ring *ring;
/* Replace the existing ringbuffer */
ring = intel_engine_create_ring(ce->engine, sz);
if (IS_ERR(ring)) {
err = PTR_ERR(ring);
goto unlock;
}
intel_ring_put(ce->ring);
ce->ring = ring;
/* Context image will be updated on next pin */
} else {
ce->ring = __intel_context_ring_size(sz);
}
unlock:
intel_context_unlock_pinned(ce);
return err;
}
long intel_context_get_ring_size(struct intel_context *ce)
{
long sz = (unsigned long)READ_ONCE(ce->ring);
if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
if (intel_context_lock_pinned(ce))
return -EINTR;
sz = ce->ring->size;
intel_context_unlock_pinned(ce);
}
return sz;
}

View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2019 Intel Corporation
*/
#ifndef INTEL_CONTEXT_PARAM_H
#define INTEL_CONTEXT_PARAM_H
struct intel_context;
int intel_context_set_ring_size(struct intel_context *ce, long sz);
long intel_context_get_ring_size(struct intel_context *ce);
#endif /* INTEL_CONTEXT_PARAM_H */

View File

@ -45,8 +45,8 @@ struct intel_context {
struct intel_engine_cs *engine;
struct intel_engine_cs *inflight;
#define intel_context_inflight(ce) ptr_mask_bits((ce)->inflight, 2)
#define intel_context_inflight_count(ce) ptr_unmask_bits((ce)->inflight, 2)
#define intel_context_inflight(ce) ptr_mask_bits(READ_ONCE((ce)->inflight), 2)
#define intel_context_inflight_count(ce) ptr_unmask_bits(READ_ONCE((ce)->inflight), 2)
struct i915_address_space *vm;
struct i915_gem_context __rcu *gem_context;

View File

@ -107,7 +107,20 @@ execlists_num_ports(const struct intel_engine_execlists * const execlists)
static inline struct i915_request *
execlists_active(const struct intel_engine_execlists *execlists)
{
return *READ_ONCE(execlists->active);
struct i915_request * const *cur, * const *old, *active;
cur = READ_ONCE(execlists->active);
smp_rmb(); /* pairs with overwrite protection in process_csb() */
do {
old = cur;
active = READ_ONCE(*cur);
cur = READ_ONCE(execlists->active);
smp_rmb(); /* and complete the seqlock retry */
} while (unlikely(cur != old));
return active;
}
static inline void

View File

@ -275,6 +275,7 @@ static void intel_engine_sanitize_mmio(struct intel_engine_cs *engine)
static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
{
const struct engine_info *info = &intel_engines[id];
struct drm_i915_private *i915 = gt->i915;
struct intel_engine_cs *engine;
BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH));
@ -301,11 +302,11 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
engine->id = id;
engine->legacy_idx = INVALID_ENGINE;
engine->mask = BIT(id);
engine->i915 = gt->i915;
engine->i915 = i915;
engine->gt = gt;
engine->uncore = gt->uncore;
engine->hw_id = engine->guc_id = info->hw_id;
engine->mmio_base = __engine_mmio_base(gt->i915, info->mmio_bases);
engine->mmio_base = __engine_mmio_base(i915, info->mmio_bases);
engine->class = info->class;
engine->instance = info->instance;
@ -313,6 +314,8 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
engine->props.heartbeat_interval_ms =
CONFIG_DRM_I915_HEARTBEAT_INTERVAL;
engine->props.max_busywait_duration_ns =
CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT;
engine->props.preempt_timeout_ms =
CONFIG_DRM_I915_PREEMPT_TIMEOUT;
engine->props.stop_timeout_ms =
@ -320,11 +323,15 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
engine->props.timeslice_duration_ms =
CONFIG_DRM_I915_TIMESLICE_DURATION;
/* Override to uninterruptible for OpenCL workloads. */
if (INTEL_GEN(i915) == 12 && engine->class == RENDER_CLASS)
engine->props.preempt_timeout_ms = 0;
engine->context_size = intel_engine_context_size(gt, engine->class);
if (WARN_ON(engine->context_size > BIT(20)))
engine->context_size = 0;
if (engine->context_size)
DRIVER_CAPS(gt->i915)->has_logical_contexts = true;
DRIVER_CAPS(i915)->has_logical_contexts = true;
/* Nothing to do here, execute in order of dependencies */
engine->schedule = NULL;
@ -340,7 +347,7 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
gt->engine_class[info->class][info->instance] = engine;
gt->engine[id] = engine;
gt->i915->engine[id] = engine;
i915->engine[id] = engine;
return 0;
}
@ -1379,24 +1386,24 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
char hdr[160];
int len;
len = snprintf(hdr, sizeof(hdr),
"\t\tActive[%d]: ",
(int)(port - execlists->active));
len = scnprintf(hdr, sizeof(hdr),
"\t\tActive[%d]: ",
(int)(port - execlists->active));
if (!i915_request_signaled(rq)) {
struct intel_timeline *tl = get_timeline(rq);
len += snprintf(hdr + len, sizeof(hdr) - len,
"ring:{start:%08x, hwsp:%08x, seqno:%08x, runtime:%llums}, ",
i915_ggtt_offset(rq->ring->vma),
tl ? tl->hwsp_offset : 0,
hwsp_seqno(rq),
DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context),
1000 * 1000));
len += scnprintf(hdr + len, sizeof(hdr) - len,
"ring:{start:%08x, hwsp:%08x, seqno:%08x, runtime:%llums}, ",
i915_ggtt_offset(rq->ring->vma),
tl ? tl->hwsp_offset : 0,
hwsp_seqno(rq),
DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context),
1000 * 1000));
if (tl)
intel_timeline_put(tl);
}
snprintf(hdr + len, sizeof(hdr) - len, "rq: ");
scnprintf(hdr + len, sizeof(hdr) - len, "rq: ");
print_request(m, rq, hdr);
}
for (port = execlists->pending; (rq = *port); port++) {

View File

@ -547,6 +547,7 @@ struct intel_engine_cs {
struct {
unsigned long heartbeat_interval_ms;
unsigned long max_busywait_duration_ns;
unsigned long preempt_timeout_ms;
unsigned long stop_timeout_ms;
unsigned long timeslice_duration_ms;

View File

@ -8,6 +8,8 @@
#include <asm/set_memory.h>
#include <asm/smp.h>
#include <drm/i915_drm.h>
#include "intel_gt.h"
#include "i915_drv.h"
#include "i915_scatterlist.h"
@ -157,6 +159,13 @@ static void gmch_ggtt_invalidate(struct i915_ggtt *ggtt)
intel_gtt_chipset_flush();
}
static u64 gen8_ggtt_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
u32 flags)
{
return addr | _PAGE_PRESENT;
}
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
{
writeq(pte, addr);
@ -172,7 +181,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
gen8_pte_t __iomem *pte =
(gen8_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE;
gen8_set_pte(pte, gen8_pte_encode(addr, level, 0));
gen8_set_pte(pte, gen8_ggtt_pte_encode(addr, level, 0));
ggtt->invalidate(ggtt);
}
@ -185,7 +194,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
struct sgt_iter sgt_iter;
gen8_pte_t __iomem *gtt_entries;
const gen8_pte_t pte_encode = gen8_pte_encode(0, level, 0);
const gen8_pte_t pte_encode = gen8_ggtt_pte_encode(0, level, 0);
dma_addr_t addr;
/*
@ -857,7 +866,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
ggtt->vm.vma_ops.set_pages = ggtt_set_pages;
ggtt->vm.vma_ops.clear_pages = clear_pages;
ggtt->vm.pte_encode = gen8_pte_encode;
ggtt->vm.pte_encode = gen8_ggtt_pte_encode;
setup_private_pat(ggtt->vm.gt->uncore);

View File

@ -292,10 +292,21 @@
#define MI_STORE_URB_MEM MI_INSTR(0x2D, 0)
#define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0)
#define PIPELINE_SELECT ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16))
#define GFX_OP_3DSTATE_VF_STATISTICS ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16))
#define MEDIA_VFE_STATE ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<16))
#define STATE_BASE_ADDRESS \
((0x3 << 29) | (0x0 << 27) | (0x1 << 24) | (0x1 << 16))
#define BASE_ADDRESS_MODIFY REG_BIT(0)
#define PIPELINE_SELECT \
((0x3 << 29) | (0x1 << 27) | (0x1 << 24) | (0x4 << 16))
#define PIPELINE_SELECT_MEDIA REG_BIT(0)
#define GFX_OP_3DSTATE_VF_STATISTICS \
((0x3 << 29) | (0x1 << 27) | (0x0 << 24) | (0xB << 16))
#define MEDIA_VFE_STATE \
((0x3 << 29) | (0x2 << 27) | (0x0 << 24) | (0x0 << 16))
#define MEDIA_VFE_STATE_MMIO_ACCESS_MASK (0x18)
#define MEDIA_INTERFACE_DESCRIPTOR_LOAD \
((0x3 << 29) | (0x2 << 27) | (0x0 << 24) | (0x2 << 16))
#define MEDIA_OBJECT \
((0x3 << 29) | (0x2 << 27) | (0x1 << 24) | (0x0 << 16))
#define GPGPU_OBJECT ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
#define GPGPU_WALKER ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \

View File

@ -667,6 +667,9 @@ void intel_gt_driver_release(struct intel_gt *gt)
void intel_gt_driver_late_release(struct intel_gt *gt)
{
/* We need to wait for inflight RCU frees to release their grip */
rcu_barrier();
intel_uc_driver_late_release(&gt->uc);
intel_gt_fini_requests(gt);
intel_gt_fini_reset(gt);

View File

@ -171,7 +171,9 @@ void __i915_vm_close(struct i915_address_space *vm)
{
struct i915_vma *vma, *vn;
mutex_lock(&vm->mutex);
if (!atomic_dec_and_mutex_lock(&vm->open, &vm->mutex))
return;
list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) {
struct drm_i915_gem_object *obj = vma->obj;
@ -186,6 +188,7 @@ void __i915_vm_close(struct i915_address_space *vm)
i915_gem_object_put(obj);
}
GEM_BUG_ON(!list_empty(&vm->bound_list));
mutex_unlock(&vm->mutex);
}
@ -484,30 +487,6 @@ void gtt_write_workarounds(struct intel_gt *gt)
}
}
u64 gen8_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
u32 flags)
{
gen8_pte_t pte = addr | _PAGE_PRESENT | _PAGE_RW;
if (unlikely(flags & PTE_READ_ONLY))
pte &= ~_PAGE_RW;
switch (level) {
case I915_CACHE_NONE:
pte |= PPAT_UNCACHED;
break;
case I915_CACHE_WT:
pte |= PPAT_DISPLAY_ELLC;
break;
default:
pte |= PPAT_CACHED;
break;
}
return pte;
}
static void tgl_setup_private_ppat(struct intel_uncore *uncore)
{
/* TGL doesn't support LLC or AGE settings */

View File

@ -429,8 +429,7 @@ static inline void
i915_vm_close(struct i915_address_space *vm)
{
GEM_BUG_ON(!atomic_read(&vm->open));
if (atomic_dec_and_test(&vm->open))
__i915_vm_close(vm);
__i915_vm_close(vm);
i915_vm_put(vm);
}
@ -515,10 +514,6 @@ struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt);
void i915_ggtt_suspend(struct i915_ggtt *gtt);
void i915_ggtt_resume(struct i915_ggtt *ggtt);
u64 gen8_pte_encode(dma_addr_t addr,
enum i915_cache_level level,
u32 flags);
int setup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p);
void cleanup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p);

View File

@ -245,7 +245,7 @@ static void mark_eio(struct i915_request *rq)
GEM_BUG_ON(i915_request_signaled(rq));
dma_fence_set_error(&rq->fence, -EIO);
i915_request_set_error_once(rq, -EIO);
i915_request_mark_complete(rq);
}
@ -293,7 +293,7 @@ static inline struct i915_priolist *to_priolist(struct rb_node *rb)
static inline int rq_prio(const struct i915_request *rq)
{
return rq->sched.attr.priority;
return READ_ONCE(rq->sched.attr.priority);
}
static int effective_prio(const struct i915_request *rq)
@ -1004,7 +1004,7 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
i915_request_cancel_breadcrumb(rq);
spin_unlock(&rq->lock);
}
rq->engine = owner;
WRITE_ONCE(rq->engine, owner);
owner->submit_request(rq);
active = NULL;
}
@ -1316,7 +1316,7 @@ __execlists_schedule_out(struct i915_request *rq,
* If we have just completed this context, the engine may now be
* idle and we want to re-enter powersaving.
*/
if (list_is_last(&rq->link, &ce->timeline->requests) &&
if (list_is_last_rcu(&rq->link, &ce->timeline->requests) &&
i915_request_completed(rq))
intel_engine_add_retire(engine, ce->timeline);
@ -1448,6 +1448,7 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
{
struct i915_request * const *port, *rq;
struct intel_context *ce = NULL;
bool sentinel = false;
trace_ports(execlists, msg, execlists->pending);
@ -1481,6 +1482,26 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
}
ce = rq->context;
/*
* Sentinels are supposed to be lonely so they flush the
* current exection off the HW. Check that they are the
* only request in the pending submission.
*/
if (sentinel) {
GEM_TRACE_ERR("context:%llx after sentinel in pending[%zd]\n",
ce->timeline->fence_context,
port - execlists->pending);
return false;
}
sentinel = i915_request_has_sentinel(rq);
if (sentinel && port != execlists->pending) {
GEM_TRACE_ERR("sentinel context:%llx not in prime position[%zd]\n",
ce->timeline->fence_context,
port - execlists->pending);
return false;
}
/* Hold tightly onto the lock to prevent concurrent retires! */
if (!spin_trylock_irqsave(&rq->lock, flags))
continue;
@ -1576,6 +1597,11 @@ static bool can_merge_ctx(const struct intel_context *prev,
return true;
}
static unsigned long i915_request_flags(const struct i915_request *rq)
{
return READ_ONCE(rq->fence.flags);
}
static bool can_merge_rq(const struct i915_request *prev,
const struct i915_request *next)
{
@ -1593,7 +1619,7 @@ static bool can_merge_rq(const struct i915_request *prev,
if (i915_request_completed(next))
return true;
if (unlikely((prev->fence.flags ^ next->fence.flags) &
if (unlikely((i915_request_flags(prev) ^ i915_request_flags(next)) &
(BIT(I915_FENCE_FLAG_NOPREEMPT) |
BIT(I915_FENCE_FLAG_SENTINEL))))
return false;
@ -1601,6 +1627,7 @@ static bool can_merge_rq(const struct i915_request *prev,
if (!can_merge_ctx(prev->context, next->context))
return false;
GEM_BUG_ON(i915_seqno_passed(prev->fence.seqno, next->fence.seqno));
return true;
}
@ -1651,17 +1678,6 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve,
spin_unlock(&old->breadcrumbs.irq_lock);
}
static struct i915_request *
last_active(const struct intel_engine_execlists *execlists)
{
struct i915_request * const *last = READ_ONCE(execlists->active);
while (*last && i915_request_completed(*last))
last++;
return *last;
}
#define for_each_waiter(p__, rq__) \
list_for_each_entry_lockless(p__, \
&(rq__)->sched.waiters_list, \
@ -1735,11 +1751,9 @@ need_timeslice(struct intel_engine_cs *engine, const struct i915_request *rq)
if (!intel_engine_has_timeslices(engine))
return false;
if (list_is_last(&rq->sched.link, &engine->active.requests))
return false;
hint = max(rq_prio(list_next_entry(rq, sched.link)),
engine->execlists.queue_priority_hint);
hint = engine->execlists.queue_priority_hint;
if (!list_is_last(&rq->sched.link, &engine->active.requests))
hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
return hint >= effective_prio(rq);
}
@ -1762,12 +1776,13 @@ timeslice(const struct intel_engine_cs *engine)
static unsigned long
active_timeslice(const struct intel_engine_cs *engine)
{
const struct i915_request *rq = *engine->execlists.active;
const struct intel_engine_execlists *execlists = &engine->execlists;
const struct i915_request *rq = *execlists->active;
if (!rq || i915_request_completed(rq))
return 0;
if (engine->execlists.switch_priority_hint < effective_prio(rq))
if (READ_ONCE(execlists->switch_priority_hint) < effective_prio(rq))
return 0;
return timeslice(engine);
@ -1781,16 +1796,29 @@ static void set_timeslice(struct intel_engine_cs *engine)
set_timer_ms(&engine->execlists.timer, active_timeslice(engine));
}
static void start_timeslice(struct intel_engine_cs *engine)
{
struct intel_engine_execlists *execlists = &engine->execlists;
int prio = queue_prio(execlists);
WRITE_ONCE(execlists->switch_priority_hint, prio);
if (prio == INT_MIN)
return;
if (timer_pending(&execlists->timer))
return;
set_timer_ms(&execlists->timer, timeslice(engine));
}
static void record_preemption(struct intel_engine_execlists *execlists)
{
(void)I915_SELFTEST_ONLY(execlists->preempt_hang.count++);
}
static unsigned long active_preempt_timeout(struct intel_engine_cs *engine)
static unsigned long active_preempt_timeout(struct intel_engine_cs *engine,
const struct i915_request *rq)
{
struct i915_request *rq;
rq = last_active(&engine->execlists);
if (!rq)
return 0;
@ -1801,13 +1829,14 @@ static unsigned long active_preempt_timeout(struct intel_engine_cs *engine)
return READ_ONCE(engine->props.preempt_timeout_ms);
}
static void set_preempt_timeout(struct intel_engine_cs *engine)
static void set_preempt_timeout(struct intel_engine_cs *engine,
const struct i915_request *rq)
{
if (!intel_engine_has_preempt_reset(engine))
return;
set_timer_ms(&engine->execlists.preempt,
active_preempt_timeout(engine));
active_preempt_timeout(engine, rq));
}
static inline void clear_ports(struct i915_request **ports, int count)
@ -1820,6 +1849,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
struct intel_engine_execlists * const execlists = &engine->execlists;
struct i915_request **port = execlists->pending;
struct i915_request ** const last_port = port + execlists->port_mask;
struct i915_request * const *active;
struct i915_request *last;
struct rb_node *rb;
bool submit = false;
@ -1874,7 +1904,10 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* i.e. we will retrigger preemption following the ack in case
* of trouble.
*/
last = last_active(execlists);
active = READ_ONCE(execlists->active);
while ((last = *active) && i915_request_completed(last))
active++;
if (last) {
if (need_preempt(engine, last, rb)) {
ENGINE_TRACE(engine,
@ -1944,11 +1977,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* Even if ELSP[1] is occupied and not worthy
* of timeslices, our queue might be.
*/
if (!execlists->timer.expires &&
need_timeslice(engine, last))
set_timer_ms(&execlists->timer,
timeslice(engine));
start_timeslice(engine);
return;
}
}
@ -1983,7 +2012,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
if (last && !can_merge_rq(last, rq)) {
spin_unlock(&ve->base.active.lock);
return; /* leave this for another */
start_timeslice(engine);
return; /* leave this for another sibling */
}
ENGINE_TRACE(engine,
@ -1995,13 +2025,14 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
"",
yesno(engine != ve->siblings[0]));
ve->request = NULL;
ve->base.execlists.queue_priority_hint = INT_MIN;
WRITE_ONCE(ve->request, NULL);
WRITE_ONCE(ve->base.execlists.queue_priority_hint,
INT_MIN);
rb_erase_cached(rb, &execlists->virtual);
RB_CLEAR_NODE(rb);
GEM_BUG_ON(!(rq->execution_mask & engine->mask));
rq->engine = engine;
WRITE_ONCE(rq->engine, engine);
if (engine != ve->siblings[0]) {
u32 *regs = ve->context.lrc_reg_state;
@ -2121,6 +2152,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
GEM_BUG_ON(last &&
!can_merge_ctx(last->context,
rq->context));
GEM_BUG_ON(last &&
i915_seqno_passed(last->fence.seqno,
rq->fence.seqno));
submit = true;
last = rq;
@ -2159,7 +2193,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
* Skip if we ended up with exactly the same set of requests,
* e.g. trying to timeslice a pair of ordered contexts
*/
if (!memcmp(execlists->active, execlists->pending,
if (!memcmp(active, execlists->pending,
(port - execlists->pending + 1) * sizeof(*port))) {
do
execlists_schedule_out(fetch_and_zero(port));
@ -2170,7 +2204,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
clear_ports(port + 1, last_port - port);
execlists_submit_ports(engine);
set_preempt_timeout(engine);
set_preempt_timeout(engine, *active);
} else {
skip_submit:
ring_set_paused(engine, 0);
@ -2191,6 +2225,7 @@ cancel_port_requests(struct intel_engine_execlists * const execlists)
execlists_schedule_out(*port);
clear_ports(execlists->inflight, ARRAY_SIZE(execlists->inflight));
smp_wmb(); /* complete the seqlock for execlists_active() */
WRITE_ONCE(execlists->active, execlists->inflight);
}
@ -2345,6 +2380,7 @@ static void process_csb(struct intel_engine_cs *engine)
/* Point active to the new ELSP; prevent overwriting */
WRITE_ONCE(execlists->active, execlists->pending);
smp_wmb(); /* notify execlists_active() */
/* cancel old inflight, prepare for switch */
trace_ports(execlists, "preempted", old);
@ -2352,11 +2388,12 @@ static void process_csb(struct intel_engine_cs *engine)
execlists_schedule_out(*old++);
/* switch pending to inflight */
WRITE_ONCE(execlists->active,
memcpy(execlists->inflight,
execlists->pending,
execlists_num_ports(execlists) *
sizeof(*execlists->pending)));
memcpy(execlists->inflight,
execlists->pending,
execlists_num_ports(execlists) *
sizeof(*execlists->pending));
smp_wmb(); /* complete the seqlock */
WRITE_ONCE(execlists->active, execlists->inflight);
WRITE_ONCE(execlists->pending[0], NULL);
} else {
@ -2579,6 +2616,10 @@ static void __execlists_unhold(struct i915_request *rq)
struct i915_request *w =
container_of(p->waiter, typeof(*w), sched);
/* Propagate any change in error status */
if (rq->fence.error)
i915_request_set_error_once(w, rq->fence.error);
if (w->engine != rq->engine)
continue;
@ -2966,6 +3007,7 @@ __execlists_update_reg_state(const struct intel_context *ce,
regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
regs[CTX_RING_HEAD] = head;
regs[CTX_RING_TAIL] = ring->tail;
regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID;
/* RPCS */
if (engine->class == RENDER_CLASS) {
@ -3636,9 +3678,6 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
if (!rq)
goto unwind;
/* We still have requests in-flight; the engine should be active */
GEM_BUG_ON(!intel_engine_pm_is_awake(engine));
ce = rq->context;
GEM_BUG_ON(!i915_vma_is_pinned(ce->state));
@ -3648,8 +3687,12 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
goto out_replay;
}
/* We still have requests in-flight; the engine should be active */
GEM_BUG_ON(!intel_engine_pm_is_awake(engine));
/* Context has requests still in-flight; it should not be idle! */
GEM_BUG_ON(i915_active_is_idle(&ce->active));
rq = active_request(ce->timeline, rq);
head = intel_ring_wrap(ce->ring, rq->head);
GEM_BUG_ON(head == ce->ring->tail);
@ -3723,7 +3766,10 @@ static void execlists_reset_rewind(struct intel_engine_cs *engine, bool stalled)
static void nop_submission_tasklet(unsigned long data)
{
struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
/* The driver is wedged; don't process any more events. */
WRITE_ONCE(engine->execlists.queue_priority_hint, INT_MIN);
}
static void execlists_reset_cancel(struct intel_engine_cs *engine)
@ -4119,26 +4165,6 @@ static int gen12_emit_flush_render(struct i915_request *request,
*cs++ = preparser_disable(false);
intel_ring_advance(request, cs);
/*
* Wa_1604544889:tgl
*/
if (IS_TGL_REVID(request->i915, TGL_REVID_A0, TGL_REVID_A0)) {
flags = 0;
flags |= PIPE_CONTROL_CS_STALL;
flags |= PIPE_CONTROL_HDC_PIPELINE_FLUSH;
flags |= PIPE_CONTROL_STORE_DATA_INDEX;
flags |= PIPE_CONTROL_QW_WRITE;
cs = intel_ring_begin(request, 6);
if (IS_ERR(cs))
return PTR_ERR(cs);
cs = gen8_emit_pipe_control(cs, flags,
LRC_PPHWSP_SCRATCH_ADDR);
intel_ring_advance(request, cs);
}
}
return 0;
@ -4877,7 +4903,7 @@ static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
mask = rq->execution_mask;
if (unlikely(!mask)) {
/* Invalid selection, submit to a random engine in error */
i915_request_skip(rq, -ENODEV);
i915_request_set_error_once(rq, -ENODEV);
mask = ve->siblings[0]->mask;
}
@ -4891,7 +4917,7 @@ static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
static void virtual_submission_tasklet(unsigned long data)
{
struct virtual_engine * const ve = (struct virtual_engine *)data;
const int prio = ve->base.execlists.queue_priority_hint;
const int prio = READ_ONCE(ve->base.execlists.queue_priority_hint);
intel_engine_mask_t mask;
unsigned int n;
@ -5287,11 +5313,15 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
show_request(m, last, "\t\tE ");
}
last = NULL;
count = 0;
if (execlists->switch_priority_hint != INT_MIN)
drm_printf(m, "\t\tSwitch priority hint: %d\n",
READ_ONCE(execlists->switch_priority_hint));
if (execlists->queue_priority_hint != INT_MIN)
drm_printf(m, "\t\tQueue priority hint: %d\n",
execlists->queue_priority_hint);
READ_ONCE(execlists->queue_priority_hint));
last = NULL;
count = 0;
for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
int i;

View File

@ -7,6 +7,7 @@
#include <linux/pm_runtime.h>
#include "i915_drv.h"
#include "i915_vgpu.h"
#include "intel_gt.h"
#include "intel_gt_pm.h"
#include "intel_rc6.h"
@ -319,10 +320,10 @@ static int vlv_rc6_init(struct intel_rc6 *rc6)
return PTR_ERR(pctx);
}
GEM_BUG_ON(range_overflows_t(u64,
i915->dsm.start,
pctx->stolen->start,
U32_MAX));
GEM_BUG_ON(range_overflows_end_t(u64,
i915->dsm.start,
pctx->stolen->start,
U32_MAX));
pctx_paddr = i915->dsm.start + pctx->stolen->start;
intel_uncore_write(uncore, VLV_PCBR, pctx_paddr);

View File

@ -48,8 +48,10 @@ static void engine_skip_context(struct i915_request *rq)
lockdep_assert_held(&engine->active.lock);
list_for_each_entry_continue(rq, &engine->active.requests, sched.link)
if (rq->context == hung_ctx)
i915_request_skip(rq, -EIO);
if (rq->context == hung_ctx) {
i915_request_set_error_once(rq, -EIO);
__i915_request_skip(rq);
}
}
static void client_mark_guilty(struct i915_gem_context *ctx, bool banned)
@ -92,13 +94,7 @@ static bool mark_guilty(struct i915_request *rq)
ctx = NULL;
rcu_read_unlock();
if (!ctx)
return false;
if (i915_gem_context_is_closed(ctx)) {
intel_context_set_banned(rq->context);
banned = true;
goto out;
}
return intel_context_is_banned(rq->context);
atomic_inc(&ctx->guilty_count);
@ -154,11 +150,12 @@ void __i915_request_reset(struct i915_request *rq, bool guilty)
rcu_read_lock(); /* protect the GEM context */
if (guilty) {
i915_request_skip(rq, -EIO);
i915_request_set_error_once(rq, -EIO);
__i915_request_skip(rq);
if (mark_guilty(rq))
engine_skip_context(rq);
} else {
dma_fence_set_error(&rq->fence, -EAGAIN);
i915_request_set_error_once(rq, -EAGAIN);
mark_innocent(rq);
}
rcu_read_unlock();
@ -785,7 +782,7 @@ static void nop_submit_request(struct i915_request *request)
unsigned long flags;
RQ_TRACE(request, "-EIO\n");
dma_fence_set_error(&request->fence, -EIO);
i915_request_set_error_once(request, -EIO);
spin_lock_irqsave(&engine->active.lock, flags);
__i915_request_submit(request);

View File

@ -29,11 +29,10 @@
#include <linux/log2.h>
#include <drm/i915_drm.h>
#include "gem/i915_gem_context.h"
#include "gen6_ppgtt.h"
#include "gen7_renderclear.h"
#include "i915_drv.h"
#include "i915_trace.h"
#include "intel_context.h"
@ -897,9 +896,7 @@ static void reset_cancel(struct intel_engine_cs *engine)
/* Mark all submitted requests as skipped. */
list_for_each_entry(request, &engine->active.requests, sched.link) {
if (!i915_request_signaled(request))
dma_fence_set_error(&request->fence, -EIO);
i915_request_set_error_once(request, -EIO);
i915_request_mark_complete(request);
}
@ -1360,7 +1357,9 @@ static int load_pd_dir(struct i915_request *rq,
return rq->engine->emit_flush(rq, EMIT_FLUSH);
}
static inline int mi_set_context(struct i915_request *rq, u32 flags)
static inline int mi_set_context(struct i915_request *rq,
struct intel_context *ce,
u32 flags)
{
struct drm_i915_private *i915 = rq->i915;
struct intel_engine_cs *engine = rq->engine;
@ -1435,7 +1434,7 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
*cs++ = MI_NOOP;
*cs++ = MI_SET_CONTEXT;
*cs++ = i915_ggtt_offset(rq->context->state) | flags;
*cs++ = i915_ggtt_offset(ce->state) | flags;
/*
* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
* WaMiSetContext_Hang:snb,ivb,vlv
@ -1550,13 +1549,56 @@ static int switch_mm(struct i915_request *rq, struct i915_address_space *vm)
return rq->engine->emit_flush(rq, EMIT_INVALIDATE);
}
static int clear_residuals(struct i915_request *rq)
{
struct intel_engine_cs *engine = rq->engine;
int ret;
ret = switch_mm(rq, vm_alias(engine->kernel_context->vm));
if (ret)
return ret;
if (engine->kernel_context->state) {
ret = mi_set_context(rq,
engine->kernel_context,
MI_MM_SPACE_GTT | MI_RESTORE_INHIBIT);
if (ret)
return ret;
}
ret = engine->emit_bb_start(rq,
engine->wa_ctx.vma->node.start, 0,
0);
if (ret)
return ret;
ret = engine->emit_flush(rq, EMIT_FLUSH);
if (ret)
return ret;
/* Always invalidate before the next switch_mm() */
return engine->emit_flush(rq, EMIT_INVALIDATE);
}
static int switch_context(struct i915_request *rq)
{
struct intel_engine_cs *engine = rq->engine;
struct intel_context *ce = rq->context;
void **residuals = NULL;
int ret;
GEM_BUG_ON(HAS_EXECLISTS(rq->i915));
if (engine->wa_ctx.vma && ce != engine->kernel_context) {
if (engine->wa_ctx.vma->private != ce) {
ret = clear_residuals(rq);
if (ret)
return ret;
residuals = &engine->wa_ctx.vma->private;
}
}
ret = switch_mm(rq, vm_alias(ce->vm));
if (ret)
return ret;
@ -1564,7 +1606,7 @@ static int switch_context(struct i915_request *rq)
if (ce->state) {
u32 flags;
GEM_BUG_ON(rq->engine->id != RCS0);
GEM_BUG_ON(engine->id != RCS0);
/* For resource streamer on HSW+ and power context elsewhere */
BUILD_BUG_ON(HSW_MI_RS_SAVE_STATE_EN != MI_SAVE_EXT_STATE_EN);
@ -1576,7 +1618,7 @@ static int switch_context(struct i915_request *rq)
else
flags |= MI_RESTORE_INHIBIT;
ret = mi_set_context(rq, flags);
ret = mi_set_context(rq, ce, flags);
if (ret)
return ret;
}
@ -1585,6 +1627,20 @@ static int switch_context(struct i915_request *rq)
if (ret)
return ret;
/*
* Now past the point of no return, this request _will_ be emitted.
*
* Or at least this preamble will be emitted, the request may be
* interrupted prior to submitting the user payload. If so, we
* still submit the "empty" request in order to preserve global
* state tracking such as this, our tracking of the current
* dirty context.
*/
if (residuals) {
intel_context_put(*residuals);
*residuals = intel_context_get(ce);
}
return 0;
}
@ -1769,6 +1825,11 @@ static void ring_release(struct intel_engine_cs *engine)
intel_engine_cleanup_common(engine);
if (engine->wa_ctx.vma) {
intel_context_put(engine->wa_ctx.vma->private);
i915_vma_unpin_and_release(&engine->wa_ctx.vma, 0);
}
intel_ring_unpin(engine->legacy.ring);
intel_ring_put(engine->legacy.ring);
@ -1916,6 +1977,64 @@ static void setup_vecs(struct intel_engine_cs *engine)
engine->emit_fini_breadcrumb = gen7_xcs_emit_breadcrumb;
}
static int gen7_ctx_switch_bb_setup(struct intel_engine_cs * const engine,
struct i915_vma * const vma)
{
return gen7_setup_clear_gpr_bb(engine, vma);
}
static int gen7_ctx_switch_bb_init(struct intel_engine_cs *engine)
{
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
int size;
int err;
size = gen7_ctx_switch_bb_setup(engine, NULL /* probe size */);
if (size <= 0)
return size;
size = ALIGN(size, PAGE_SIZE);
obj = i915_gem_object_create_internal(engine->i915, size);
if (IS_ERR(obj))
return PTR_ERR(obj);
vma = i915_vma_instance(obj, engine->gt->vm, NULL);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
goto err_obj;
}
vma->private = intel_context_create(engine); /* dummy residuals */
if (IS_ERR(vma->private)) {
err = PTR_ERR(vma->private);
goto err_obj;
}
err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH);
if (err)
goto err_private;
err = i915_vma_sync(vma);
if (err)
goto err_unpin;
err = gen7_ctx_switch_bb_setup(engine, vma);
if (err)
goto err_unpin;
engine->wa_ctx.vma = vma;
return 0;
err_unpin:
i915_vma_unpin(vma);
err_private:
intel_context_put(vma->private);
err_obj:
i915_gem_object_put(obj);
return err;
}
int intel_ring_submission_setup(struct intel_engine_cs *engine)
{
struct intel_timeline *timeline;
@ -1969,11 +2088,19 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine)
GEM_BUG_ON(timeline->hwsp_ggtt != engine->status_page.vma);
if (IS_GEN(engine->i915, 7) && engine->class == RENDER_CLASS) {
err = gen7_ctx_switch_bb_init(engine);
if (err)
goto err_ring_unpin;
}
/* Finally, take ownership and responsibility for cleanup! */
engine->release = ring_release;
return 0;
err_ring_unpin:
intel_ring_unpin(ring);
err_ring:
intel_ring_put(ring);
err_timeline_unpin:
@ -1984,3 +2111,7 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine)
intel_engine_cleanup_common(engine);
return err;
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftest_ring_submission.c"
#endif

View File

@ -4,6 +4,8 @@
* Copyright © 2019 Intel Corporation
*/
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "intel_gt.h"
#include "intel_gt_irq.h"
@ -55,7 +57,7 @@ static u32 rps_pm_mask(struct intel_rps *rps, u8 val)
if (val < rps->max_freq_softlimit)
mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
mask &= rps->pm_events;
mask &= READ_ONCE(rps->pm_events);
return rps_pm_sanitize_mask(rps, ~mask);
}
@ -68,17 +70,19 @@ static void rps_reset_ei(struct intel_rps *rps)
static void rps_enable_interrupts(struct intel_rps *rps)
{
struct intel_gt *gt = rps_to_gt(rps);
u32 events;
rps_reset_ei(rps);
if (IS_VALLEYVIEW(gt->i915))
/* WaGsvRC0ResidencyMethod:vlv */
rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED;
events = GEN6_PM_RP_UP_EI_EXPIRED;
else
rps->pm_events = (GEN6_PM_RP_UP_THRESHOLD |
GEN6_PM_RP_DOWN_THRESHOLD |
GEN6_PM_RP_DOWN_TIMEOUT);
events = (GEN6_PM_RP_UP_THRESHOLD |
GEN6_PM_RP_DOWN_THRESHOLD |
GEN6_PM_RP_DOWN_TIMEOUT);
WRITE_ONCE(rps->pm_events, events);
spin_lock_irq(&gt->irq_lock);
gen6_gt_pm_enable_irq(gt, rps->pm_events);
spin_unlock_irq(&gt->irq_lock);
@ -115,8 +119,7 @@ static void rps_disable_interrupts(struct intel_rps *rps)
{
struct intel_gt *gt = rps_to_gt(rps);
rps->pm_events = 0;
WRITE_ONCE(rps->pm_events, 0);
set(gt->uncore, GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u));
spin_lock_irq(&gt->irq_lock);
@ -642,7 +645,7 @@ void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive)
{
mutex_lock(&rps->power.mutex);
if (interactive) {
if (!rps->power.interactive++ && rps->active)
if (!rps->power.interactive++ && READ_ONCE(rps->active))
rps_set_power(rps, HIGH_POWER);
} else {
GEM_BUG_ON(!rps->power.interactive);
@ -719,11 +722,15 @@ void intel_rps_unpark(struct intel_rps *rps)
* performance, jump directly to RPe as our starting frequency.
*/
mutex_lock(&rps->lock);
rps->active = true;
WRITE_ONCE(rps->active, true);
freq = max(rps->cur_freq, rps->efficient_freq),
freq = clamp(freq, rps->min_freq_softlimit, rps->max_freq_softlimit);
intel_rps_set(rps, freq);
rps->last_adj = 0;
mutex_unlock(&rps->lock);
if (INTEL_GEN(rps_to_i915(rps)) >= 6)
@ -743,7 +750,7 @@ void intel_rps_park(struct intel_rps *rps)
if (INTEL_GEN(i915) >= 6)
rps_disable_interrupts(rps);
rps->active = false;
WRITE_ONCE(rps->active, false);
if (rps->last_freq <= rps->idle_freq)
return;
@ -767,10 +774,10 @@ void intel_rps_park(struct intel_rps *rps)
void intel_rps_boost(struct i915_request *rq)
{
struct intel_rps *rps = &rq->engine->gt->rps;
struct intel_rps *rps = &READ_ONCE(rq->engine)->gt->rps;
unsigned long flags;
if (i915_request_signaled(rq) || !rps->active)
if (i915_request_signaled(rq) || !READ_ONCE(rps->active))
return;
/* Serializes with i915_request_retire() */
@ -1453,12 +1460,12 @@ static void rps_work(struct work_struct *work)
u32 pm_iir = 0;
spin_lock_irq(&gt->irq_lock);
pm_iir = fetch_and_zero(&rps->pm_iir);
pm_iir = fetch_and_zero(&rps->pm_iir) & READ_ONCE(rps->pm_events);
client_boost = atomic_read(&rps->num_waiters);
spin_unlock_irq(&gt->irq_lock);
/* Make sure we didn't queue anything we're not going to process. */
if ((pm_iir & rps->pm_events) == 0 && !client_boost)
if (!pm_iir && !client_boost)
goto out;
mutex_lock(&rps->lock);
@ -1554,11 +1561,15 @@ void gen11_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
{
struct intel_gt *gt = rps_to_gt(rps);
u32 events;
if (pm_iir & rps->pm_events) {
events = pm_iir & READ_ONCE(rps->pm_events);
if (events) {
spin_lock(&gt->irq_lock);
gen6_gt_pm_mask_irq(gt, pm_iir & rps->pm_events);
rps->pm_iir |= pm_iir & rps->pm_events;
gen6_gt_pm_mask_irq(gt, events);
rps->pm_iir |= events;
schedule_work(&rps->work);
spin_unlock(&gt->irq_lock);
}

View File

@ -192,11 +192,15 @@ static void cacheline_release(struct intel_timeline_cacheline *cl)
static void cacheline_free(struct intel_timeline_cacheline *cl)
{
if (!i915_active_acquire_if_busy(&cl->active)) {
__idle_cacheline_free(cl);
return;
}
GEM_BUG_ON(ptr_test_bit(cl->vaddr, CACHELINE_FREE));
cl->vaddr = ptr_set_bit(cl->vaddr, CACHELINE_FREE);
if (i915_active_is_idle(&cl->active))
__idle_cacheline_free(cl);
i915_active_release(&cl->active);
}
int intel_timeline_init(struct intel_timeline *timeline,

View File

@ -575,12 +575,29 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
/* allow headerless messages for preemptible GPGPU context */
WA_SET_BIT_MASKED(GEN10_SAMPLER_MODE,
GEN11_SAMPLER_ENABLE_HEADLESS_MSG);
/* Wa_1604278689:icl,ehl */
wa_write(wal, IVB_FBC_RT_BASE, 0xFFFFFFFF & ~ILK_FBC_RT_VALID);
wa_write_masked_or(wal, IVB_FBC_RT_BASE_UPPER,
0, /* write-only register; skip validation */
0xFFFFFFFF);
/* Wa_1406306137:icl,ehl */
wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU);
}
static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal)
{
/* Wa_1409142259:tgl */
/*
* Wa_1409142259:tgl
* Wa_1409347922:tgl
* Wa_1409252684:tgl
* Wa_1409217633:tgl
* Wa_1409207793:tgl
* Wa_1409178076:tgl
* Wa_1408979724:tgl
*/
WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3,
GEN12_DISABLE_CPS_AWARE_COLOR_PIPE);
@ -593,6 +610,11 @@ static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine,
*/
wa_add(wal, FF_MODE2, FF_MODE2_TDS_TIMER_MASK,
FF_MODE2_TDS_TIMER_128, 0);
/* WaDisableGPGPUMidThreadPreemption:tgl */
WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1,
GEN9_PREEMPT_GPGPU_LEVEL_MASK,
GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL);
}
static void
@ -898,11 +920,6 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
SLICE_UNIT_LEVEL_CLKGATE,
MSCUNIT_CLKGATE_DIS);
/* Wa_1406680159:icl */
wa_write_or(wal,
SUBSLICE_UNIT_LEVEL_CLKGATE,
GWUNIT_CLKGATE_DIS);
/* Wa_1406838659:icl (pre-prod) */
if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
wa_write_or(wal,
@ -931,7 +948,7 @@ tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
SUBSLICE_UNIT_LEVEL_CLKGATE2,
CPSSUNIT_CLKGATE_DIS);
/* Wa_1409180338:tgl */
/* Wa_1607087056:tgl also know as BUG:1409180338 */
if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0))
wa_write_or(wal,
SLICE_UNIT_LEVEL_CLKGATE,
@ -1246,6 +1263,7 @@ static void tgl_whitelist_build(struct intel_engine_cs *engine)
case RENDER_CLASS:
/*
* WaAllowPMDepthAndInvocationCountAccessFromUMD:tgl
* Wa_1408556865:tgl
*
* This covers 4 registers which are next to one another :
* - PS_INVOCATION_COUNT
@ -1259,6 +1277,9 @@ static void tgl_whitelist_build(struct intel_engine_cs *engine)
/* Wa_1808121037:tgl */
whitelist_reg(w, GEN7_COMMON_SLICE_CHICKEN1);
/* Wa_1806527549:tgl */
whitelist_reg(w, HIZ_CHICKEN);
break;
default:
break;
@ -1325,19 +1346,21 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
struct drm_i915_private *i915 = engine->i915;
if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) {
/* Wa_1606700617:tgl */
wa_masked_en(wal,
GEN9_CS_DEBUG_MODE1,
FF_DOP_CLOCK_GATE_DISABLE);
/* Wa_1607138336:tgl */
/*
* Wa_1607138336:tgl
* Wa_1607063988:tgl
*/
wa_write_or(wal,
GEN9_CTX_PREEMPT_REG,
GEN12_DISABLE_POSH_BUSY_FF_DOP_CG);
/* Wa_1607030317:tgl */
/* Wa_1607186500:tgl */
/* Wa_1607297627:tgl */
/*
* Wa_1607030317:tgl
* Wa_1607186500:tgl
* Wa_1607297627:tgl there is 3 entries for this WA on BSpec, 2
* of then says it is fixed on B0 the other one says it is
* permanent
*/
wa_masked_en(wal,
GEN6_RC_SLEEP_PSMI_CONTROL,
GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE |
@ -1356,10 +1379,29 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN7_FF_THREAD_MODE,
GEN12_FF_TESSELATION_DOP_GATE_DISABLE);
/*
* Wa_1409085225:tgl
* Wa_14010229206:tgl
*/
wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN12_DISABLE_TDL_PUSH);
/* Wa_1408615072:tgl */
wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2,
VSUNIT_CLKGATE_DIS_TGL);
}
if (IS_TIGERLAKE(i915)) {
/* Wa_1606931601:tgl */
wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_DISABLE_EARLY_READ);
/* Wa_1409804808:tgl */
wa_masked_en(wal, GEN7_ROW_CHICKEN2,
GEN12_PUSH_CONST_DEREF_HOLD_DIS);
/* Wa_1606700617:tgl */
wa_masked_en(wal,
GEN7_ROW_CHICKEN2,
GEN12_DISABLE_EARLY_READ);
GEN9_CS_DEBUG_MODE1,
FF_DOP_CLOCK_GATE_DISABLE);
}
if (IS_GEN(i915, 11)) {
@ -1425,10 +1467,38 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN11_SCRATCH2,
GEN11_COHERENT_PARTIAL_WRITE_MERGE_ENABLE,
0);
/* WaEnable32PlaneMode:icl */
wa_masked_en(wal, GEN9_CSFE_CHICKEN1_RCS,
GEN11_ENABLE_32_PLANE_MODE);
/*
* Wa_1408615072:icl,ehl (vsunit)
* Wa_1407596294:icl,ehl (hsunit)
*/
wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE,
VSUNIT_CLKGATE_DIS | HSUNIT_CLKGATE_DIS);
/* Wa_1407352427:icl,ehl */
wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2,
PSDUNIT_CLKGATE_DIS);
/* Wa_1406680159:icl,ehl */
wa_write_or(wal,
SUBSLICE_UNIT_LEVEL_CLKGATE,
GWUNIT_CLKGATE_DIS);
/*
* Wa_1408767742:icl[a2..forever],ehl[all]
* Wa_1605460711:icl[a0..c0]
*/
wa_write_or(wal,
GEN7_FF_THREAD_MODE,
GEN12_FF_TESSELATION_DOP_GATE_DISABLE);
}
if (IS_GEN_RANGE(i915, 9, 11)) {
/* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl */
if (IS_GEN_RANGE(i915, 9, 12)) {
/* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl,tgl */
wa_masked_en(wal,
GEN7_FF_SLICE_CS_CHICKEN1,
GEN9_FFSC_PERCTX_PREEMPT_CTRL);
@ -1595,15 +1665,34 @@ create_scratch(struct i915_address_space *vm, int count)
return ERR_PTR(err);
}
static const struct {
u32 start;
u32 end;
} mcr_ranges_gen8[] = {
{ .start = 0x5500, .end = 0x55ff },
{ .start = 0x7000, .end = 0x7fff },
{ .start = 0x9400, .end = 0x97ff },
{ .start = 0xb000, .end = 0xb3ff },
{ .start = 0xe000, .end = 0xe7ff },
{},
};
static bool mcr_range(struct drm_i915_private *i915, u32 offset)
{
int i;
if (INTEL_GEN(i915) < 8)
return false;
/*
* Registers in this range are affected by the MCR selector
* Registers in these ranges are affected by the MCR selector
* which only controls CPU initiated MMIO. Routing does not
* work for CS access so we cannot verify them on this path.
*/
if (INTEL_GEN(i915) >= 8 && (offset >= 0xb000 && offset <= 0xb4ff))
return true;
for (i = 0; mcr_ranges_gen8[i].start; i++)
if (offset >= mcr_ranges_gen8[i].start &&
offset <= mcr_ranges_gen8[i].end)
return true;
return false;
}

View File

@ -0,0 +1,61 @@
// SPDX-License-Identifier: MIT
/*
* Copyright © 2020 Intel Corporation
*
* Generated by: IGT Gpu Tools on Fri 21 Feb 2020 05:29:32 AM UTC
*/
static const u32 ivb_clear_kernel[] = {
0x00000001, 0x26020128, 0x00000024, 0x00000000,
0x00000040, 0x20280c21, 0x00000028, 0x00000001,
0x01000010, 0x20000c20, 0x0000002c, 0x00000000,
0x00010220, 0x34001c00, 0x00001400, 0x0000002c,
0x00600001, 0x20600061, 0x00000000, 0x00000000,
0x00000008, 0x20601c85, 0x00000e00, 0x0000000c,
0x00000005, 0x20601ca5, 0x00000060, 0x00000001,
0x00000008, 0x20641c85, 0x00000e00, 0x0000000d,
0x00000005, 0x20641ca5, 0x00000064, 0x00000003,
0x00000041, 0x207424a5, 0x00000064, 0x00000034,
0x00000040, 0x206014a5, 0x00000060, 0x00000074,
0x00000008, 0x20681c85, 0x00000e00, 0x00000008,
0x00000005, 0x20681ca5, 0x00000068, 0x0000000f,
0x00000041, 0x20701ca5, 0x00000060, 0x00000010,
0x00000040, 0x206814a5, 0x00000068, 0x00000070,
0x00600001, 0x20a00061, 0x00000000, 0x00000000,
0x00000005, 0x206c1c85, 0x00000e00, 0x00000007,
0x00000041, 0x206c1ca5, 0x0000006c, 0x00000004,
0x00600001, 0x20800021, 0x008d0000, 0x00000000,
0x00000001, 0x20800021, 0x0000006c, 0x00000000,
0x00000001, 0x20840021, 0x00000068, 0x00000000,
0x00000001, 0x20880061, 0x00000000, 0x00000003,
0x00000005, 0x208c0d21, 0x00000086, 0xffffffff,
0x05600032, 0x20a00fa1, 0x008d0080, 0x02190001,
0x00000040, 0x20a01ca5, 0x000000a0, 0x00000001,
0x05600032, 0x20a00fa1, 0x008d0080, 0x040a8001,
0x02000040, 0x20281c21, 0x00000028, 0xffffffff,
0x00010220, 0x34001c00, 0x00001400, 0xfffffffc,
0x00000001, 0x26020128, 0x00000024, 0x00000000,
0x00000001, 0x220010e4, 0x00000000, 0x00000000,
0x00000001, 0x220831ec, 0x00000000, 0x007f007f,
0x00600001, 0x20400021, 0x008d0000, 0x00000000,
0x00600001, 0x2fe00021, 0x008d0000, 0x00000000,
0x00200001, 0x20400121, 0x00450020, 0x00000000,
0x00000001, 0x20480061, 0x00000000, 0x000f000f,
0x00000005, 0x204c0d21, 0x00000046, 0xffffffef,
0x00800001, 0x20600061, 0x00000000, 0x00000000,
0x00800001, 0x20800061, 0x00000000, 0x00000000,
0x00800001, 0x20a00061, 0x00000000, 0x00000000,
0x00800001, 0x20c00061, 0x00000000, 0x00000000,
0x00800001, 0x20e00061, 0x00000000, 0x00000000,
0x00800001, 0x21000061, 0x00000000, 0x00000000,
0x00800001, 0x21200061, 0x00000000, 0x00000000,
0x00800001, 0x21400061, 0x00000000, 0x00000000,
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
0x00000040, 0x20402d21, 0x00000020, 0x00100010,
0x05600032, 0x20000fa0, 0x008d0040, 0x120a8000,
0x02000040, 0x22083d8c, 0x00000208, 0xffffffff,
0x00800001, 0xa0000109, 0x00000602, 0x00000000,
0x00000040, 0x22001c84, 0x00000200, 0x00000020,
0x00010220, 0x34001c00, 0x00001400, 0xfffffff8,
0x07600032, 0x20000fa0, 0x008d0fe0, 0x82000010,
};

View File

@ -244,9 +244,7 @@ static void mock_reset_cancel(struct intel_engine_cs *engine)
/* Mark all submitted requests as skipped. */
list_for_each_entry(request, &engine->active.requests, sched.link) {
if (!i915_request_signaled(request))
dma_fence_set_error(&request->fence, -EIO);
i915_request_set_error_once(request, -EIO);
i915_request_mark_complete(request);
}

View File

@ -142,6 +142,24 @@ static int __live_idle_pulse(struct intel_engine_cs *engine,
return err;
}
static void engine_heartbeat_disable(struct intel_engine_cs *engine,
unsigned long *saved)
{
*saved = engine->props.heartbeat_interval_ms;
engine->props.heartbeat_interval_ms = 0;
intel_engine_pm_get(engine);
intel_engine_park_heartbeat(engine);
}
static void engine_heartbeat_enable(struct intel_engine_cs *engine,
unsigned long saved)
{
intel_engine_pm_put(engine);
engine->props.heartbeat_interval_ms = saved;
}
static int live_idle_flush(void *arg)
{
struct intel_gt *gt = arg;
@ -152,9 +170,11 @@ static int live_idle_flush(void *arg)
/* Check that we can flush the idle barriers */
for_each_engine(engine, gt, id) {
intel_engine_pm_get(engine);
unsigned long heartbeat;
engine_heartbeat_disable(engine, &heartbeat);
err = __live_idle_pulse(engine, intel_engine_flush_barriers);
intel_engine_pm_put(engine);
engine_heartbeat_enable(engine, heartbeat);
if (err)
break;
}
@ -172,9 +192,11 @@ static int live_idle_pulse(void *arg)
/* Check that heartbeat pulses flush the idle barriers */
for_each_engine(engine, gt, id) {
intel_engine_pm_get(engine);
unsigned long heartbeat;
engine_heartbeat_disable(engine, &heartbeat);
err = __live_idle_pulse(engine, intel_engine_pulse);
intel_engine_pm_put(engine);
engine_heartbeat_enable(engine, heartbeat);
if (err && err != -ENODEV)
break;

View File

@ -268,7 +268,7 @@ hang_create_request(struct hang *h, struct intel_engine_cs *engine)
cancel_rq:
if (err) {
i915_request_skip(rq, err);
i915_request_set_error_once(rq, err);
i915_request_add(rq);
}
unpin_hws:

Some files were not shown because too many files have changed in this diff Show More