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 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 :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: :internal:
Video BIOS Table (VBT) Video BIOS Table (VBT)
@ -332,7 +332,7 @@ This process is dubbed relocation.
GEM BO Management Implementation Details 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 :doc: Virtual Memory Address
Buffer Object Eviction Buffer Object Eviction
@ -382,7 +382,7 @@ Logical Rings, Logical Ring Contexts and Execlists
Global GTT views 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 :doc: Global GTT views
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_gtt.c .. 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_ANY
#undef DEVICE_ID #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 * drm_dp_read_desc - read sink/branch descriptor from DPCD
* @aux: DisplayPort AUX channel * @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)) if (drm_dp_read_desc(port->mgr->aux, &desc, true))
return NULL; 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->mgr->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14 &&
port->parent == port->mgr->mst_primary) { port->parent == port->mgr->mst_primary) {
u8 downstreamport; 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 check the health of the GPU and undertake regular house-keeping of
internal driver state. 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 May be 0 to disable heartbeats and therefore disable automatic GPU
hang detection. hang detection.
@ -33,11 +36,18 @@ config DRM_I915_PREEMPT_TIMEOUT
expires, the HW will be reset to allow the more important context expires, the HW will be reset to allow the more important context
to execute. to execute.
This is adjustable via
/sys/class/drm/card?/engine/*/preempt_timeout_ms
May be 0 to disable the timeout. May be 0 to disable the timeout.
config DRM_I915_SPIN_REQUEST The compiled in default may get overridden at driver probe time on
int "Busywait for request completion (us)" certain platforms and certain engines which will be reflected in the
default 5 # microseconds sysfs control.
config DRM_I915_MAX_REQUEST_BUSYWAIT
int "Busywait for request completion limit (ns)"
default 8000 # nanoseconds
help help
Before sleeping waiting for a request (GPU operation) to complete, Before sleeping waiting for a request (GPU operation) to complete,
we may spend some time polling for its completion. As the IRQ may 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 check if the request will complete in the time it would have taken
us to enable the interrupt. 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 May be 0 to disable the initial spin. In practice, we estimate
the cost of enabling the interrupt (if currently disabled) to be the cost of enabling the interrupt (if currently disabled) to be
a few microseconds. 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 that the reset itself may take longer and so be more disruptive to
interactive or low latency workloads. interactive or low latency workloads.
This is adjustable via
/sys/class/drm/card?/engine/*/stop_timeout_ms
config DRM_I915_TIMESLICE_DURATION config DRM_I915_TIMESLICE_DURATION
int "Scheduling quantum for userspace batches (ms, jiffy granularity)" int "Scheduling quantum for userspace batches (ms, jiffy granularity)"
default 1 # milliseconds default 1 # milliseconds
@ -73,4 +89,7 @@ config DRM_I915_TIMESLICE_DURATION
is scheduled for execution for the timeslice duration, before is scheduled for execution for the timeslice duration, before
switching to the next context. switching to the next context.
This is adjustable via
/sys/class/drm/card?/engine/*/timeslice_duration_ms
May be 0 to disable timeslicing. May be 0 to disable timeslicing.

View File

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

View File

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

View File

@ -133,15 +133,37 @@ intel_plane_destroy_state(struct drm_plane *plane,
kfree(plane_state); 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, unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state) const struct intel_plane_state *plane_state)
{ {
const struct drm_framebuffer *fb = plane_state->hw.fb; const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int cpp; unsigned int cpp;
unsigned int pixel_rate;
if (!plane_state->uapi.visible) if (!plane_state->uapi.visible)
return 0; return 0;
pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
cpp = fb->format->cpp[0]; 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) if (fb->format->is_yuv && fb->format->num_planes > 1)
cpp *= 4; cpp *= 4;
return cpp * crtc_state->pixel_rate; return pixel_rate * cpp;
} }
int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, 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; 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, unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state); const struct intel_plane_state *plane_state);
void intel_plane_copy_uapi_to_hw_state(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 }, { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 },
{ 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, { 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 },
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, { 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 */ /* 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 */ /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) 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 = const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode; &crtc_state->hw.adjusted_mode;
int i; int i;
@ -243,6 +248,9 @@ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_sta
break; 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)) { if (i == ARRAY_SIZE(hdmi_audio_clock)) {
DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n",
adjusted_mode->crtc_clock); adjusted_mode->crtc_clock);
@ -844,7 +852,7 @@ static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv,
struct intel_crtc *crtc; struct intel_crtc *crtc;
int ret; int ret;
crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A); crtc = intel_get_first_crtc(dev_priv);
if (!crtc) if (!crtc)
return; return;

View File

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

View File

@ -32,8 +32,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <drm/i915_drm.h>
struct drm_i915_private; struct drm_i915_private;
struct intel_crtc_state; struct intel_crtc_state;
struct intel_encoder; 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, const struct intel_cdclk_config *cdclk_config,
enum pipe pipe) enum pipe pipe)
{ {
struct intel_encoder *encoder;
if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config)) if (!intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config))
return; 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"); 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); 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, if (drm_WARN(&dev_priv->drm,
intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config), intel_cdclk_changed(&dev_priv->cdclk.hw, cdclk_config),
"cdclk state doesn't match!\n")) { "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); crtc_state->csc_mode);
} }
/* static void chv_load_cgm_csc(struct intel_crtc *crtc,
* Set up the pipe CSC unit on CherryView. const struct drm_property_blob *blob)
*/
static void cherryview_load_csc_matrix(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); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
const struct drm_color_ctm *ctm = blob->data;
enum pipe pipe = crtc->pipe; enum pipe pipe = crtc->pipe;
u16 coeffs[9];
int i;
if (crtc_state->hw.ctm) { for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data; u64 abs_coeff = ((1ULL << 63) - 1) & ctm->matrix[i];
u16 coeffs[9] = {};
int i;
for (i = 0; i < ARRAY_SIZE(coeffs); i++) { /* Round coefficient. */
u64 abs_coeff = abs_coeff += 1 << (32 - 13);
((1ULL << 63) - 1) & ctm->matrix[i]; /* Clamp to hardware limits. */
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
/* Round coefficient. */ coeffs[i] = 0;
abs_coeff += 1 << (32 - 13);
/* Clamp to hardware limits. */
abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
/* Write coefficients in S3.12 format. */ /* Write coefficients in S3.12 format. */
if (ctm->matrix[i] & (1ULL << 63)) if (ctm->matrix[i] & (1ULL << 63))
coeffs[i] = 1 << 15; coeffs[i] |= 1 << 15;
coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
coeffs[i] |= (abs_coeff >> 20) & 0xfff;
}
intel_de_write(dev_priv, CGM_PIPE_CSC_COEFF01(pipe), coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
coeffs[1] << 16 | coeffs[0]); coeffs[i] |= (abs_coeff >> 20) & 0xfff;
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]);
} }
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) 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); 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) */ /* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */
static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color) 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); (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) static u32 ilk_lut_10(const struct drm_color_lut *color)
{ {
return drm_color_lut_extract(color->red, 10) << 20 | 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); drm_color_lut_extract(color->blue, 10);
} }
/* Loads the legacy palette/gamma unit for the CRTC. */ static void ilk_lut_10_pack(struct drm_color_lut *entry, u32 val)
static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob)
{ {
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); entry->red = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_RED_MASK, val), 10);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); entry->green = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_GREEN_MASK, val), 10);
enum pipe pipe = crtc->pipe; entry->blue = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_BLUE_MASK, val), 10);
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);
} }
static void i9xx_color_commit(const struct intel_crtc_state *crtc_state) 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); 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, static void i965_load_lut_10p6(struct intel_crtc *crtc,
const struct drm_property_blob *blob) 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) static void i965_load_luts(const struct intel_crtc_state *crtc_state)
{ {
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 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; 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) if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
i9xx_load_luts(crtc_state); i9xx_load_lut_8(crtc, gamma_lut);
else else
i965_load_lut_10p6(crtc, gamma_lut); 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, static void ilk_load_lut_10(struct intel_crtc *crtc,
const struct drm_property_blob *blob) 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++) for (i = 0; i < lut_size; i++)
intel_de_write(dev_priv, PREC_PALETTE(pipe, 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) 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; const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
i9xx_load_luts(crtc_state); ilk_load_lut_8(crtc, gamma_lut);
else else
ilk_load_lut_10(crtc, gamma_lut); 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; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) { 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) { } else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE | ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(0)); 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; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) { 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) { } else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE | bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(0)); 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 intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe; 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; const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data;
u32 i;
/* /*
* When setting the auto-increment bit, the hardware seems to * 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 intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe; 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;
u32 i;
/* /*
* When setting the auto-increment bit, the hardware seems to * 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); glk_load_degamma_lut_linear(crtc_state);
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) { if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) {
i9xx_load_luts(crtc_state); ilk_load_lut_8(crtc, gamma_lut);
} else { } else {
bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0)); bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
ivb_load_lut_ext_max(crtc); 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; const struct drm_color_lut *lut = blob->data;
struct intel_dsb *dsb = intel_dsb_get(crtc); struct intel_dsb *dsb = intel_dsb_get(crtc);
enum pipe pipe = crtc->pipe; enum pipe pipe = crtc->pipe;
u32 i; int i;
/* /*
* Program Super Fine segment (let's call it seg1)... * 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; const struct drm_color_lut *entry;
struct intel_dsb *dsb = intel_dsb_get(crtc); struct intel_dsb *dsb = intel_dsb_get(crtc);
enum pipe pipe = crtc->pipe; enum pipe pipe = crtc->pipe;
u32 i; int i;
/* /*
* Program Fine segment (let's call it seg2)... * 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) { switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
case GAMMA_MODE_MODE_8BIT: case GAMMA_MODE_MODE_8BIT:
i9xx_load_luts(crtc_state); ilk_load_lut_8(crtc, gamma_lut);
break; break;
case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED: case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
icl_program_gamma_superfine_segment(crtc_state); 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); 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, static void chv_load_cgm_degamma(struct intel_crtc *crtc,
const struct drm_property_blob *blob) 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) static void chv_load_luts(const struct intel_crtc_state *crtc_state)
{ {
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 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 *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)) { if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
i9xx_load_luts(crtc_state);
return;
}
if (degamma_lut)
chv_load_cgm_degamma(crtc, degamma_lut); 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); 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) 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; return true;
} }
/* convert hw value with given bit_precision to lut property val */ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
static u32 intel_color_lut_pack(u32 val, u32 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 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); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe; enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob; struct drm_property_blob *blob;
struct drm_color_lut *blob_data; struct drm_color_lut *lut;
u32 i, val; int i;
blob = drm_property_create_blob(&dev_priv->drm, blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH, 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)) if (IS_ERR(blob))
return NULL; return NULL;
blob_data = blob->data; lut = blob->data;
for (i = 0; i < LEGACY_LUT_LENGTH; i++) { for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
if (HAS_GMCH(dev_priv)) u32 val = intel_de_read(dev_priv, PALETTE(pipe, i));
val = intel_de_read(dev_priv, PALETTE(pipe, i));
else
val = intel_de_read(dev_priv, LGC_PALETTE(pipe, i));
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET( i9xx_lut_8_pack(&lut[i], val);
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);
} }
return blob; 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) 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) if (!crtc_state->gamma_enable)
return; 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 * static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
i965_read_lut_10p6(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); 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; enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob; struct drm_property_blob *blob;
struct drm_color_lut *blob_data; struct drm_color_lut *lut;
u32 i, val1, val2;
blob = drm_property_create_blob(&dev_priv->drm, blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * lut_size, 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)) if (IS_ERR(blob))
return NULL; return NULL;
blob_data = blob->data; lut = blob->data;
for (i = 0; i < lut_size - 1; i++) { for (i = 0; i < lut_size - 1; i++) {
val1 = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0)); u32 ldw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 0));
val2 = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1)); u32 udw = intel_de_read(dev_priv, PALETTE(pipe, 2 * i + 1));
blob_data[i].red = REG_FIELD_GET(PALETTE_RED_MASK, val2) << 8 | i965_lut_10p6_pack(&lut[i], ldw, udw);
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);
} }
blob_data[i].red = REG_FIELD_GET(PIPEGCMAX_RGB_MASK, lut[i].red = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 0)));
intel_de_read(dev_priv, PIPEGCMAX(pipe, 0))); lut[i].green = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 1)));
blob_data[i].green = REG_FIELD_GET(PIPEGCMAX_RGB_MASK, lut[i].blue = i965_lut_11p6_max_pack(intel_de_read(dev_priv, PIPEGCMAX(pipe, 2)));
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)));
return blob; return blob;
} }
static void i965_read_luts(struct intel_crtc_state *crtc_state) 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) if (!crtc_state->gamma_enable)
return; return;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) 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 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 * static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
chv_read_cgm_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); 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; enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob; struct drm_property_blob *blob;
struct drm_color_lut *blob_data; struct drm_color_lut *lut;
u32 i, val;
blob = drm_property_create_blob(&dev_priv->drm, blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * lut_size, 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)) if (IS_ERR(blob))
return NULL; return NULL;
blob_data = blob->data; lut = blob->data;
for (i = 0; i < lut_size; i++) { for (i = 0; i < lut_size; i++) {
val = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0)); u32 ldw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0));
blob_data[i].green = intel_color_lut_pack(REG_FIELD_GET( u32 udw = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1));
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);
val = intel_de_read(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1)); chv_cgm_gamma_pack(&lut[i], ldw, udw);
blob_data[i].red = intel_color_lut_pack(REG_FIELD_GET(
CGM_PIPE_GAMMA_RED_MASK, val), 10);
} }
return blob; 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) 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) 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 else
i965_read_luts(crtc_state); i965_read_luts(crtc_state);
} }
static struct drm_property_blob * static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
ilk_read_lut_10(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); 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; enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob; struct drm_property_blob *blob;
struct drm_color_lut *blob_data; struct drm_color_lut *lut;
u32 i, val; 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, blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * lut_size, 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)) if (IS_ERR(blob))
return NULL; return NULL;
blob_data = blob->data; lut = blob->data;
for (i = 0; i < lut_size; i++) { 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( ilk_lut_10_pack(&lut[i], val);
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);
} }
return blob; 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) 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) if (!crtc_state->gamma_enable)
return; return;
@ -1852,21 +1897,19 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state)
return; return;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) 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 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 * static struct drm_property_blob *glk_read_lut_10(struct intel_crtc *crtc,
glk_read_lut_10(const struct intel_crtc_state *crtc_state, u32 prec_index) 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); 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; enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob; struct drm_property_blob *blob;
struct drm_color_lut *blob_data; struct drm_color_lut *lut;
u32 i, val;
blob = drm_property_create_blob(&dev_priv->drm, blob = drm_property_create_blob(&dev_priv->drm,
sizeof(struct drm_color_lut) * hw_lut_size, 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)) if (IS_ERR(blob))
return NULL; return NULL;
blob_data = blob->data; lut = blob->data;
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), intel_de_write(dev_priv, PREC_PAL_INDEX(pipe),
prec_index | PAL_PREC_AUTO_INCREMENT); prec_index | PAL_PREC_AUTO_INCREMENT);
for (i = 0; i < hw_lut_size; i++) { 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( ilk_lut_10_pack(&lut[i], val);
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);
} }
intel_de_write(dev_priv, PREC_PAL_INDEX(pipe), 0); 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) 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) if (!crtc_state->gamma_enable)
return; return;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT) 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 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) void intel_color_init(struct intel_crtc *crtc)

View File

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

View File

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

View File

@ -1325,164 +1325,6 @@ intel_ddi_get_crtc_encoder(struct intel_crtc *crtc)
return ret; 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, static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
enum port port) 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) static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
{ {
int dotclock; 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; 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, static void intel_ddi_clock_get(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config) struct intel_crtc_state *pipe_config)
{ {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 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) if (intel_phy_is_tc(dev_priv, phy) &&
icl_ddi_clock_get(encoder, pipe_config); intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll) ==
else if (IS_CANNONLAKE(dev_priv)) DPLL_ID_ICL_TBTPLL)
cnl_ddi_clock_get(encoder, pipe_config); pipe_config->port_clock = icl_calc_tbt_pll_link(dev_priv,
else if (IS_GEN9_LP(dev_priv)) encoder->port);
bxt_ddi_clock_get(encoder, pipe_config); else
else if (IS_GEN9_BC(dev_priv)) pipe_config->port_clock =
skl_ddi_clock_get(encoder, pipe_config); intel_dpll_get_freq(dev_priv, pipe_config->shared_dpll);
else if (INTEL_GEN(dev_priv) <= 8)
hsw_ddi_clock_get(encoder, pipe_config); ddi_dotclock_get(pipe_config);
} }
void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state, 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); enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
u32 val; u32 val;
mutex_lock(&dev_priv->dpll_lock); mutex_lock(&dev_priv->dpll.lock);
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0); val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
drm_WARN_ON(&dev_priv->drm, 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); val &= ~icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); 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) 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); enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
u32 val; u32 val;
mutex_lock(&dev_priv->dpll_lock); mutex_lock(&dev_priv->dpll.lock);
val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0); val = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0);
val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy); val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); 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, 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)) if (drm_WARN_ON(&dev_priv->drm, !pll))
return; return;
mutex_lock(&dev_priv->dpll_lock); mutex_lock(&dev_priv->dpll.lock);
if (INTEL_GEN(dev_priv) >= 11) { if (INTEL_GEN(dev_priv) >= 11) {
if (!intel_phy_is_combo(dev_priv, phy)) 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)); 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) 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, if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
crtc_state->hdmi_high_tmds_clock_ratio, crtc_state->hdmi_high_tmds_clock_ratio,
crtc_state->hdmi_scrambling)) crtc_state->hdmi_scrambling))
DRM_ERROR("[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n", DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Failed to configure sink "
connector->base.id, connector->name); "scrambling/TMDS bit clock ratio\n",
connector->base.id, connector->name);
/* Display WA #1143: skl,kbl,cfl */ /* Display WA #1143: skl,kbl,cfl */
if (IS_GEN9_BC(dev_priv)) { if (IS_GEN9_BC(dev_priv)) {

View File

@ -6,8 +6,6 @@
#ifndef __INTEL_DDI_H__ #ifndef __INTEL_DDI_H__
#define __INTEL_DDI_H__ #define __INTEL_DDI_H__
#include <drm/i915_drm.h>
#include "intel_display.h" #include "intel_display.h"
struct drm_connector_state; 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, int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
bool enable); bool enable);
void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder); 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__ */ #endif /* __INTEL_DDI_H__ */

View File

@ -41,7 +41,6 @@
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/i915_drm.h>
#include "display/intel_crt.h" #include "display/intel_crt.h"
#include "display/intel_ddi.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 * 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) if (!crtc)
return 0; 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 */ /* 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)); u32 temp = intel_de_read(dev_priv, PCH_DPLL(i));
if (!(temp & DPLL_VCO_ENABLE)) 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) BIT(PLANE_CURSOR))) == 0)
val |= PIPEMISC_HDR_MODE_PRECISION; 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); 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) if (new_crtc_state->hw.active)
I915_STATE_WARN(!(pll->active_mask & crtc_mask), I915_STATE_WARN(!(pll->active_mask & crtc_mask),
"pll active mismatch (expected pipe %c in active mask 0x%02x)\n", "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 else
I915_STATE_WARN(pll->active_mask & crtc_mask, I915_STATE_WARN(pll->active_mask & crtc_mask,
"pll active mismatch (didn't expect pipe %c in active mask 0x%02x)\n", "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), I915_STATE_WARN(!(pll->state.crtc_mask & crtc_mask),
"pll enabled crtcs mismatch (expected 0x%x in 0x%02x)\n", "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, I915_STATE_WARN(pll->active_mask & crtc_mask,
"pll active mismatch (didn't expect pipe %c in active mask)\n", "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, I915_STATE_WARN(pll->state.crtc_mask & crtc_mask,
"pll enabled crtcs mismatch (found %x in enabled mask)\n", "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; int i;
for (i = 0; i < dev_priv->num_shared_dpll; i++) for (i = 0; i < dev_priv->dpll.num_shared_dpll; i++)
verify_single_dpll_state(dev_priv, &dev_priv->shared_dplls[i], NULL, NULL); verify_single_dpll_state(dev_priv,
&dev_priv->dpll.shared_dplls[i],
NULL, NULL);
} }
static void static void
@ -15318,7 +15323,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
struct intel_crtc *crtc; struct intel_crtc *crtc;
struct intel_crtc_state *old_crtc_state, *new_crtc_state; struct intel_crtc_state *old_crtc_state, *new_crtc_state;
struct skl_ddb_entry entries[I915_MAX_PIPES] = {}; struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
const u8 num_pipes = INTEL_NUM_PIPES(dev_priv);
u8 update_pipes = 0, modeset_pipes = 0; u8 update_pipes = 0, modeset_pipes = 0;
int i; int i;
@ -15355,7 +15359,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
continue; continue;
if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
entries, num_pipes, pipe)) entries, I915_MAX_PIPES, pipe))
continue; continue;
entries[pipe] = new_crtc_state->wm.skl.ddb; entries[pipe] = new_crtc_state->wm.skl.ddb;
@ -15393,7 +15397,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
continue; continue;
drm_WARN_ON(&dev_priv->drm, skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, 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; entries[pipe] = new_crtc_state->wm.skl.ddb;
modeset_pipes &= ~BIT(pipe); modeset_pipes &= ~BIT(pipe);
@ -15428,7 +15432,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state)
continue; continue;
drm_WARN_ON(&dev_priv->drm, skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb, 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; entries[pipe] = new_crtc_state->wm.skl.ddb;
modeset_pipes &= ~BIT(pipe); 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; struct intel_plane *plane;
const struct drm_plane_funcs *plane_funcs; const struct drm_plane_funcs *plane_funcs;
unsigned int supported_rotations; unsigned int supported_rotations;
unsigned int possible_crtcs;
const u32 *formats; const u32 *formats;
int num_formats; int num_formats;
int ret, zpos; 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->get_hw_state = i9xx_plane_get_hw_state;
plane->check_plane = i9xx_plane_check; plane->check_plane = i9xx_plane_check;
possible_crtcs = BIT(pipe);
if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
possible_crtcs, plane_funcs, 0, plane_funcs,
formats, num_formats, formats, num_formats,
i9xx_format_modifiers, i9xx_format_modifiers,
DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY,
"primary %c", pipe_name(pipe)); "primary %c", pipe_name(pipe));
else else
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
possible_crtcs, plane_funcs, 0, plane_funcs,
formats, num_formats, formats, num_formats,
i9xx_format_modifiers, i9xx_format_modifiers,
DRM_PLANE_TYPE_PRIMARY, DRM_PLANE_TYPE_PRIMARY,
@ -16454,7 +16455,6 @@ static struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv, intel_cursor_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe) enum pipe pipe)
{ {
unsigned int possible_crtcs;
struct intel_plane *cursor; struct intel_plane *cursor;
int ret, zpos; 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)) if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
cursor->cursor.size = ~0; cursor->cursor.size = ~0;
possible_crtcs = BIT(pipe);
ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base, ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
possible_crtcs, &intel_cursor_plane_funcs, 0, &intel_cursor_plane_funcs,
intel_cursor_formats, intel_cursor_formats,
ARRAY_SIZE(intel_cursor_formats), ARRAY_SIZE(intel_cursor_formats),
cursor_format_modifiers, cursor_format_modifiers,
@ -16619,6 +16617,18 @@ static void intel_crtc_free(struct intel_crtc *crtc)
kfree(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) static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
{ {
struct intel_plane *primary, *cursor; 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_color_init(crtc);
intel_crtc_crc_init(crtc);
drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe); drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
return 0; return 0;
@ -17785,11 +17797,9 @@ static void plane_config_fini(struct intel_initial_plane_config *plane_config)
i915_vma_put(plane_config->vma); 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; int ret;
i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0); 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); 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_init_pm(i915);
intel_panel_sanitize_ssc(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_shared_dpll_init(dev);
intel_update_fdi_pll_freq(i915); 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 intel_connector *connector;
struct drm_connector_list_iter conn_iter; struct drm_connector_list_iter conn_iter;
u8 active_pipes = 0; u8 active_pipes = 0;
int i;
for_each_intel_crtc(dev, crtc) { for_each_intel_crtc(dev, crtc) {
struct intel_crtc_state *crtc_state = 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); readout_plane_state(dev_priv);
for (i = 0; i < dev_priv->num_shared_dpll; i++) { intel_dpll_readout_hw_state(dev_priv);
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);
}
for_each_intel_encoder(dev, encoder) { for_each_intel_encoder(dev, encoder) {
pipe = 0; pipe = 0;
@ -18623,7 +18618,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
struct intel_encoder *encoder; struct intel_encoder *encoder;
struct intel_crtc *crtc; struct intel_crtc *crtc;
intel_wakeref_t wakeref; intel_wakeref_t wakeref;
int i;
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); 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); intel_modeset_update_connector_atomic_state(dev);
for (i = 0; i < dev_priv->num_shared_dpll; i++) { intel_dpll_sanitize_state(dev_priv);
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;
}
if (IS_G4X(dev_priv)) { if (IS_G4X(dev_priv)) {
g4x_wm_get_hw_state(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) #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 { struct intel_display_error_state {
u32 power_well_driver; 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++) { for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
enum transcoder cpu_transcoder = transcoders[i]; enum transcoder cpu_transcoder = transcoders[i];
if (!INTEL_INFO(dev_priv)->trans_offsets[cpu_transcoder]) if (!has_transcoder(dev_priv, cpu_transcoder))
continue; continue;
error->transcoder[i].available = true; error->transcoder[i].available = true;

View File

@ -26,7 +26,6 @@
#define _INTEL_DISPLAY_H_ #define _INTEL_DISPLAY_H_
#include <drm/drm_util.h> #include <drm/drm_util.h>
#include <drm/i915_drm.h>
enum link_m_n_set; enum link_m_n_set;
struct dpll; struct dpll;
@ -40,6 +39,7 @@ struct drm_framebuffer;
struct drm_i915_error_state_buf; struct drm_i915_error_state_buf;
struct drm_i915_gem_object; struct drm_i915_gem_object;
struct drm_i915_private; struct drm_i915_private;
struct drm_mode_fb_cmd2;
struct drm_modeset_acquire_ctx; struct drm_modeset_acquire_ctx;
struct drm_plane; struct drm_plane;
struct drm_plane_state; struct drm_plane_state;
@ -47,6 +47,7 @@ struct i915_ggtt_view;
struct intel_atomic_state; struct intel_atomic_state;
struct intel_crtc; struct intel_crtc;
struct intel_crtc_state; struct intel_crtc_state;
struct intel_crtc_state;
struct intel_digital_port; struct intel_digital_port;
struct intel_dp; struct intel_dp;
struct intel_encoder; struct intel_encoder;
@ -55,7 +56,6 @@ struct intel_plane;
struct intel_plane_state; struct intel_plane_state;
struct intel_remapped_info; struct intel_remapped_info;
struct intel_rotation_info; struct intel_rotation_info;
struct intel_crtc_state;
enum i915_gpio { enum i915_gpio {
GPIOA, GPIOA,
@ -313,10 +313,11 @@ enum phy_fia {
}; };
#define for_each_pipe(__dev_priv, __p) \ #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) \ #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)) for_each_if((__mask) & BIT(__p))
#define for_each_cpu_transcoder_masked(__dev_priv, __t, __mask) \ #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 */ /* modesetting */
void intel_modeset_init_hw(struct drm_i915_private *i915); 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); int intel_modeset_init(struct drm_i915_private *i915);
void intel_modeset_driver_remove(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); 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; int i;
drm_modeset_lock_all(dev); 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, seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name,
pll->info->id); pll->info->id);

View File

@ -939,11 +939,17 @@ unlock:
static void assert_can_enable_dc5(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, enum i915_power_well_id high_pg;
SKL_DISP_PW_2);
drm_WARN_ONCE(&dev_priv->drm, pg2_enabled, /* Power wells at this level and above must be disabled for DC5 entry */
"PG2 not disabled to enable DC5.\n"); 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, drm_WARN_ONCE(&dev_priv->drm,
(intel_de_read(dev_priv, DC_STATE_EN) & (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)) BIT_ULL(POWER_DOMAIN_INIT))
#define TGL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ #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_MODESET) | \
BIT_ULL(POWER_DOMAIN_AUX_A) | \ BIT_ULL(POWER_DOMAIN_AUX_A) | \
BIT_ULL(POWER_DOMAIN_AUX_B) | \ BIT_ULL(POWER_DOMAIN_AUX_B) | \
@ -3936,7 +3942,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
.name = "power well 3", .name = "power well 3",
.domains = TGL_PW_3_POWER_DOMAINS, .domains = TGL_PW_3_POWER_DOMAINS,
.ops = &hsw_power_well_ops, .ops = &hsw_power_well_ops,
.id = DISP_PW_ID_NONE, .id = TGL_DISP_PW_3,
{ {
.hsw.regs = &hsw_power_well_regs, .hsw.regs = &hsw_power_well_regs,
.hsw.idx = ICL_PW_CTL_IDX_PW_3, .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_MISC_IO,
SKL_DISP_PW_1, SKL_DISP_PW_1,
SKL_DISP_PW_2, SKL_DISP_PW_2,
TGL_DISP_PW_3,
SKL_DISP_DC_OFF, SKL_DISP_DC_OFF,
}; };

View File

@ -39,7 +39,6 @@
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/drm_vblank.h> #include <drm/drm_vblank.h>
#include <drm/i915_drm.h>
#include <drm/i915_mei_hdcp_interface.h> #include <drm/i915_mei_hdcp_interface.h>
#include <media/cec-notifier.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 */ /* Flag to use the scanline counter instead of the pixel counter */
#define I915_MODE_FLAG_USE_SCANLINE_COUNTER (1<<2) #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_pipe_wm {
struct intel_wm_level wm[5]; struct intel_wm_level wm[5];
bool fbc_wm_enabled; bool fbc_wm_enabled;
@ -650,6 +657,14 @@ struct intel_pipe_wm {
bool sprites_scaled; 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_plane_wm {
struct skl_wm_level wm[8]; struct skl_wm_level wm[8];
struct skl_wm_level uv_wm[8]; struct skl_wm_level uv_wm[8];
@ -1046,6 +1061,32 @@ struct intel_crtc_state {
enum transcoder mst_master_transcoder; 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 intel_crtc {
struct drm_crtc base; struct drm_crtc base;
enum pipe pipe; enum pipe pipe;
@ -1089,6 +1130,10 @@ struct intel_crtc {
/* per pipe DSB related info */ /* per pipe DSB related info */
struct intel_dsb dsb; struct intel_dsb dsb;
#ifdef CONFIG_DEBUG_FS
struct intel_pipe_crc pipe_crc;
#endif
}; };
struct intel_plane { struct intel_plane {
@ -1235,6 +1280,7 @@ struct intel_dp {
int max_link_rate; int max_link_rate;
/* sink or branch descriptor */ /* sink or branch descriptor */
struct drm_dp_desc desc; struct drm_dp_desc desc;
u32 edid_quirks;
struct drm_dp_aux aux; struct drm_dp_aux aux;
u32 aux_busy_last_status; u32 aux_busy_last_status;
u8 train_set[4]; 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 * static inline struct intel_crtc *
intel_get_crtc_for_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) 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]; 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_DP_MST) |
(1 << INTEL_OUTPUT_EDP)); (1 << INTEL_OUTPUT_EDP));
} }
static inline void static inline void
intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe) 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 static inline void
intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, enum pipe pipe) 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_edid.h>
#include <drm/drm_hdcp.h> #include <drm/drm_hdcp.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include <drm/i915_drm.h>
#include "i915_debugfs.h" #include "i915_debugfs.h"
#include "i915_drv.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_connector *intel_connector = intel_dp->attached_connector;
struct intel_digital_connector_state *intel_conn_state = struct intel_digital_connector_state *intel_conn_state =
to_intel_digital_connector_state(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); DP_DPCD_QUIRK_CONSTANT_N);
int ret = 0, output_bpp; 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(). * it don't care about read it here and in intel_edp_init_dpcd().
*/ */
if (!intel_dp_is_edp(intel_dp) && 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; u8 count;
ssize_t r; 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); intel_dp->has_audio = drm_detect_monitor_audio(edid);
drm_dp_cec_set_edid(&intel_dp->aux, edid); drm_dp_cec_set_edid(&intel_dp->aux, edid);
intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
} }
static void static void
@ -5694,6 +5695,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
intel_connector->detect_edid = NULL; intel_connector->detect_edid = NULL;
intel_dp->has_audio = false; intel_dp->has_audio = false;
intel_dp->edid_quirks = 0;
} }
static int static int
@ -6449,6 +6451,7 @@ static
int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port, int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
bool is_repeater, u8 content_type) bool is_repeater, u8 content_type)
{ {
int ret;
struct hdcp2_dp_errata_stream_type stream_type_msg; struct hdcp2_dp_errata_stream_type stream_type_msg;
if (is_repeater) 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.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE;
stream_type_msg.stream_type = content_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)); sizeof(stream_type_msg));
return ret < 0 ? ret : 0;
} }
static 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); edid = drm_get_edid(connector, &intel_dp->aux.ddc);
if (edid) { if (edid) {
if (drm_add_edid_modes(connector, edid)) { if (drm_add_edid_modes(connector, edid)) {
drm_connector_update_edid_property(connector, drm_connector_update_edid_property(connector, edid);
edid); intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
} else { } else {
kfree(edid); kfree(edid);
edid = ERR_PTR(-EINVAL); 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); intel_panel_setup_backlight(connector, pipe);
if (fixed_mode) { if (fixed_mode) {
/* We do not know the orientation, but their might be a quirk */
drm_connector_set_panel_orientation_with_quirk(connector, drm_connector_set_panel_orientation_with_quirk(connector,
DRM_MODE_PANEL_ORIENTATION_UNKNOWN, dev_priv->vbt.orientation,
fixed_mode->hdisplay, fixed_mode->vdisplay); fixed_mode->hdisplay, fixed_mode->vdisplay);
} }

View File

@ -8,8 +8,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <drm/i915_drm.h>
#include "i915_reg.h" #include "i915_reg.h"
enum pipe; 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) int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
{ {
struct intel_panel *panel = &intel_connector->panel; 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 || if (i915_modparams.enable_dpcd_backlight == 0 ||
(i915_modparams.enable_dpcd_backlight == -1 && !intel_dp_aux_display_control_capable(intel_connector))
dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
return -ENODEV; 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; return -ENODEV;
}
panel->backlight.setup = intel_dp_aux_setup_backlight; panel->backlight.setup = intel_dp_aux_setup_backlight;
panel->backlight.enable = intel_dp_aux_enable_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 = const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode; &crtc_state->hw.adjusted_mode;
void *port = connector->port; 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); DP_DPCD_QUIRK_CONSTANT_N);
int bpp, slots = -EINVAL; int bpp, slots = -EINVAL;
@ -548,12 +548,41 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
return ret; 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 = { static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_digital_connector_atomic_get_property, .atomic_get_property = intel_digital_connector_atomic_get_property,
.atomic_set_property = intel_digital_connector_atomic_set_property, .atomic_set_property = intel_digital_connector_atomic_set_property,
.late_register = intel_connector_register, .late_register = intel_dp_mst_connector_late_register,
.early_unregister = intel_connector_unregister, .early_unregister = intel_dp_mst_connector_early_unregister,
.destroy = intel_connector_destroy, .destroy = intel_connector_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_digital_connector_duplicate_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, bool (*get_hw_state)(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll, struct intel_shared_dpll *pll,
struct intel_dpll_hw_state *hw_state); 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, void intel_update_active_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc, struct intel_crtc *crtc,
struct intel_encoder *encoder); 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_prepare_shared_dpll(const struct intel_crtc_state *crtc_state);
void intel_enable_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_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_swap_state(struct intel_atomic_state *state);
void intel_shared_dpll_init(struct drm_device *dev); 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, void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
const struct intel_dpll_hw_state *hw_state); 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); 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); 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)); dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id));
if (DSB_STATUS & dsb_ctrl) { 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; 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)); dsb_ctrl = intel_de_read(dev_priv, DSB_CTRL(pipe, dsb->id));
if (DSB_STATUS & dsb_ctrl) { 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; return false;
} }
@ -115,20 +115,20 @@ intel_dsb_get(struct intel_crtc *crtc)
obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE); obj = i915_gem_object_create_internal(i915, DSB_BUF_SIZE);
if (IS_ERR(obj)) { if (IS_ERR(obj)) {
DRM_ERROR("Gem object creation failed\n"); drm_err(&i915->drm, "Gem object creation failed\n");
goto out; goto out;
} }
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0);
if (IS_ERR(vma)) { if (IS_ERR(vma)) {
DRM_ERROR("Vma creation failed\n"); drm_err(&i915->drm, "Vma creation failed\n");
i915_gem_object_put(obj); i915_gem_object_put(obj);
goto out; goto out;
} }
buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC); buf = i915_gem_object_pin_map(vma->obj, I915_MAP_WC);
if (IS_ERR(buf)) { if (IS_ERR(buf)) {
DRM_ERROR("Command buffer creation failed\n"); drm_err(&i915->drm, "Command buffer creation failed\n");
goto out; 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)) { 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; 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)) { 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; return;
} }
@ -310,7 +310,8 @@ void intel_dsb_commit(struct intel_dsb *dsb)
goto reset; goto reset;
if (is_dsb_busy(dsb)) { 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; goto reset;
} }
intel_de_write(dev_priv, DSB_HEAD(pipe, dsb->id), 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)); (tail - dsb->free_pos * 4));
if (is_dsb_busy(dsb)) { 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; goto reset;
} }
DRM_DEBUG_KMS("DSB execution started - head 0x%x, tail 0x%x\n", drm_dbg_kms(&dev_priv->drm,
i915_ggtt_offset(dsb->vma), tail); "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), intel_de_write(dev_priv, DSB_TAIL(pipe, dsb->id),
i915_ggtt_offset(dsb->vma) + tail); i915_ggtt_offset(dsb->vma) + tail);
if (wait_for(!is_dsb_busy(dsb), 1)) { 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; goto reset;
} }

View File

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

View File

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

View File

@ -42,6 +42,7 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "i915_vgpu.h"
#include "intel_display_types.h" #include "intel_display_types.h"
#include "intel_fbc.h" #include "intel_fbc.h"
#include "intel_frontbuffer.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); SNB_CPU_FENCE_ENABLE | params->fence_id);
intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET,
params->crtc.fence_y_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, SNB_DPFC_CTL_SA, 0);
intel_de_write(dev_priv, DPFC_CPU_FENCE_OFFSET, 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; fbc->compressed_llb = compressed_llb;
GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start, GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
fbc->compressed_fb.start, fbc->compressed_fb.start,
U32_MAX)); U32_MAX));
GEM_BUG_ON(range_overflows_t(u64, dev_priv->dsm.start, GEM_BUG_ON(range_overflows_end_t(u64, dev_priv->dsm.start,
fbc->compressed_llb->start, fbc->compressed_llb->start,
U32_MAX)); U32_MAX));
intel_de_write(dev_priv, FBC_CFB_BASE, intel_de_write(dev_priv, FBC_CFB_BASE,
dev_priv->dsm.start + fbc->compressed_fb.start); dev_priv->dsm.start + fbc->compressed_fb.start);
intel_de_write(dev_priv, FBC_LL_BASE, 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; 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) static bool intel_fbc_can_activate(struct intel_crtc *crtc)
{ {
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_fbc *fbc = &dev_priv->fbc; struct intel_fbc *fbc = &dev_priv->fbc;
struct intel_fbc_state_cache *cache = &fbc->state_cache; struct intel_fbc_state_cache *cache = &fbc->state_cache;
if (!intel_fbc_can_enable(dev_priv))
return false;
if (!cache->plane.visible) { if (!cache->plane.visible) {
fbc->no_fbc_reason = "primary plane not visible"; fbc->no_fbc_reason = "primary plane not visible";
return false; return false;
@ -795,28 +821,6 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
return true; 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, static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
struct intel_fbc_reg_params *params) struct intel_fbc_reg_params *params)
{ {

View File

@ -40,7 +40,6 @@
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_display_types.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); intel_de_posting_read(dev_priv, reg);
trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe); 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, 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); intel_de_posting_read(dev_priv, reg);
} else { } else {
if (old && intel_de_read(dev_priv, reg) & PIPE_FIFO_UNDERRUN_STATUS) 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); intel_de_posting_read(dev_priv, GEN7_ERR_INT);
trace_intel_cpu_fifo_underrun(dev_priv, pipe); 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, 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 && if (old &&
intel_de_read(dev_priv, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) { intel_de_read(dev_priv, GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
DRM_ERROR("uncleared fifo underrun on pipe %c\n", drm_err(&dev_priv->drm,
pipe_name(pipe)); "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); intel_de_posting_read(dev_priv, SERR_INT);
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder); trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
DRM_ERROR("pch fifo underrun on pch transcoder %c\n", drm_err(&dev_priv->drm, "pch fifo underrun on pch transcoder %c\n",
pipe_name(pch_transcoder)); pipe_name(pch_transcoder));
} }
static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, 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) & if (old && intel_de_read(dev_priv, SERR_INT) &
SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) { SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n", drm_err(&dev_priv->drm,
pipe_name(pch_transcoder)); "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)) { if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
trace_intel_cpu_fifo_underrun(dev_priv, pipe); trace_intel_cpu_fifo_underrun(dev_priv, pipe);
DRM_ERROR("CPU pipe %c FIFO underrun\n", drm_err(&dev_priv->drm, "CPU pipe %c FIFO underrun\n",
pipe_name(pipe)); pipe_name(pipe));
} }
intel_fbc_handle_fifo_underrun_irq(dev_priv); 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, if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
false)) { false)) {
trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder); trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
DRM_ERROR("PCH transcoder %c FIFO underrun\n", drm_err(&dev_priv->drm, "PCH transcoder %c FIFO underrun\n",
pipe_name(pch_transcoder)); pipe_name(pch_transcoder));
} }
} }

View File

@ -32,7 +32,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <drm/drm_hdcp.h> #include <drm/drm_hdcp.h>
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_display_types.h" #include "intel_display_types.h"
@ -632,8 +631,9 @@ retry:
* till then let it sleep. * till then let it sleep.
*/ */
if (gmbus_wait_idle(dev_priv)) { if (gmbus_wait_idle(dev_priv)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n", drm_dbg_kms(&dev_priv->drm,
adapter->name); "GMBUS [%s] timed out waiting for idle\n",
adapter->name);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} }
intel_de_write_fw(dev_priv, GMBUS0, 0); intel_de_write_fw(dev_priv, GMBUS0, 0);
@ -656,8 +656,9 @@ clear_err:
*/ */
ret = -ENXIO; ret = -ENXIO;
if (gmbus_wait_idle(dev_priv)) { if (gmbus_wait_idle(dev_priv)) {
DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n", drm_dbg_kms(&dev_priv->drm,
adapter->name); "GMBUS [%s] timed out after NAK\n",
adapter->name);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
} }
@ -669,9 +670,9 @@ clear_err:
intel_de_write_fw(dev_priv, GMBUS1, 0); intel_de_write_fw(dev_priv, GMBUS1, 0);
intel_de_write_fw(dev_priv, GMBUS0, 0); intel_de_write_fw(dev_priv, GMBUS0, 0);
DRM_DEBUG_KMS("GMBUS [%s] NAK for addr: %04x %c(%d)\n", drm_dbg_kms(&dev_priv->drm, "GMBUS [%s] NAK for addr: %04x %c(%d)\n",
adapter->name, msgs[i].addr, adapter->name, msgs[i].addr,
(msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len); (msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len);
/* /*
* Passive adapters sometimes NAK the first probe. Retry the first * Passive adapters sometimes NAK the first probe. Retry the first
@ -680,16 +681,18 @@ clear_err:
* drm_do_probe_ddc_edid, which bails out on the first -ENXIO. * drm_do_probe_ddc_edid, which bails out on the first -ENXIO.
*/ */
if (ret == -ENXIO && i == 0 && try++ == 0) { if (ret == -ENXIO && i == 0 && try++ == 0) {
DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n", drm_dbg_kms(&dev_priv->drm,
adapter->name); "GMBUS [%s] NAK on first message, retry\n",
adapter->name);
goto retry; goto retry;
} }
goto out; goto out;
timeout: timeout:
DRM_DEBUG_KMS("GMBUS [%s] timed out, falling back to bit banging on pin %d\n", drm_dbg_kms(&dev_priv->drm,
bus->adapter.name, bus->reg0 & 0xff); "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); 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); mutex_lock(&dev_priv->gmbus_mutex);
bus->force_bit += force_bit ? 1 : -1; bus->force_bit += force_bit ? 1 : -1;
DRM_DEBUG_KMS("%sabling bit-banging on %s. force bit now %d\n", drm_dbg_kms(&dev_priv->drm,
force_bit ? "en" : "dis", adapter->name, "%sabling bit-banging on %s. force bit now %d\n",
bus->force_bit); force_bit ? "en" : "dis", adapter->name,
bus->force_bit);
mutex_unlock(&dev_priv->gmbus_mutex); 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, int intel_hdcp_read_valid_bksv(struct intel_digital_port *intel_dig_port,
const struct intel_hdcp_shim *shim, u8 *bksv) 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; int ret, i, tries = 2;
/* HDCP spec states that we must retry the bksv if it is invalid */ /* 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; break;
} }
if (i == tries) { if (i == tries) {
DRM_DEBUG_KMS("Bksv is invalid\n"); drm_dbg_kms(&i915->drm, "Bksv is invalid\n");
return -ENODEV; return -ENODEV;
} }
@ -485,8 +486,8 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
return ret; return ret;
sha_idx += sizeof(sha_text); sha_idx += sizeof(sha_text);
} else { } else {
DRM_DEBUG_KMS("Invalid number of leftovers %d\n", drm_dbg_kms(&dev_priv->drm, "Invalid number of leftovers %d\n",
sha_leftovers); sha_leftovers);
return -EINVAL; return -EINVAL;
} }
@ -514,11 +515,11 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector,
rep_ctl | HDCP_SHA1_COMPLETE_HASH); rep_ctl | HDCP_SHA1_COMPLETE_HASH);
if (intel_de_wait_for_set(dev_priv, HDCP_REP_CTL, if (intel_de_wait_for_set(dev_priv, HDCP_REP_CTL,
HDCP_SHA1_COMPLETE, 1)) { 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; return -ETIMEDOUT;
} }
if (!(intel_de_read(dev_priv, HDCP_REP_CTL) & HDCP_SHA1_V_MATCH)) { 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; 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); ret = intel_hdcp_poll_ksv_fifo(intel_dig_port, shim);
if (ret) { 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; return ret;
} }
@ -547,7 +549,7 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) || if (DRM_HDCP_MAX_DEVICE_EXCEEDED(bstatus[0]) ||
DRM_HDCP_MAX_CASCADE_EXCEEDED(bstatus[1])) { 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; return -EPERM;
} }
@ -560,13 +562,14 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
*/ */
num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]); num_downstream = DRM_HDCP_NUM_DOWNSTREAM(bstatus[0]);
if (num_downstream == 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; return -EINVAL;
} }
ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL); ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL);
if (!ksv_fifo) { 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; 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, if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, ksv_fifo,
num_downstream)) { 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; ret = -EPERM;
goto err; goto err;
} }
@ -594,12 +597,13 @@ int intel_hdcp_auth_downstream(struct intel_connector *connector)
} }
if (i == tries) { 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; goto err;
} }
DRM_DEBUG_KMS("HDCP is enabled (%d downstream devices)\n", drm_dbg_kms(&dev_priv->drm, "HDCP is enabled (%d downstream devices)\n",
num_downstream); num_downstream);
ret = 0; ret = 0;
err: err:
kfree(ksv_fifo); kfree(ksv_fifo);
@ -642,7 +646,8 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (ret) if (ret)
return ret; return ret;
if (!hdcp_capable) { 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; return -EINVAL;
} }
} }
@ -659,7 +664,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (intel_de_wait_for_set(dev_priv, if (intel_de_wait_for_set(dev_priv,
HDCP_STATUS(dev_priv, cpu_transcoder, port), HDCP_STATUS(dev_priv, cpu_transcoder, port),
HDCP_STATUS_AN_READY, 1)) { 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; return -ETIMEDOUT;
} }
@ -680,7 +685,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
return ret; return ret;
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, bksv.shim, 1)) { 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; return -EPERM;
} }
@ -706,7 +711,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
/* Wait for R0 ready */ /* Wait for R0 ready */
if (wait_for(intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)) & if (wait_for(intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port)) &
(HDCP_STATUS_R0_READY | HDCP_STATUS_ENC), 1)) { (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; return -ETIMEDOUT;
} }
@ -743,8 +748,10 @@ static int intel_hdcp_auth(struct intel_connector *connector)
} }
if (i == tries) { if (i == tries) {
DRM_DEBUG_KMS("Timed out waiting for Ri prime match (%x)\n", drm_dbg_kms(&dev_priv->drm,
intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port))); "Timed out waiting for Ri prime match (%x)\n",
intel_de_read(dev_priv, HDCP_STATUS(dev_priv,
cpu_transcoder, port)));
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -753,7 +760,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
HDCP_STATUS(dev_priv, cpu_transcoder, port), HDCP_STATUS(dev_priv, cpu_transcoder, port),
HDCP_STATUS_ENC, HDCP_STATUS_ENC,
ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { 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; return -ETIMEDOUT;
} }
@ -765,7 +772,7 @@ static int intel_hdcp_auth(struct intel_connector *connector)
if (repeater_present) if (repeater_present)
return intel_hdcp_auth_downstream(connector); 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; return 0;
} }
@ -1271,7 +1278,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
return ret; return ret;
if (msgs.send_cert.rx_caps[0] != HDCP_2_2_RX_CAPS_VERSION_VAL) { 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; 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, if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
msgs.send_cert.cert_rx.receiver_id, msgs.send_cert.cert_rx.receiver_id,
1)) { 1)) {
DRM_ERROR("Receiver ID is revoked\n"); drm_err(&dev_priv->drm, "Receiver ID is revoked\n");
return -EPERM; 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]) || if (HDCP_2_2_MAX_CASCADE_EXCEEDED(rx_info[1]) ||
HDCP_2_2_MAX_DEVS_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; return -EINVAL;
} }
@ -1463,9 +1470,15 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
seq_num_v = seq_num_v =
drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.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) { if (seq_num_v < hdcp->seq_num_v) {
/* Roll over of the seq_num_v from repeater. Reauthenticate. */ /* 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; return -EINVAL;
} }
@ -1474,7 +1487,7 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm, if (drm_hdcp_check_ksvs_revoked(&dev_priv->drm,
msgs.recvid_list.receiver_ids, msgs.recvid_list.receiver_ids,
device_cnt)) { 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; return -EPERM;
} }
@ -1507,25 +1520,27 @@ static int hdcp2_authenticate_repeater(struct intel_connector *connector)
static int hdcp2_authenticate_sink(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 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; struct intel_hdcp *hdcp = &connector->hdcp;
const struct intel_hdcp_shim *shim = hdcp->shim; const struct intel_hdcp_shim *shim = hdcp->shim;
int ret; int ret;
ret = hdcp2_authentication_key_exchange(connector); ret = hdcp2_authentication_key_exchange(connector);
if (ret < 0) { 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; return ret;
} }
ret = hdcp2_locality_check(connector); ret = hdcp2_locality_check(connector);
if (ret < 0) { 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; return ret;
} }
ret = hdcp2_session_key_exchange(connector); ret = hdcp2_session_key_exchange(connector);
if (ret < 0) { 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; return ret;
} }
@ -1540,7 +1555,8 @@ static int hdcp2_authenticate_sink(struct intel_connector *connector)
if (hdcp->is_repeater) { if (hdcp->is_repeater) {
ret = hdcp2_authenticate_repeater(connector); ret = hdcp2_authenticate_repeater(connector);
if (ret < 0) { 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; 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) 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; int ret, i, tries = 3;
for (i = 0; i < tries; i++) { for (i = 0; i < tries; i++) {
@ -1638,10 +1655,10 @@ static int hdcp2_authenticate_and_encrypt(struct intel_connector *connector)
break; break;
/* Clearing the mei hdcp session */ /* Clearing the mei hdcp session */
DRM_DEBUG_KMS("HDCP2.2 Auth %d of %d Failed.(%d)\n", drm_dbg_kms(&i915->drm, "HDCP2.2 Auth %d of %d Failed.(%d)\n",
i + 1, tries, ret); i + 1, tries, ret);
if (hdcp2_deauthenticate_port(connector) < 0) 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) { 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); msleep(HDCP_2_2_DELAY_BEFORE_ENCRYPTION_EN);
ret = hdcp2_enable_encryption(connector); ret = hdcp2_enable_encryption(connector);
if (ret < 0) { 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) 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) 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; struct intel_hdcp *hdcp = &connector->hdcp;
int ret; int ret;
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being enabled. Type: %d\n", drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being enabled. Type: %d\n",
connector->base.name, connector->base.base.id, connector->base.name, connector->base.base.id,
hdcp->content_type); hdcp->content_type);
ret = hdcp2_authenticate_and_encrypt(connector); ret = hdcp2_authenticate_and_encrypt(connector);
if (ret) { if (ret) {
DRM_DEBUG_KMS("HDCP2 Type%d Enabling Failed. (%d)\n", drm_dbg_kms(&i915->drm, "HDCP2 Type%d Enabling Failed. (%d)\n",
hdcp->content_type, ret); hdcp->content_type, ret);
return ret; return ret;
} }
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is enabled. Type %d\n", drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is enabled. Type %d\n",
connector->base.name, connector->base.base.id, connector->base.name, connector->base.base.id,
hdcp->content_type); hdcp->content_type);
hdcp->hdcp2_encrypted = true; hdcp->hdcp2_encrypted = true;
return 0; return 0;
@ -1687,15 +1706,16 @@ static int _intel_hdcp2_enable(struct intel_connector *connector)
static int _intel_hdcp2_disable(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; int ret;
DRM_DEBUG_KMS("[%s:%d] HDCP2.2 is being Disabled\n", drm_dbg_kms(&i915->drm, "[%s:%d] HDCP2.2 is being Disabled\n",
connector->base.name, connector->base.base.id); connector->base.name, connector->base.base.id);
ret = hdcp2_disable_encryption(connector); ret = hdcp2_disable_encryption(connector);
if (hdcp2_deauthenticate_port(connector) < 0) 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; 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, static void intel_hdcp2_init(struct intel_connector *connector,
const struct intel_hdcp_shim *shim) const struct intel_hdcp_shim *shim)
{ {
struct drm_i915_private *i915 = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp; struct intel_hdcp *hdcp = &connector->hdcp;
int ret; int ret;
ret = initialize_hdcp_port_data(connector, shim); ret = initialize_hdcp_port_data(connector, shim);
if (ret) { if (ret) {
DRM_DEBUG_KMS("Mei hdcp data init failed\n"); drm_dbg_kms(&i915->drm, "Mei hdcp data init failed\n");
return; return;
} }

View File

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

View File

@ -36,7 +36,6 @@
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_hdcp.h> #include <drm/drm_hdcp.h>
#include <drm/drm_scdc_helper.h> #include <drm/drm_scdc_helper.h>
#include <drm/i915_drm.h>
#include <drm/intel_lpe_audio.h> #include <drm/intel_lpe_audio.h>
#include "i915_debugfs.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 */ /* Display Wa_1405510057:icl,ehl */
if (bpc == 12 && IS_GLK_REVID(dev_priv, 0, GLK_REVID_A1) &&
adjusted_mode->htotal > 5460)
return false;
/* Display Wa_1405510057:icl */
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 && 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_end -
adjusted_mode->crtc_hblank_start) % 8 == 2) adjusted_mode->crtc_hblank_start) % 8 == 2)
return false; return false;

View File

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

View File

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

View File

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

View File

@ -127,7 +127,8 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
kfree(pdata); kfree(pdata);
if (IS_ERR(platdev)) { 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; return platdev;
} }
@ -190,7 +191,8 @@ static bool lpe_audio_detect(struct drm_i915_private *dev_priv)
}; };
if (!pci_dev_present(atom_hdaudio_ids)) { 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; 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); dev_priv->lpe_audio.irq = irq_alloc_desc(0);
if (dev_priv->lpe_audio.irq < 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); dev_priv->lpe_audio.irq);
ret = dev_priv->lpe_audio.irq; ret = dev_priv->lpe_audio.irq;
goto err; 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); ret = lpe_audio_irq_init(dev_priv);
if (ret) { 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); ret);
goto err_free_irq; 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)) { if (IS_ERR(dev_priv->lpe_audio.platdev)) {
ret = PTR_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); ret);
goto err_free_irq; 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); ret = generic_handle_irq(dev_priv->lpe_audio.irq);
if (ret) if (ret)
DRM_ERROR_RATELIMITED("error handling LPE audio irq: %d\n", drm_err_ratelimited(&dev_priv->drm,
ret); "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)) { if (lpe_audio_detect(dev_priv)) {
ret = lpe_audio_setup(dev_priv); ret = lpe_audio_setup(dev_priv);
if (ret < 0) 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; return ret;
} }

View File

@ -37,7 +37,6 @@
#include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_atomic.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 && if (INTEL_GEN(dev_priv) <= 4 &&
pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) { pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
DRM_DEBUG_KMS("Panel power timings uninitialized, " drm_dbg_kms(&dev_priv->drm,
"setting defaults\n"); "Panel power timings uninitialized, "
"setting defaults\n");
/* Set T2 to 40ms and T5 to 200ms in 100 usec units */ /* Set T2 to 40ms and T5 to 200ms in 100 usec units */
pps->t1_t2 = 40 * 10; pps->t1_t2 = 40 * 10;
pps->t5 = 200 * 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; pps->tx = 200 * 10;
} }
DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d " 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", "divider %d port %d powerdown_on_reset %d\n",
pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx, pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
pps->divider, pps->port, pps->powerdown_on_reset); pps->divider, pps->port, pps->powerdown_on_reset);
} }
static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv, 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); intel_de_posting_read(dev_priv, lvds_encoder->reg);
if (intel_de_wait_for_set(dev_priv, PP_STATUS(0), PP_ON, 5000)) 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); 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_write(dev_priv, PP_CONTROL(0),
intel_de_read(dev_priv, PP_CONTROL(0)) & ~PANEL_POWER_ON); 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)) 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_write(dev_priv, lvds_encoder->reg,
intel_de_read(dev_priv, lvds_encoder->reg) & ~LVDS_PORT_EN); 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!! */ /* Should never happen!! */
if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) { 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; return -EINVAL;
} }
@ -408,8 +410,9 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
lvds_bpp = 6*3; lvds_bpp = 6*3;
if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) { if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n", drm_dbg_kms(&dev_priv->drm,
pipe_config->pipe_bpp, lvds_bpp); "forcing display bpp (was %d) to LVDS (%d)\n",
pipe_config->pipe_bpp, lvds_bpp);
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) { 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; return;
} }
@ -852,10 +856,12 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
pin = GMBUS_PIN_PANEL; pin = GMBUS_PIN_PANEL;
if (!intel_bios_is_lvds_present(dev_priv, &pin)) { if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
if ((lvds & LVDS_PORT_EN) == 0) { 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; 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); 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); fixed_mode = intel_encoder_current_mode(intel_encoder);
if (fixed_mode) { 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); drm_mode_debug_printmodeline(fixed_mode);
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
} }
@ -985,8 +991,8 @@ out:
intel_panel_setup_backlight(connector, INVALID_PIPE); intel_panel_setup_backlight(connector, INVALID_PIPE);
lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder); lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
DRM_DEBUG_KMS("detected %s-link lvds configuration\n", drm_dbg_kms(&dev_priv->drm, "detected %s-link lvds configuration\n",
lvds_encoder->is_dual_link ? "dual" : "single"); lvds_encoder->is_dual_link ? "dual" : "single");
lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK; lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
@ -995,7 +1001,7 @@ out:
failed: failed:
mutex_unlock(&dev->mode_config.mutex); 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_connector_cleanup(connector);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(lvds_encoder); kfree(lvds_encoder);

View File

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

View File

@ -27,7 +27,6 @@
*/ */
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/i915_drm.h>
#include "gem/i915_gem_pm.h" #include "gem/i915_gem_pm.h"
#include "gt/intel_ring.h" #include "gt/intel_ring.h"
@ -324,7 +323,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
/* check for underruns */ /* check for underruns */
tmp = intel_de_read(dev_priv, DOVSTA); tmp = intel_de_read(dev_priv, DOVSTA);
if (tmp & (1 << 17)) 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); rq = alloc_request(overlay, NULL);
if (IS_ERR(rq)) if (IS_ERR(rq))
@ -1069,7 +1068,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
overlay = dev_priv->overlay; overlay = dev_priv->overlay;
if (!overlay) { if (!overlay) {
DRM_DEBUG("userspace bug: no overlay\n"); drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
return -ENODEV; return -ENODEV;
} }
@ -1093,7 +1092,8 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
if (i915_gem_object_is_tiled(new_bo)) { 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; ret = -EINVAL;
goto out_unlock; goto out_unlock;
} }
@ -1228,7 +1228,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
overlay = dev_priv->overlay; overlay = dev_priv->overlay;
if (!overlay) { if (!overlay) {
DRM_DEBUG("userspace bug: no overlay\n"); drm_dbg(&dev_priv->drm, "userspace bug: no overlay\n");
return -ENODEV; return -ENODEV;
} }
@ -1372,7 +1372,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
update_reg_attrs(overlay, overlay->regs); update_reg_attrs(overlay, overlay->regs);
dev_priv->overlay = overlay; dev_priv->overlay = overlay;
DRM_INFO("Initialized overlay support.\n"); drm_info(&dev_priv->drm, "Initialized overlay support.\n");
return; return;
out_free: 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 drm_i915_private *dev_priv = to_i915(dev);
struct intel_panel *panel = &connector->panel; struct intel_panel *panel = &connector->panel;
const char *desc; const char *desc;
u32 level, ns;
int retval; int retval;
/* Get the right PWM chip for DSI backlight according to VBT */ /* 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); pwm_apply_args(panel->backlight.pwm);
retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS, panel->backlight.min = 0; /* 0% */
CRC_PMIC_PWM_PERIOD_NS); 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) { if (retval < 0) {
drm_err(&dev_priv->drm, "Failed to configure the pwm chip\n"); drm_err(&dev_priv->drm, "Failed to configure the pwm chip\n");
pwm_put(panel->backlight.pwm); pwm_put(panel->backlight.pwm);
@ -1915,11 +1920,10 @@ static int pwm_setup_backlight(struct intel_connector *connector,
return retval; return retval;
} }
panel->backlight.min = 0; /* 0% */ level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100,
panel->backlight.max = 100; /* 100% */ CRC_PMIC_PWM_PERIOD_NS);
panel->backlight.level = DIV_ROUND_UP( panel->backlight.level =
pwm_get_duty_cycle(panel->backlight.pwm) * 100, intel_panel_compute_brightness(connector, level);
CRC_PMIC_PWM_PERIOD_NS);
panel->backlight.enabled = panel->backlight.level != 0; panel->backlight.enabled = panel->backlight.level != 0;
drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n", 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; 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) { spin_lock_init(&pipe_crc->lock);
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
spin_lock_init(&pipe_crc->lock);
}
} }
static int i8xx_crc_source_valid(struct drm_i915_private *dev_priv, 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) 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 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_display_power_domain power_domain;
enum intel_pipe_crc_source source; enum intel_pipe_crc_source source;
intel_wakeref_t wakeref; 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_crtc *crtc = &intel_crtc->base;
struct drm_i915_private *dev_priv = to_i915(crtc->dev); 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; u32 val = 0;
if (!crtc->crc.opened) 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_crtc *crtc = &intel_crtc->base;
struct drm_i915_private *dev_priv = to_i915(crtc->dev); 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. */ /* Swallow crc's until we stop generating them. */
spin_lock_irq(&pipe_crc->lock); spin_lock_irq(&pipe_crc->lock);

View File

@ -13,7 +13,7 @@ struct drm_i915_private;
struct intel_crtc; struct intel_crtc;
#ifdef CONFIG_DEBUG_FS #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_set_crc_source(struct drm_crtc *crtc, const char *source_name);
int intel_crtc_verify_crc_source(struct drm_crtc *crtc, int intel_crtc_verify_crc_source(struct drm_crtc *crtc,
const char *source_name, size_t *values_cnt); 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_disable_pipe_crc(struct intel_crtc *crtc);
void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc); void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc);
#else #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_set_crc_source NULL
#define intel_crtc_verify_crc_source NULL #define intel_crtc_verify_crc_source NULL
#define intel_crtc_get_crc_sources 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", drm_dbg_kms(&dev_priv->drm, "eDP panel supports PSR version %x\n",
intel_dp->psr_dpcd[0]); 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, drm_dbg_kms(&dev_priv->drm,
"PSR support not currently available for this panel\n"); "PSR support not currently available for this panel\n");
return; return;

View File

@ -82,6 +82,16 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = {
DMI_MATCH(DMI_PRODUCT_NAME, ""), 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 */ { } /* terminating entry */
}, },
.hook = quirk_invert_brightness, .hook = quirk_invert_brightness,

View File

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

View File

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

View File

@ -37,10 +37,10 @@
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h> #include <drm/drm_plane_helper.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "i915_vgpu.h"
#include "intel_atomic_plane.h" #include "intel_atomic_plane.h"
#include "intel_display_types.h" #include "intel_display_types.h"
#include "intel_frontbuffer.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; u32 src_x, src_y, src_w, src_h, hsub, vsub;
bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation); 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. * Hardware doesn't handle subpixel coordinates.
* Adjust to (macro)pixel boundary, but be careful not to * 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, drm_rect_init(src, src_x << 16, src_y << 16,
src_w << 16, src_h << 16); src_w << 16, src_h << 16);
if (!fb->format->is_yuv) if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
return 0; hsub = 2;
vsub = 2;
/* YUV specific checks */ } else {
if (!rotated) {
hsub = fb->format->hsub; hsub = fb->format->hsub;
vsub = fb->format->vsub; 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) { 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", DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
src_x, src_w, hsub, rotated ? "rotated " : ""); src_x, src_w, hsub, yesno(rotated));
return -EINVAL; return -EINVAL;
} }
if (src_y % vsub || src_h % vsub) { 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", DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
src_y, src_h, vsub, rotated ? "rotated " : ""); src_y, src_h, vsub, yesno(rotated));
return -EINVAL; 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) const struct intel_plane_state *plane_state)
{ {
struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); 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 num, den;
unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
skl_plane_ratio(crtc_state, plane_state, &num, &den); 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)) if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
den *= 2; den *= 2;
src_w = drm_rect_width(&plane_state->uapi.src) >> 16; return DIV_ROUND_UP(pixel_rate * num, den);
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));
} }
static unsigned int static unsigned int
@ -2077,6 +2076,18 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
return 0; 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, static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_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; 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; return 0;
} }
@ -3011,7 +3031,6 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
struct intel_plane *plane; struct intel_plane *plane;
enum drm_plane_type plane_type; enum drm_plane_type plane_type;
unsigned int supported_rotations; unsigned int supported_rotations;
unsigned int possible_crtcs;
const u64 *modifiers; const u64 *modifiers;
const u32 *formats; const u32 *formats;
int num_formats; int num_formats;
@ -3066,10 +3085,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
else else
plane_type = DRM_PLANE_TYPE_OVERLAY; plane_type = DRM_PLANE_TYPE_OVERLAY;
possible_crtcs = BIT(pipe);
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
possible_crtcs, plane_funcs, 0, plane_funcs,
formats, num_formats, modifiers, formats, num_formats, modifiers,
plane_type, plane_type,
"plane %d%c", plane_id + 1, "plane %d%c", plane_id + 1,
@ -3120,7 +3137,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
{ {
struct intel_plane *plane; struct intel_plane *plane;
const struct drm_plane_funcs *plane_funcs; const struct drm_plane_funcs *plane_funcs;
unsigned long possible_crtcs;
unsigned int supported_rotations; unsigned int supported_rotations;
const u64 *modifiers; const u64 *modifiers;
const u32 *formats; const u32 *formats;
@ -3205,10 +3221,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
plane->id = PLANE_SPRITE0 + sprite; plane->id = PLANE_SPRITE0 + sprite;
plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id); plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
possible_crtcs = BIT(pipe);
ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
possible_crtcs, plane_funcs, 0, plane_funcs,
formats, num_formats, modifiers, formats, num_formats, modifiers,
DRM_PLANE_TYPE_OVERLAY, DRM_PLANE_TYPE_OVERLAY,
"sprite %c", sprite_name(pipe, sprite)); "sprite %c", sprite_name(pipe, sprite));

View File

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

View File

@ -6,8 +6,6 @@
* Manasi Navare <manasi.d.navare@intel.com> * Manasi Navare <manasi.d.navare@intel.com>
*/ */
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_display_types.h" #include "intel_display_types.h"
#include "intel_dsi.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, .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) static void vlv_dsi_add_properties(struct intel_connector *connector)
{ {
struct drm_i915_private *dev_priv = to_i915(connector->base.dev); 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( drm_connector_set_panel_orientation_with_quirk(
&connector->base, &connector->base,
vlv_dsi_get_panel_orientation(connector), intel_dsi_get_panel_orientation(connector),
connector->panel.fixed_mode->hdisplay, connector->panel.fixed_mode->hdisplay,
connector->panel.fixed_mode->vdisplay); connector->panel.fixed_mode->vdisplay);
} }

View File

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

View File

@ -67,10 +67,9 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/nospec.h> #include <linux/nospec.h>
#include <drm/i915_drm.h>
#include "gt/gen6_ppgtt.h" #include "gt/gen6_ppgtt.h"
#include "gt/intel_context.h" #include "gt/intel_context.h"
#include "gt/intel_context_param.h"
#include "gt/intel_engine_heartbeat.h" #include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_user.h" #include "gt/intel_engine_user.h"
#include "gt/intel_ring.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]) if (!e->engines[count])
continue; continue;
RCU_INIT_POINTER(e->engines[count]->gem_context, NULL);
intel_context_put(e->engines[count]); intel_context_put(e->engines[count]);
} }
kfree(e); kfree(e);
@ -256,7 +254,51 @@ static void free_engines(struct i915_gem_engines *e)
static void free_engines_rcu(struct rcu_head *rcu) 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) 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; struct i915_gem_engines *e;
enum intel_engine_id id; enum intel_engine_id id;
e = kzalloc(struct_size(e, engines, I915_NUM_ENGINES), GFP_KERNEL); e = alloc_engines(I915_NUM_ENGINES);
if (!e) if (!e)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
e->ctx = ctx;
for_each_engine(engine, gt, id) { for_each_engine(engine, gt, id) {
struct intel_context *ce; struct intel_context *ce;
@ -305,7 +345,6 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
list_del(&ctx->link); list_del(&ctx->link);
spin_unlock(&ctx->i915->gem.contexts.lock); spin_unlock(&ctx->i915->gem.contexts.lock);
free_engines(rcu_access_pointer(ctx->engines));
mutex_destroy(&ctx->engines_mutex); mutex_destroy(&ctx->engines_mutex);
if (ctx->timeline) 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) static void kill_stale_engines(struct i915_gem_context *ctx)
{ {
struct i915_gem_engines *pos, *next; 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) { 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; continue;
}
spin_unlock_irqrestore(&ctx->stale.lock, flags); spin_unlock_irq(&ctx->stale.lock);
kill_engines(pos); 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_safe_reset_next(pos, next, link);
list_del_init(&pos->link); /* decouple from FENCE_COMPLETE */ list_del_init(&pos->link); /* decouple from FENCE_COMPLETE */
i915_sw_fence_complete(&pos->fence); 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) static void kill_context(struct i915_gem_context *ctx)
{ {
kill_stale_engines(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) 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; 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); i915_gem_context_set_closed(ctx);
set_closed_name(ctx); mutex_unlock(&ctx->engines_mutex);
mutex_lock(&ctx->mutex); mutex_lock(&ctx->mutex);
set_closed_name(ctx);
vm = i915_gem_context_vm(ctx); vm = i915_gem_context_vm(ctx);
if (vm) if (vm)
i915_vm_close(vm); i915_vm_close(vm);
@ -668,23 +757,30 @@ err_free:
return ERR_PTR(err); return ERR_PTR(err);
} }
static void static int
context_apply_all(struct i915_gem_context *ctx, 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) void *data)
{ {
struct i915_gem_engines_iter it; struct i915_gem_engines_iter it;
struct intel_context *ce; struct intel_context *ce;
int err = 0;
for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
fn(ce, data); err = fn(ce, data);
if (err)
break;
}
i915_gem_context_unlock_engines(ctx); 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); i915_vm_put(ce->vm);
ce->vm = i915_vm_get(vm); ce->vm = i915_vm_get(vm);
return 0;
} }
static struct i915_address_space * static struct i915_address_space *
@ -722,9 +818,10 @@ static void __set_timeline(struct intel_timeline **dst,
intel_timeline_put(old); 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); __set_timeline(&ce->timeline, timeline);
return 0;
} }
static void __assign_timeline(struct i915_gem_context *ctx, 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) void i915_gem_driver_release__contexts(struct drm_i915_private *i915)
{ {
flush_work(&i915->gem.contexts.free_work); 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, static int gem_context_register(struct i915_gem_context *ctx,
@ -971,6 +1069,30 @@ static void cb_retire(struct i915_active *base)
kfree(cb); 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); I915_SELFTEST_DECLARE(static intel_engine_mask_t context_barrier_inject_fault);
static int context_barrier_task(struct i915_gem_context *ctx, static int context_barrier_task(struct i915_gem_context *ctx,
intel_engine_mask_t engines, 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 context_barrier_task *cb;
struct i915_gem_engines_iter it; struct i915_gem_engines_iter it;
struct i915_gem_engines *e;
struct intel_context *ce; struct intel_context *ce;
int err = 0; int err = 0;
@ -997,7 +1120,13 @@ static int context_barrier_task(struct i915_gem_context *ctx,
return err; 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; struct i915_request *rq;
if (I915_SELFTEST_ONLY(context_barrier_inject_fault & if (I915_SELFTEST_ONLY(context_barrier_inject_fault &
@ -1028,7 +1157,7 @@ static int context_barrier_task(struct i915_gem_context *ctx,
if (err) if (err)
break; break;
} }
i915_gem_context_unlock_engines(ctx); i915_sw_fence_complete(&e->fence);
cb->task = err ? NULL : task; /* caller needs to unwind instead */ cb->task = err ? NULL : task; /* caller needs to unwind instead */
cb->data = data; cb->data = data;
@ -1215,6 +1344,63 @@ out:
return err; 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 static int
user_to_context_sseu(struct drm_i915_private *i915, user_to_context_sseu(struct drm_i915_private *i915,
const struct drm_i915_gem_context_param_sseu *user, 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, [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 static int
set_engines(struct i915_gem_context *ctx, set_engines(struct i915_gem_context *ctx,
const struct drm_i915_gem_context_param *args) const struct drm_i915_gem_context_param *args)
@ -1669,14 +1784,10 @@ set_engines(struct i915_gem_context *ctx,
* first 64 engines defined here. * first 64 engines defined here.
*/ */
num_engines = (args->size - sizeof(*user)) / sizeof(*user->engines); num_engines = (args->size - sizeof(*user)) / sizeof(*user->engines);
set.engines = alloc_engines(num_engines);
set.engines = kmalloc(struct_size(set.engines, engines, num_engines),
GFP_KERNEL);
if (!set.engines) if (!set.engines)
return -ENOMEM; return -ENOMEM;
set.engines->ctx = ctx;
for (n = 0; n < num_engines; n++) { for (n = 0; n < num_engines; n++) {
struct i915_engine_class_instance ci; struct i915_engine_class_instance ci;
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
@ -1729,6 +1840,11 @@ set_engines(struct i915_gem_context *ctx,
replace: replace:
mutex_lock(&ctx->engines_mutex); 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) if (args->size)
i915_gem_context_set_user_engines(ctx); i915_gem_context_set_user_engines(ctx);
else else
@ -1737,7 +1853,7 @@ replace:
mutex_unlock(&ctx->engines_mutex); mutex_unlock(&ctx->engines_mutex);
/* Keep track of old engine sets for kill_context() */ /* Keep track of old engine sets for kill_context() */
engines_idle_release(set.engines); engines_idle_release(ctx, set.engines);
return 0; return 0;
} }
@ -1748,7 +1864,7 @@ __copy_engines(struct i915_gem_engines *e)
struct i915_gem_engines *copy; struct i915_gem_engines *copy;
unsigned int n; unsigned int n;
copy = kmalloc(struct_size(e, engines, e->num_engines), GFP_KERNEL); copy = alloc_engines(e->num_engines);
if (!copy) if (!copy)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
@ -1852,17 +1968,19 @@ set_persistence(struct i915_gem_context *ctx,
return __context_set_persistence(ctx, args->value); 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; struct i915_gem_context *ctx = arg;
if (!intel_engine_has_semaphores(ce->engine)) if (!intel_engine_has_semaphores(ce->engine))
return; return 0;
if (ctx->sched.priority >= I915_PRIORITY_NORMAL) if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
intel_context_set_use_semaphores(ce); intel_context_set_use_semaphores(ce);
else else
intel_context_clear_use_semaphores(ce); intel_context_clear_use_semaphores(ce);
return 0;
} }
static int set_priority(struct i915_gem_context *ctx, 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); ret = set_persistence(ctx, args);
break; break;
case I915_CONTEXT_PARAM_RINGSIZE:
ret = set_ringsize(ctx, args);
break;
case I915_CONTEXT_PARAM_BAN_PERIOD: case I915_CONTEXT_PARAM_BAN_PERIOD:
default: default:
ret = -EINVAL; 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); 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, static int clone_engines(struct i915_gem_context *dst,
struct i915_gem_context *src) struct i915_gem_context *src)
{ {
@ -1991,12 +2125,10 @@ static int clone_engines(struct i915_gem_context *dst,
bool user_engines; bool user_engines;
unsigned long n; unsigned long n;
clone = kmalloc(struct_size(e, engines, e->num_engines), GFP_KERNEL); clone = alloc_engines(e->num_engines);
if (!clone) if (!clone)
goto err_unlock; goto err_unlock;
clone->ctx = dst;
for (n = 0; n < e->num_engines; n++) { for (n = 0; n < e->num_engines; n++) {
struct intel_engine_cs *engine; 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); 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; clone->num_engines = n;
@ -2033,8 +2171,7 @@ static int clone_engines(struct i915_gem_context *dst,
i915_gem_context_unlock_engines(src); i915_gem_context_unlock_engines(src);
/* Serialised by constructor */ /* Serialised by constructor */
free_engines(__context_engines_static(dst)); engines_idle_release(dst, rcu_replace_pointer(dst->engines, clone, 1));
RCU_INIT_POINTER(dst->engines, clone);
if (user_engines) if (user_engines)
i915_gem_context_set_user_engines(dst); i915_gem_context_set_user_engines(dst);
else 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); args->value = i915_gem_context_is_persistent(ctx);
break; break;
case I915_CONTEXT_PARAM_RINGSIZE:
ret = get_ringsize(ctx, args);
break;
case I915_CONTEXT_PARAM_BAN_PERIOD: case I915_CONTEXT_PARAM_BAN_PERIOD:
default: default:
ret = -EINVAL; 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; const struct i915_gem_engines *e = it->engines;
struct intel_context *ctx; struct intel_context *ctx;
if (unlikely(!e))
return NULL;
do { do {
if (it->idx >= e->num_engines) if (it->idx >= e->num_engines)
return NULL; return NULL;

View File

@ -207,7 +207,6 @@ static inline void
i915_gem_engines_iter_init(struct i915_gem_engines_iter *it, i915_gem_engines_iter_init(struct i915_gem_engines_iter *it,
struct i915_gem_engines *engines) struct i915_gem_engines *engines)
{ {
GEM_BUG_ON(!engines);
it->engines = engines; it->engines = engines;
it->idx = 0; 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/slab.h>
#include <linux/swiotlb.h> #include <linux/swiotlb.h>
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_gem.h" #include "i915_gem.h"
#include "i915_gem_object.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; struct file *file;
rcu_read_lock(); rcu_read_lock();
file = i915->gem.mmap_singleton; file = READ_ONCE(i915->gem.mmap_singleton);
if (file && !get_file_rcu(file)) if (file && !get_file_rcu(file))
file = NULL; file = NULL;
rcu_read_unlock(); rcu_read_unlock();

View File

@ -11,8 +11,6 @@
#include <drm/drm_file.h> #include <drm/drm_file.h>
#include <drm/drm_device.h> #include <drm/drm_device.h>
#include <drm/i915_drm.h>
#include "display/intel_frontbuffer.h" #include "display/intel_frontbuffer.h"
#include "i915_gem_object_types.h" #include "i915_gem_object_types.h"
#include "i915_gem_gtt.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); 0);
out_request: out_request:
if (unlikely(err)) if (unlikely(err))
i915_request_skip(rq, err); i915_request_set_error_once(rq, err);
i915_request_add(rq); i915_request_add(rq);
out_batch: out_batch:
@ -196,6 +196,17 @@ out_unpin:
return err; 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 *intel_emit_vma_copy_blt(struct intel_context *ce,
struct i915_vma *src, struct i915_vma *src,
struct i915_vma *dst) 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); size = min_t(u64, rem, block_size);
GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX); 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++ = GEN9_XY_FAST_COPY_BLT_CMD | (10 - 2);
*cmd++ = BLT_DEPTH_32 | PAGE_SIZE; *cmd++ = BLT_DEPTH_32 | PAGE_SIZE;
*cmd++ = 0; *cmd++ = 0;
@ -385,7 +397,7 @@ out_unlock:
drm_gem_unlock_reservations(objs, ARRAY_SIZE(objs), &acquire); drm_gem_unlock_reservations(objs, ARRAY_SIZE(objs), &acquire);
out_request: out_request:
if (unlikely(err)) if (unlikely(err))
i915_request_skip(rq, err); i915_request_set_error_once(rq, err);
i915_request_add(rq); i915_request_add(rq);
out_batch: 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 */ /* Perma-pin (until release) the physical set of pages */
__i915_gem_object_pin_pages(obj); __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_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); mutex_unlock(&obj->mm.lock);
return 0; return 0;

View File

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

View File

@ -13,6 +13,7 @@
#include "gem/i915_gem_region.h" #include "gem/i915_gem_region.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_gem_stolen.h" #include "i915_gem_stolen.h"
#include "i915_vgpu.h"
/* /*
* The BIOS typically reserves some of the system's memory for the exclusive * 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/string.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_gem.h" #include "i915_gem.h"

View File

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

View File

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

View File

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

View File

@ -23,6 +23,9 @@ mock_context(struct drm_i915_private *i915,
INIT_LIST_HEAD(&ctx->link); INIT_LIST_HEAD(&ctx->link);
ctx->i915 = i915; ctx->i915 = i915;
spin_lock_init(&ctx->stale.lock);
INIT_LIST_HEAD(&ctx->stale.engines);
i915_gem_context_set_persistence(ctx); i915_gem_context_set_persistence(ctx);
mutex_init(&ctx->engines_mutex); 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 "gen8_ppgtt.h"
#include "i915_scatterlist.h" #include "i915_scatterlist.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "i915_pvinfo.h"
#include "i915_vgpu.h" #include "i915_vgpu.h"
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gtt.h" #include "intel_gtt.h"
@ -25,6 +26,30 @@ static u64 gen8_pde_encode(const dma_addr_t addr,
return pde; 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) static void gen8_ppgtt_notify_vgt(struct i915_ppgtt *ppgtt, bool create)
{ {
struct drm_i915_private *i915 = ppgtt->vm.i915; 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.allocate_va_range = gen8_ppgtt_alloc;
ppgtt->vm.clear_range = gen8_ppgtt_clear; ppgtt->vm.clear_range = gen8_ppgtt_clear;
ppgtt->vm.pte_encode = gen8_pte_encode;
if (intel_vgpu_active(gt->i915)) if (intel_vgpu_active(gt->i915))
gen8_ppgtt_notify_vgt(ppgtt, true); 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; return -EINTR;
if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
if (intel_context_is_banned(ce)) {
err = -EIO;
goto unlock;
}
err = ce->ops->alloc(ce); err = ce->ops->alloc(ce);
if (unlikely(err)) if (unlikely(err))
goto unlock; 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 *engine;
struct intel_engine_cs *inflight; struct intel_engine_cs *inflight;
#define intel_context_inflight(ce) ptr_mask_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((ce)->inflight, 2) #define intel_context_inflight_count(ce) ptr_unmask_bits(READ_ONCE((ce)->inflight), 2)
struct i915_address_space *vm; struct i915_address_space *vm;
struct i915_gem_context __rcu *gem_context; 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 * static inline struct i915_request *
execlists_active(const struct intel_engine_execlists *execlists) 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 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) static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
{ {
const struct engine_info *info = &intel_engines[id]; const struct engine_info *info = &intel_engines[id];
struct drm_i915_private *i915 = gt->i915;
struct intel_engine_cs *engine; struct intel_engine_cs *engine;
BUILD_BUG_ON(MAX_ENGINE_CLASS >= BIT(GEN11_ENGINE_CLASS_WIDTH)); 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->id = id;
engine->legacy_idx = INVALID_ENGINE; engine->legacy_idx = INVALID_ENGINE;
engine->mask = BIT(id); engine->mask = BIT(id);
engine->i915 = gt->i915; engine->i915 = i915;
engine->gt = gt; engine->gt = gt;
engine->uncore = gt->uncore; engine->uncore = gt->uncore;
engine->hw_id = engine->guc_id = info->hw_id; 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->class = info->class;
engine->instance = info->instance; 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 = engine->props.heartbeat_interval_ms =
CONFIG_DRM_I915_HEARTBEAT_INTERVAL; CONFIG_DRM_I915_HEARTBEAT_INTERVAL;
engine->props.max_busywait_duration_ns =
CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT;
engine->props.preempt_timeout_ms = engine->props.preempt_timeout_ms =
CONFIG_DRM_I915_PREEMPT_TIMEOUT; CONFIG_DRM_I915_PREEMPT_TIMEOUT;
engine->props.stop_timeout_ms = 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 = engine->props.timeslice_duration_ms =
CONFIG_DRM_I915_TIMESLICE_DURATION; 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); engine->context_size = intel_engine_context_size(gt, engine->class);
if (WARN_ON(engine->context_size > BIT(20))) if (WARN_ON(engine->context_size > BIT(20)))
engine->context_size = 0; engine->context_size = 0;
if (engine->context_size) 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 */ /* Nothing to do here, execute in order of dependencies */
engine->schedule = NULL; 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_class[info->class][info->instance] = engine;
gt->engine[id] = engine; gt->engine[id] = engine;
gt->i915->engine[id] = engine; i915->engine[id] = engine;
return 0; return 0;
} }
@ -1379,24 +1386,24 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine,
char hdr[160]; char hdr[160];
int len; int len;
len = snprintf(hdr, sizeof(hdr), len = scnprintf(hdr, sizeof(hdr),
"\t\tActive[%d]: ", "\t\tActive[%d]: ",
(int)(port - execlists->active)); (int)(port - execlists->active));
if (!i915_request_signaled(rq)) { if (!i915_request_signaled(rq)) {
struct intel_timeline *tl = get_timeline(rq); struct intel_timeline *tl = get_timeline(rq);
len += snprintf(hdr + len, sizeof(hdr) - len, len += scnprintf(hdr + len, sizeof(hdr) - len,
"ring:{start:%08x, hwsp:%08x, seqno:%08x, runtime:%llums}, ", "ring:{start:%08x, hwsp:%08x, seqno:%08x, runtime:%llums}, ",
i915_ggtt_offset(rq->ring->vma), i915_ggtt_offset(rq->ring->vma),
tl ? tl->hwsp_offset : 0, tl ? tl->hwsp_offset : 0,
hwsp_seqno(rq), hwsp_seqno(rq),
DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context), DIV_ROUND_CLOSEST_ULL(intel_context_get_total_runtime_ns(rq->context),
1000 * 1000)); 1000 * 1000));
if (tl) if (tl)
intel_timeline_put(tl); intel_timeline_put(tl);
} }
snprintf(hdr + len, sizeof(hdr) - len, "rq: "); scnprintf(hdr + len, sizeof(hdr) - len, "rq: ");
print_request(m, rq, hdr); print_request(m, rq, hdr);
} }
for (port = execlists->pending; (rq = *port); port++) { for (port = execlists->pending; (rq = *port); port++) {

View File

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

View File

@ -8,6 +8,8 @@
#include <asm/set_memory.h> #include <asm/set_memory.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <drm/i915_drm.h>
#include "intel_gt.h" #include "intel_gt.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_scatterlist.h" #include "i915_scatterlist.h"
@ -157,6 +159,13 @@ static void gmch_ggtt_invalidate(struct i915_ggtt *ggtt)
intel_gtt_chipset_flush(); 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) static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
{ {
writeq(pte, addr); 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 *pte =
(gen8_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE; (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); 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 i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
struct sgt_iter sgt_iter; struct sgt_iter sgt_iter;
gen8_pte_t __iomem *gtt_entries; 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; 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.set_pages = ggtt_set_pages;
ggtt->vm.vma_ops.clear_pages = clear_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); setup_private_pat(ggtt->vm.gt->uncore);

View File

@ -292,10 +292,21 @@
#define MI_STORE_URB_MEM MI_INSTR(0x2D, 0) #define MI_STORE_URB_MEM MI_INSTR(0x2D, 0)
#define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0) #define MI_CONDITIONAL_BATCH_BUFFER_END MI_INSTR(0x36, 0)
#define PIPELINE_SELECT ((0x3<<29)|(0x1<<27)|(0x1<<24)|(0x4<<16)) #define STATE_BASE_ADDRESS \
#define GFX_OP_3DSTATE_VF_STATISTICS ((0x3<<29)|(0x1<<27)|(0x0<<24)|(0xB<<16)) ((0x3 << 29) | (0x0 << 27) | (0x1 << 24) | (0x1 << 16))
#define MEDIA_VFE_STATE ((0x3<<29)|(0x2<<27)|(0x0<<24)|(0x0<<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_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_OBJECT ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x4<<16))
#define GPGPU_WALKER ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16)) #define GPGPU_WALKER ((0x3<<29)|(0x2<<27)|(0x1<<24)|(0x5<<16))
#define GFX_OP_3DSTATE_DX9_CONSTANTF_VS \ #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) 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_uc_driver_late_release(&gt->uc);
intel_gt_fini_requests(gt); intel_gt_fini_requests(gt);
intel_gt_fini_reset(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; 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) { list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) {
struct drm_i915_gem_object *obj = vma->obj; 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); i915_gem_object_put(obj);
} }
GEM_BUG_ON(!list_empty(&vm->bound_list)); GEM_BUG_ON(!list_empty(&vm->bound_list));
mutex_unlock(&vm->mutex); 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) static void tgl_setup_private_ppat(struct intel_uncore *uncore)
{ {
/* TGL doesn't support LLC or AGE settings */ /* 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) i915_vm_close(struct i915_address_space *vm)
{ {
GEM_BUG_ON(!atomic_read(&vm->open)); 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); 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_suspend(struct i915_ggtt *gtt);
void i915_ggtt_resume(struct i915_ggtt *ggtt); 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); 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); 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)); 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); 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) 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) 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); i915_request_cancel_breadcrumb(rq);
spin_unlock(&rq->lock); spin_unlock(&rq->lock);
} }
rq->engine = owner; WRITE_ONCE(rq->engine, owner);
owner->submit_request(rq); owner->submit_request(rq);
active = NULL; 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 * If we have just completed this context, the engine may now be
* idle and we want to re-enter powersaving. * 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)) i915_request_completed(rq))
intel_engine_add_retire(engine, ce->timeline); 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 i915_request * const *port, *rq;
struct intel_context *ce = NULL; struct intel_context *ce = NULL;
bool sentinel = false;
trace_ports(execlists, msg, execlists->pending); trace_ports(execlists, msg, execlists->pending);
@ -1481,6 +1482,26 @@ assert_pending_valid(const struct intel_engine_execlists *execlists,
} }
ce = rq->context; 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! */ /* Hold tightly onto the lock to prevent concurrent retires! */
if (!spin_trylock_irqsave(&rq->lock, flags)) if (!spin_trylock_irqsave(&rq->lock, flags))
continue; continue;
@ -1576,6 +1597,11 @@ static bool can_merge_ctx(const struct intel_context *prev,
return true; 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, static bool can_merge_rq(const struct i915_request *prev,
const struct i915_request *next) const struct i915_request *next)
{ {
@ -1593,7 +1619,7 @@ static bool can_merge_rq(const struct i915_request *prev,
if (i915_request_completed(next)) if (i915_request_completed(next))
return true; 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_NOPREEMPT) |
BIT(I915_FENCE_FLAG_SENTINEL)))) BIT(I915_FENCE_FLAG_SENTINEL))))
return false; return false;
@ -1601,6 +1627,7 @@ static bool can_merge_rq(const struct i915_request *prev,
if (!can_merge_ctx(prev->context, next->context)) if (!can_merge_ctx(prev->context, next->context))
return false; return false;
GEM_BUG_ON(i915_seqno_passed(prev->fence.seqno, next->fence.seqno));
return true; return true;
} }
@ -1651,17 +1678,6 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve,
spin_unlock(&old->breadcrumbs.irq_lock); 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__) \ #define for_each_waiter(p__, rq__) \
list_for_each_entry_lockless(p__, \ list_for_each_entry_lockless(p__, \
&(rq__)->sched.waiters_list, \ &(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)) if (!intel_engine_has_timeslices(engine))
return false; return false;
if (list_is_last(&rq->sched.link, &engine->active.requests)) hint = engine->execlists.queue_priority_hint;
return false; if (!list_is_last(&rq->sched.link, &engine->active.requests))
hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
hint = max(rq_prio(list_next_entry(rq, sched.link)),
engine->execlists.queue_priority_hint);
return hint >= effective_prio(rq); return hint >= effective_prio(rq);
} }
@ -1762,12 +1776,13 @@ timeslice(const struct intel_engine_cs *engine)
static unsigned long static unsigned long
active_timeslice(const struct intel_engine_cs *engine) 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)) if (!rq || i915_request_completed(rq))
return 0; return 0;
if (engine->execlists.switch_priority_hint < effective_prio(rq)) if (READ_ONCE(execlists->switch_priority_hint) < effective_prio(rq))
return 0; return 0;
return timeslice(engine); 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)); 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) static void record_preemption(struct intel_engine_execlists *execlists)
{ {
(void)I915_SELFTEST_ONLY(execlists->preempt_hang.count++); (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) if (!rq)
return 0; 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); 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)) if (!intel_engine_has_preempt_reset(engine))
return; return;
set_timer_ms(&engine->execlists.preempt, 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) 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 intel_engine_execlists * const execlists = &engine->execlists;
struct i915_request **port = execlists->pending; struct i915_request **port = execlists->pending;
struct i915_request ** const last_port = port + execlists->port_mask; struct i915_request ** const last_port = port + execlists->port_mask;
struct i915_request * const *active;
struct i915_request *last; struct i915_request *last;
struct rb_node *rb; struct rb_node *rb;
bool submit = false; 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 * i.e. we will retrigger preemption following the ack in case
* of trouble. * of trouble.
*/ */
last = last_active(execlists); active = READ_ONCE(execlists->active);
while ((last = *active) && i915_request_completed(last))
active++;
if (last) { if (last) {
if (need_preempt(engine, last, rb)) { if (need_preempt(engine, last, rb)) {
ENGINE_TRACE(engine, 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 * Even if ELSP[1] is occupied and not worthy
* of timeslices, our queue might be. * of timeslices, our queue might be.
*/ */
if (!execlists->timer.expires && start_timeslice(engine);
need_timeslice(engine, last))
set_timer_ms(&execlists->timer,
timeslice(engine));
return; return;
} }
} }
@ -1983,7 +2012,8 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
if (last && !can_merge_rq(last, rq)) { if (last && !can_merge_rq(last, rq)) {
spin_unlock(&ve->base.active.lock); spin_unlock(&ve->base.active.lock);
return; /* leave this for another */ start_timeslice(engine);
return; /* leave this for another sibling */
} }
ENGINE_TRACE(engine, ENGINE_TRACE(engine,
@ -1995,13 +2025,14 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
"", "",
yesno(engine != ve->siblings[0])); yesno(engine != ve->siblings[0]));
ve->request = NULL; WRITE_ONCE(ve->request, NULL);
ve->base.execlists.queue_priority_hint = INT_MIN; WRITE_ONCE(ve->base.execlists.queue_priority_hint,
INT_MIN);
rb_erase_cached(rb, &execlists->virtual); rb_erase_cached(rb, &execlists->virtual);
RB_CLEAR_NODE(rb); RB_CLEAR_NODE(rb);
GEM_BUG_ON(!(rq->execution_mask & engine->mask)); GEM_BUG_ON(!(rq->execution_mask & engine->mask));
rq->engine = engine; WRITE_ONCE(rq->engine, engine);
if (engine != ve->siblings[0]) { if (engine != ve->siblings[0]) {
u32 *regs = ve->context.lrc_reg_state; u32 *regs = ve->context.lrc_reg_state;
@ -2121,6 +2152,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
GEM_BUG_ON(last && GEM_BUG_ON(last &&
!can_merge_ctx(last->context, !can_merge_ctx(last->context,
rq->context)); rq->context));
GEM_BUG_ON(last &&
i915_seqno_passed(last->fence.seqno,
rq->fence.seqno));
submit = true; submit = true;
last = rq; last = rq;
@ -2159,7 +2193,7 @@ done:
* Skip if we ended up with exactly the same set of requests, * Skip if we ended up with exactly the same set of requests,
* e.g. trying to timeslice a pair of ordered contexts * 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))) { (port - execlists->pending + 1) * sizeof(*port))) {
do do
execlists_schedule_out(fetch_and_zero(port)); execlists_schedule_out(fetch_and_zero(port));
@ -2170,7 +2204,7 @@ done:
clear_ports(port + 1, last_port - port); clear_ports(port + 1, last_port - port);
execlists_submit_ports(engine); execlists_submit_ports(engine);
set_preempt_timeout(engine); set_preempt_timeout(engine, *active);
} else { } else {
skip_submit: skip_submit:
ring_set_paused(engine, 0); ring_set_paused(engine, 0);
@ -2191,6 +2225,7 @@ cancel_port_requests(struct intel_engine_execlists * const execlists)
execlists_schedule_out(*port); execlists_schedule_out(*port);
clear_ports(execlists->inflight, ARRAY_SIZE(execlists->inflight)); clear_ports(execlists->inflight, ARRAY_SIZE(execlists->inflight));
smp_wmb(); /* complete the seqlock for execlists_active() */
WRITE_ONCE(execlists->active, execlists->inflight); 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 */ /* Point active to the new ELSP; prevent overwriting */
WRITE_ONCE(execlists->active, execlists->pending); WRITE_ONCE(execlists->active, execlists->pending);
smp_wmb(); /* notify execlists_active() */
/* cancel old inflight, prepare for switch */ /* cancel old inflight, prepare for switch */
trace_ports(execlists, "preempted", old); trace_ports(execlists, "preempted", old);
@ -2352,11 +2388,12 @@ static void process_csb(struct intel_engine_cs *engine)
execlists_schedule_out(*old++); execlists_schedule_out(*old++);
/* switch pending to inflight */ /* switch pending to inflight */
WRITE_ONCE(execlists->active, memcpy(execlists->inflight,
memcpy(execlists->inflight, execlists->pending,
execlists->pending, execlists_num_ports(execlists) *
execlists_num_ports(execlists) * sizeof(*execlists->pending));
sizeof(*execlists->pending))); smp_wmb(); /* complete the seqlock */
WRITE_ONCE(execlists->active, execlists->inflight);
WRITE_ONCE(execlists->pending[0], NULL); WRITE_ONCE(execlists->pending[0], NULL);
} else { } else {
@ -2579,6 +2616,10 @@ static void __execlists_unhold(struct i915_request *rq)
struct i915_request *w = struct i915_request *w =
container_of(p->waiter, typeof(*w), sched); 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) if (w->engine != rq->engine)
continue; 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_START] = i915_ggtt_offset(ring->vma);
regs[CTX_RING_HEAD] = head; regs[CTX_RING_HEAD] = head;
regs[CTX_RING_TAIL] = ring->tail; regs[CTX_RING_TAIL] = ring->tail;
regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID;
/* RPCS */ /* RPCS */
if (engine->class == RENDER_CLASS) { if (engine->class == RENDER_CLASS) {
@ -3636,9 +3678,6 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
if (!rq) if (!rq)
goto unwind; 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; ce = rq->context;
GEM_BUG_ON(!i915_vma_is_pinned(ce->state)); 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; 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! */ /* Context has requests still in-flight; it should not be idle! */
GEM_BUG_ON(i915_active_is_idle(&ce->active)); GEM_BUG_ON(i915_active_is_idle(&ce->active));
rq = active_request(ce->timeline, rq); rq = active_request(ce->timeline, rq);
head = intel_ring_wrap(ce->ring, rq->head); head = intel_ring_wrap(ce->ring, rq->head);
GEM_BUG_ON(head == ce->ring->tail); 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) 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. */ /* 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) 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); *cs++ = preparser_disable(false);
intel_ring_advance(request, cs); 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; return 0;
@ -4877,7 +4903,7 @@ static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
mask = rq->execution_mask; mask = rq->execution_mask;
if (unlikely(!mask)) { if (unlikely(!mask)) {
/* Invalid selection, submit to a random engine in error */ /* 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; 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) static void virtual_submission_tasklet(unsigned long data)
{ {
struct virtual_engine * const ve = (struct virtual_engine *)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; intel_engine_mask_t mask;
unsigned int n; unsigned int n;
@ -5287,11 +5313,15 @@ void intel_execlists_show_requests(struct intel_engine_cs *engine,
show_request(m, last, "\t\tE "); show_request(m, last, "\t\tE ");
} }
last = NULL; if (execlists->switch_priority_hint != INT_MIN)
count = 0; drm_printf(m, "\t\tSwitch priority hint: %d\n",
READ_ONCE(execlists->switch_priority_hint));
if (execlists->queue_priority_hint != INT_MIN) if (execlists->queue_priority_hint != INT_MIN)
drm_printf(m, "\t\tQueue priority hint: %d\n", 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)) { for (rb = rb_first_cached(&execlists->queue); rb; rb = rb_next(rb)) {
struct i915_priolist *p = rb_entry(rb, typeof(*p), node); struct i915_priolist *p = rb_entry(rb, typeof(*p), node);
int i; int i;

View File

@ -7,6 +7,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_vgpu.h"
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gt_pm.h" #include "intel_gt_pm.h"
#include "intel_rc6.h" #include "intel_rc6.h"
@ -319,10 +320,10 @@ static int vlv_rc6_init(struct intel_rc6 *rc6)
return PTR_ERR(pctx); return PTR_ERR(pctx);
} }
GEM_BUG_ON(range_overflows_t(u64, GEM_BUG_ON(range_overflows_end_t(u64,
i915->dsm.start, i915->dsm.start,
pctx->stolen->start, pctx->stolen->start,
U32_MAX)); U32_MAX));
pctx_paddr = i915->dsm.start + pctx->stolen->start; pctx_paddr = i915->dsm.start + pctx->stolen->start;
intel_uncore_write(uncore, VLV_PCBR, pctx_paddr); 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); lockdep_assert_held(&engine->active.lock);
list_for_each_entry_continue(rq, &engine->active.requests, sched.link) list_for_each_entry_continue(rq, &engine->active.requests, sched.link)
if (rq->context == hung_ctx) if (rq->context == hung_ctx) {
i915_request_skip(rq, -EIO); i915_request_set_error_once(rq, -EIO);
__i915_request_skip(rq);
}
} }
static void client_mark_guilty(struct i915_gem_context *ctx, bool banned) 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; ctx = NULL;
rcu_read_unlock(); rcu_read_unlock();
if (!ctx) if (!ctx)
return false; return intel_context_is_banned(rq->context);
if (i915_gem_context_is_closed(ctx)) {
intel_context_set_banned(rq->context);
banned = true;
goto out;
}
atomic_inc(&ctx->guilty_count); 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 */ rcu_read_lock(); /* protect the GEM context */
if (guilty) { if (guilty) {
i915_request_skip(rq, -EIO); i915_request_set_error_once(rq, -EIO);
__i915_request_skip(rq);
if (mark_guilty(rq)) if (mark_guilty(rq))
engine_skip_context(rq); engine_skip_context(rq);
} else { } else {
dma_fence_set_error(&rq->fence, -EAGAIN); i915_request_set_error_once(rq, -EAGAIN);
mark_innocent(rq); mark_innocent(rq);
} }
rcu_read_unlock(); rcu_read_unlock();
@ -785,7 +782,7 @@ static void nop_submit_request(struct i915_request *request)
unsigned long flags; unsigned long flags;
RQ_TRACE(request, "-EIO\n"); 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); spin_lock_irqsave(&engine->active.lock, flags);
__i915_request_submit(request); __i915_request_submit(request);

View File

@ -29,11 +29,10 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <drm/i915_drm.h>
#include "gem/i915_gem_context.h" #include "gem/i915_gem_context.h"
#include "gen6_ppgtt.h" #include "gen6_ppgtt.h"
#include "gen7_renderclear.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "intel_context.h" #include "intel_context.h"
@ -897,9 +896,7 @@ static void reset_cancel(struct intel_engine_cs *engine)
/* Mark all submitted requests as skipped. */ /* Mark all submitted requests as skipped. */
list_for_each_entry(request, &engine->active.requests, sched.link) { list_for_each_entry(request, &engine->active.requests, sched.link) {
if (!i915_request_signaled(request)) i915_request_set_error_once(request, -EIO);
dma_fence_set_error(&request->fence, -EIO);
i915_request_mark_complete(request); 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); 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 drm_i915_private *i915 = rq->i915;
struct intel_engine_cs *engine = rq->engine; 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_NOOP;
*cs++ = MI_SET_CONTEXT; *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 * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
* WaMiSetContext_Hang:snb,ivb,vlv * 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); 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) static int switch_context(struct i915_request *rq)
{ {
struct intel_engine_cs *engine = rq->engine;
struct intel_context *ce = rq->context; struct intel_context *ce = rq->context;
void **residuals = NULL;
int ret; int ret;
GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); 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)); ret = switch_mm(rq, vm_alias(ce->vm));
if (ret) if (ret)
return ret; return ret;
@ -1564,7 +1606,7 @@ static int switch_context(struct i915_request *rq)
if (ce->state) { if (ce->state) {
u32 flags; u32 flags;
GEM_BUG_ON(rq->engine->id != RCS0); GEM_BUG_ON(engine->id != RCS0);
/* For resource streamer on HSW+ and power context elsewhere */ /* For resource streamer on HSW+ and power context elsewhere */
BUILD_BUG_ON(HSW_MI_RS_SAVE_STATE_EN != MI_SAVE_EXT_STATE_EN); 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 else
flags |= MI_RESTORE_INHIBIT; flags |= MI_RESTORE_INHIBIT;
ret = mi_set_context(rq, flags); ret = mi_set_context(rq, ce, flags);
if (ret) if (ret)
return ret; return ret;
} }
@ -1585,6 +1627,20 @@ static int switch_context(struct i915_request *rq)
if (ret) if (ret)
return 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; return 0;
} }
@ -1769,6 +1825,11 @@ static void ring_release(struct intel_engine_cs *engine)
intel_engine_cleanup_common(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_unpin(engine->legacy.ring);
intel_ring_put(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; 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) int intel_ring_submission_setup(struct intel_engine_cs *engine)
{ {
struct intel_timeline *timeline; 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); 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! */ /* Finally, take ownership and responsibility for cleanup! */
engine->release = ring_release; engine->release = ring_release;
return 0; return 0;
err_ring_unpin:
intel_ring_unpin(ring);
err_ring: err_ring:
intel_ring_put(ring); intel_ring_put(ring);
err_timeline_unpin: err_timeline_unpin:
@ -1984,3 +2111,7 @@ err:
intel_engine_cleanup_common(engine); intel_engine_cleanup_common(engine);
return err; 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 * Copyright © 2019 Intel Corporation
*/ */
#include <drm/i915_drm.h>
#include "i915_drv.h" #include "i915_drv.h"
#include "intel_gt.h" #include "intel_gt.h"
#include "intel_gt_irq.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) if (val < rps->max_freq_softlimit)
mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD; 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); 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) static void rps_enable_interrupts(struct intel_rps *rps)
{ {
struct intel_gt *gt = rps_to_gt(rps); struct intel_gt *gt = rps_to_gt(rps);
u32 events;
rps_reset_ei(rps); rps_reset_ei(rps);
if (IS_VALLEYVIEW(gt->i915)) if (IS_VALLEYVIEW(gt->i915))
/* WaGsvRC0ResidencyMethod:vlv */ /* WaGsvRC0ResidencyMethod:vlv */
rps->pm_events = GEN6_PM_RP_UP_EI_EXPIRED; events = GEN6_PM_RP_UP_EI_EXPIRED;
else else
rps->pm_events = (GEN6_PM_RP_UP_THRESHOLD | events = (GEN6_PM_RP_UP_THRESHOLD |
GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_THRESHOLD |
GEN6_PM_RP_DOWN_TIMEOUT); GEN6_PM_RP_DOWN_TIMEOUT);
WRITE_ONCE(rps->pm_events, events);
spin_lock_irq(&gt->irq_lock); spin_lock_irq(&gt->irq_lock);
gen6_gt_pm_enable_irq(gt, rps->pm_events); gen6_gt_pm_enable_irq(gt, rps->pm_events);
spin_unlock_irq(&gt->irq_lock); 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); 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)); set(gt->uncore, GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u));
spin_lock_irq(&gt->irq_lock); 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); mutex_lock(&rps->power.mutex);
if (interactive) { if (interactive) {
if (!rps->power.interactive++ && rps->active) if (!rps->power.interactive++ && READ_ONCE(rps->active))
rps_set_power(rps, HIGH_POWER); rps_set_power(rps, HIGH_POWER);
} else { } else {
GEM_BUG_ON(!rps->power.interactive); 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. * performance, jump directly to RPe as our starting frequency.
*/ */
mutex_lock(&rps->lock); mutex_lock(&rps->lock);
rps->active = true;
WRITE_ONCE(rps->active, true);
freq = max(rps->cur_freq, rps->efficient_freq), freq = max(rps->cur_freq, rps->efficient_freq),
freq = clamp(freq, rps->min_freq_softlimit, rps->max_freq_softlimit); freq = clamp(freq, rps->min_freq_softlimit, rps->max_freq_softlimit);
intel_rps_set(rps, freq); intel_rps_set(rps, freq);
rps->last_adj = 0; rps->last_adj = 0;
mutex_unlock(&rps->lock); mutex_unlock(&rps->lock);
if (INTEL_GEN(rps_to_i915(rps)) >= 6) 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) if (INTEL_GEN(i915) >= 6)
rps_disable_interrupts(rps); rps_disable_interrupts(rps);
rps->active = false; WRITE_ONCE(rps->active, false);
if (rps->last_freq <= rps->idle_freq) if (rps->last_freq <= rps->idle_freq)
return; return;
@ -767,10 +774,10 @@ void intel_rps_park(struct intel_rps *rps)
void intel_rps_boost(struct i915_request *rq) 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; unsigned long flags;
if (i915_request_signaled(rq) || !rps->active) if (i915_request_signaled(rq) || !READ_ONCE(rps->active))
return; return;
/* Serializes with i915_request_retire() */ /* Serializes with i915_request_retire() */
@ -1453,12 +1460,12 @@ static void rps_work(struct work_struct *work)
u32 pm_iir = 0; u32 pm_iir = 0;
spin_lock_irq(&gt->irq_lock); 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); client_boost = atomic_read(&rps->num_waiters);
spin_unlock_irq(&gt->irq_lock); spin_unlock_irq(&gt->irq_lock);
/* Make sure we didn't queue anything we're not going to process. */ /* 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; goto out;
mutex_lock(&rps->lock); 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) void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
{ {
struct intel_gt *gt = rps_to_gt(rps); 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); 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); schedule_work(&rps->work);
spin_unlock(&gt->irq_lock); 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) 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)); GEM_BUG_ON(ptr_test_bit(cl->vaddr, CACHELINE_FREE));
cl->vaddr = ptr_set_bit(cl->vaddr, CACHELINE_FREE); cl->vaddr = ptr_set_bit(cl->vaddr, CACHELINE_FREE);
if (i915_active_is_idle(&cl->active)) i915_active_release(&cl->active);
__idle_cacheline_free(cl);
} }
int intel_timeline_init(struct intel_timeline *timeline, 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 */ /* allow headerless messages for preemptible GPGPU context */
WA_SET_BIT_MASKED(GEN10_SAMPLER_MODE, WA_SET_BIT_MASKED(GEN10_SAMPLER_MODE,
GEN11_SAMPLER_ENABLE_HEADLESS_MSG); 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, static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal) 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, WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3,
GEN12_DISABLE_CPS_AWARE_COLOR_PIPE); 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, wa_add(wal, FF_MODE2, FF_MODE2_TDS_TIMER_MASK,
FF_MODE2_TDS_TIMER_128, 0); 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 static void
@ -898,11 +920,6 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal)
SLICE_UNIT_LEVEL_CLKGATE, SLICE_UNIT_LEVEL_CLKGATE,
MSCUNIT_CLKGATE_DIS); MSCUNIT_CLKGATE_DIS);
/* Wa_1406680159:icl */
wa_write_or(wal,
SUBSLICE_UNIT_LEVEL_CLKGATE,
GWUNIT_CLKGATE_DIS);
/* Wa_1406838659:icl (pre-prod) */ /* Wa_1406838659:icl (pre-prod) */
if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0)) if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
wa_write_or(wal, 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, SUBSLICE_UNIT_LEVEL_CLKGATE2,
CPSSUNIT_CLKGATE_DIS); 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)) if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0))
wa_write_or(wal, wa_write_or(wal,
SLICE_UNIT_LEVEL_CLKGATE, SLICE_UNIT_LEVEL_CLKGATE,
@ -1246,6 +1263,7 @@ static void tgl_whitelist_build(struct intel_engine_cs *engine)
case RENDER_CLASS: case RENDER_CLASS:
/* /*
* WaAllowPMDepthAndInvocationCountAccessFromUMD:tgl * WaAllowPMDepthAndInvocationCountAccessFromUMD:tgl
* Wa_1408556865:tgl
* *
* This covers 4 registers which are next to one another : * This covers 4 registers which are next to one another :
* - PS_INVOCATION_COUNT * - PS_INVOCATION_COUNT
@ -1259,6 +1277,9 @@ static void tgl_whitelist_build(struct intel_engine_cs *engine)
/* Wa_1808121037:tgl */ /* Wa_1808121037:tgl */
whitelist_reg(w, GEN7_COMMON_SLICE_CHICKEN1); whitelist_reg(w, GEN7_COMMON_SLICE_CHICKEN1);
/* Wa_1806527549:tgl */
whitelist_reg(w, HIZ_CHICKEN);
break; break;
default: default:
break; 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; struct drm_i915_private *i915 = engine->i915;
if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) { if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) {
/* Wa_1606700617:tgl */ /*
wa_masked_en(wal, * Wa_1607138336:tgl
GEN9_CS_DEBUG_MODE1, * Wa_1607063988:tgl
FF_DOP_CLOCK_GATE_DISABLE); */
/* Wa_1607138336:tgl */
wa_write_or(wal, wa_write_or(wal,
GEN9_CTX_PREEMPT_REG, GEN9_CTX_PREEMPT_REG,
GEN12_DISABLE_POSH_BUSY_FF_DOP_CG); GEN12_DISABLE_POSH_BUSY_FF_DOP_CG);
/* Wa_1607030317:tgl */ /*
/* Wa_1607186500:tgl */ * Wa_1607030317:tgl
/* Wa_1607297627: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, wa_masked_en(wal,
GEN6_RC_SLEEP_PSMI_CONTROL, GEN6_RC_SLEEP_PSMI_CONTROL,
GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE | 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, GEN7_FF_THREAD_MODE,
GEN12_FF_TESSELATION_DOP_GATE_DISABLE); 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_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, wa_masked_en(wal,
GEN7_ROW_CHICKEN2, GEN9_CS_DEBUG_MODE1,
GEN12_DISABLE_EARLY_READ); FF_DOP_CLOCK_GATE_DISABLE);
} }
if (IS_GEN(i915, 11)) { 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_SCRATCH2,
GEN11_COHERENT_PARTIAL_WRITE_MERGE_ENABLE, GEN11_COHERENT_PARTIAL_WRITE_MERGE_ENABLE,
0); 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)) { if (IS_GEN_RANGE(i915, 9, 12)) {
/* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl */ /* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl,tgl */
wa_masked_en(wal, wa_masked_en(wal,
GEN7_FF_SLICE_CS_CHICKEN1, GEN7_FF_SLICE_CS_CHICKEN1,
GEN9_FFSC_PERCTX_PREEMPT_CTRL); GEN9_FFSC_PERCTX_PREEMPT_CTRL);
@ -1595,15 +1665,34 @@ err_obj:
return ERR_PTR(err); 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) 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 * which only controls CPU initiated MMIO. Routing does not
* work for CS access so we cannot verify them on this path. * work for CS access so we cannot verify them on this path.
*/ */
if (INTEL_GEN(i915) >= 8 && (offset >= 0xb000 && offset <= 0xb4ff)) for (i = 0; mcr_ranges_gen8[i].start; i++)
return true; if (offset >= mcr_ranges_gen8[i].start &&
offset <= mcr_ranges_gen8[i].end)
return true;
return false; 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. */ /* Mark all submitted requests as skipped. */
list_for_each_entry(request, &engine->active.requests, sched.link) { list_for_each_entry(request, &engine->active.requests, sched.link) {
if (!i915_request_signaled(request)) i915_request_set_error_once(request, -EIO);
dma_fence_set_error(&request->fence, -EIO);
i915_request_mark_complete(request); i915_request_mark_complete(request);
} }

View File

@ -142,6 +142,24 @@ out:
return err; 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) static int live_idle_flush(void *arg)
{ {
struct intel_gt *gt = 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 */ /* Check that we can flush the idle barriers */
for_each_engine(engine, gt, id) { 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); err = __live_idle_pulse(engine, intel_engine_flush_barriers);
intel_engine_pm_put(engine); engine_heartbeat_enable(engine, heartbeat);
if (err) if (err)
break; break;
} }
@ -172,9 +192,11 @@ static int live_idle_pulse(void *arg)
/* Check that heartbeat pulses flush the idle barriers */ /* Check that heartbeat pulses flush the idle barriers */
for_each_engine(engine, gt, id) { 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); err = __live_idle_pulse(engine, intel_engine_pulse);
intel_engine_pm_put(engine); engine_heartbeat_enable(engine, heartbeat);
if (err && err != -ENODEV) if (err && err != -ENODEV)
break; break;

View File

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

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