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:
commit
9001b17698
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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")) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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"
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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__ */
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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(>->uc);
|
intel_uc_driver_late_release(>->uc);
|
||||||
intel_gt_fini_requests(gt);
|
intel_gt_fini_requests(gt);
|
||||||
intel_gt_fini_reset(gt);
|
intel_gt_fini_reset(gt);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(>->irq_lock);
|
spin_lock_irq(>->irq_lock);
|
||||||
gen6_gt_pm_enable_irq(gt, rps->pm_events);
|
gen6_gt_pm_enable_irq(gt, rps->pm_events);
|
||||||
spin_unlock_irq(>->irq_lock);
|
spin_unlock_irq(>->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(>->irq_lock);
|
spin_lock_irq(>->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(>->irq_lock);
|
spin_lock_irq(>->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(>->irq_lock);
|
spin_unlock_irq(>->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(>->irq_lock);
|
spin_lock(>->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(>->irq_lock);
|
spin_unlock(>->irq_lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue